00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "postgres.h"
00015
00016 #include "access/htup_details.h"
00017 #include "catalog/pg_operator.h"
00018 #include "catalog/pg_type.h"
00019 #include "executor/executor.h"
00020 #include "miscadmin.h"
00021 #include "nodes/makefuncs.h"
00022 #include "nodes/nodeFuncs.h"
00023 #include "optimizer/clauses.h"
00024 #include "optimizer/cost.h"
00025 #include "optimizer/planmain.h"
00026 #include "optimizer/planner.h"
00027 #include "optimizer/prep.h"
00028 #include "optimizer/subselect.h"
00029 #include "optimizer/var.h"
00030 #include "parser/parse_relation.h"
00031 #include "rewrite/rewriteManip.h"
00032 #include "utils/builtins.h"
00033 #include "utils/lsyscache.h"
00034 #include "utils/syscache.h"
00035
00036
00037 typedef struct convert_testexpr_context
00038 {
00039 PlannerInfo *root;
00040 List *subst_nodes;
00041 } convert_testexpr_context;
00042
00043 typedef struct process_sublinks_context
00044 {
00045 PlannerInfo *root;
00046 bool isTopQual;
00047 } process_sublinks_context;
00048
00049 typedef struct finalize_primnode_context
00050 {
00051 PlannerInfo *root;
00052 Bitmapset *paramids;
00053 } finalize_primnode_context;
00054
00055
00056 static Node *build_subplan(PlannerInfo *root, Plan *plan, PlannerInfo *subroot,
00057 List *plan_params,
00058 SubLinkType subLinkType, Node *testexpr,
00059 bool adjust_testexpr, bool unknownEqFalse);
00060 static List *generate_subquery_params(PlannerInfo *root, List *tlist,
00061 List **paramIds);
00062 static List *generate_subquery_vars(PlannerInfo *root, List *tlist,
00063 Index varno);
00064 static Node *convert_testexpr(PlannerInfo *root,
00065 Node *testexpr,
00066 List *subst_nodes);
00067 static Node *convert_testexpr_mutator(Node *node,
00068 convert_testexpr_context *context);
00069 static bool subplan_is_hashable(Plan *plan);
00070 static bool testexpr_is_hashable(Node *testexpr);
00071 static bool hash_ok_operator(OpExpr *expr);
00072 static bool simplify_EXISTS_query(Query *query);
00073 static Query *convert_EXISTS_to_ANY(PlannerInfo *root, Query *subselect,
00074 Node **testexpr, List **paramIds);
00075 static Node *replace_correlation_vars_mutator(Node *node, PlannerInfo *root);
00076 static Node *process_sublinks_mutator(Node *node,
00077 process_sublinks_context *context);
00078 static Bitmapset *finalize_plan(PlannerInfo *root,
00079 Plan *plan,
00080 Bitmapset *valid_params,
00081 Bitmapset *scan_params);
00082 static bool finalize_primnode(Node *node, finalize_primnode_context *context);
00083
00084
00085
00086
00087
00088
00089
00090 static int
00091 assign_param_for_var(PlannerInfo *root, Var *var)
00092 {
00093 ListCell *ppl;
00094 PlannerParamItem *pitem;
00095 Index levelsup;
00096
00097
00098 for (levelsup = var->varlevelsup; levelsup > 0; levelsup--)
00099 root = root->parent_root;
00100
00101
00102 foreach(ppl, root->plan_params)
00103 {
00104 pitem = (PlannerParamItem *) lfirst(ppl);
00105 if (IsA(pitem->item, Var))
00106 {
00107 Var *pvar = (Var *) pitem->item;
00108
00109
00110
00111
00112
00113 if (pvar->varno == var->varno &&
00114 pvar->varattno == var->varattno &&
00115 pvar->vartype == var->vartype &&
00116 pvar->vartypmod == var->vartypmod &&
00117 pvar->varcollid == var->varcollid &&
00118 pvar->varnoold == var->varnoold &&
00119 pvar->varoattno == var->varoattno)
00120 return pitem->paramId;
00121 }
00122 }
00123
00124
00125 var = (Var *) copyObject(var);
00126 var->varlevelsup = 0;
00127
00128 pitem = makeNode(PlannerParamItem);
00129 pitem->item = (Node *) var;
00130 pitem->paramId = root->glob->nParamExec++;
00131
00132 root->plan_params = lappend(root->plan_params, pitem);
00133
00134 return pitem->paramId;
00135 }
00136
00137
00138
00139
00140
00141 static Param *
00142 replace_outer_var(PlannerInfo *root, Var *var)
00143 {
00144 Param *retval;
00145 int i;
00146
00147 Assert(var->varlevelsup > 0 && var->varlevelsup < root->query_level);
00148
00149
00150 i = assign_param_for_var(root, var);
00151
00152 retval = makeNode(Param);
00153 retval->paramkind = PARAM_EXEC;
00154 retval->paramid = i;
00155 retval->paramtype = var->vartype;
00156 retval->paramtypmod = var->vartypmod;
00157 retval->paramcollid = var->varcollid;
00158 retval->location = var->location;
00159
00160 return retval;
00161 }
00162
00163
00164
00165
00166
00167
00168
00169
00170 Param *
00171 assign_nestloop_param_var(PlannerInfo *root, Var *var)
00172 {
00173 Param *retval;
00174 int i;
00175
00176 Assert(var->varlevelsup == 0);
00177
00178 i = assign_param_for_var(root, var);
00179
00180 retval = makeNode(Param);
00181 retval->paramkind = PARAM_EXEC;
00182 retval->paramid = i;
00183 retval->paramtype = var->vartype;
00184 retval->paramtypmod = var->vartypmod;
00185 retval->paramcollid = var->varcollid;
00186 retval->location = var->location;
00187
00188 return retval;
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198 static int
00199 assign_param_for_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv)
00200 {
00201 ListCell *ppl;
00202 PlannerParamItem *pitem;
00203 Index levelsup;
00204
00205
00206 for (levelsup = phv->phlevelsup; levelsup > 0; levelsup--)
00207 root = root->parent_root;
00208
00209
00210 foreach(ppl, root->plan_params)
00211 {
00212 pitem = (PlannerParamItem *) lfirst(ppl);
00213 if (IsA(pitem->item, PlaceHolderVar))
00214 {
00215 PlaceHolderVar *pphv = (PlaceHolderVar *) pitem->item;
00216
00217
00218 if (pphv->phid == phv->phid)
00219 return pitem->paramId;
00220 }
00221 }
00222
00223
00224 phv = (PlaceHolderVar *) copyObject(phv);
00225 if (phv->phlevelsup != 0)
00226 {
00227 IncrementVarSublevelsUp((Node *) phv, -((int) phv->phlevelsup), 0);
00228 Assert(phv->phlevelsup == 0);
00229 }
00230
00231 pitem = makeNode(PlannerParamItem);
00232 pitem->item = (Node *) phv;
00233 pitem->paramId = root->glob->nParamExec++;
00234
00235 root->plan_params = lappend(root->plan_params, pitem);
00236
00237 return pitem->paramId;
00238 }
00239
00240
00241
00242
00243
00244
00245
00246 static Param *
00247 replace_outer_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv)
00248 {
00249 Param *retval;
00250 int i;
00251
00252 Assert(phv->phlevelsup > 0 && phv->phlevelsup < root->query_level);
00253
00254
00255 i = assign_param_for_placeholdervar(root, phv);
00256
00257 retval = makeNode(Param);
00258 retval->paramkind = PARAM_EXEC;
00259 retval->paramid = i;
00260 retval->paramtype = exprType((Node *) phv->phexpr);
00261 retval->paramtypmod = exprTypmod((Node *) phv->phexpr);
00262 retval->paramcollid = exprCollation((Node *) phv->phexpr);
00263 retval->location = -1;
00264
00265 return retval;
00266 }
00267
00268
00269
00270
00271
00272
00273
00274 Param *
00275 assign_nestloop_param_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv)
00276 {
00277 Param *retval;
00278 int i;
00279
00280 Assert(phv->phlevelsup == 0);
00281
00282 i = assign_param_for_placeholdervar(root, phv);
00283
00284 retval = makeNode(Param);
00285 retval->paramkind = PARAM_EXEC;
00286 retval->paramid = i;
00287 retval->paramtype = exprType((Node *) phv->phexpr);
00288 retval->paramtypmod = exprTypmod((Node *) phv->phexpr);
00289 retval->paramcollid = exprCollation((Node *) phv->phexpr);
00290 retval->location = -1;
00291
00292 return retval;
00293 }
00294
00295
00296
00297
00298
00299 static Param *
00300 replace_outer_agg(PlannerInfo *root, Aggref *agg)
00301 {
00302 Param *retval;
00303 PlannerParamItem *pitem;
00304 Index levelsup;
00305
00306 Assert(agg->agglevelsup > 0 && agg->agglevelsup < root->query_level);
00307
00308
00309 for (levelsup = agg->agglevelsup; levelsup > 0; levelsup--)
00310 root = root->parent_root;
00311
00312
00313
00314
00315
00316 agg = (Aggref *) copyObject(agg);
00317 IncrementVarSublevelsUp((Node *) agg, -((int) agg->agglevelsup), 0);
00318 Assert(agg->agglevelsup == 0);
00319
00320 pitem = makeNode(PlannerParamItem);
00321 pitem->item = (Node *) agg;
00322 pitem->paramId = root->glob->nParamExec++;
00323
00324 root->plan_params = lappend(root->plan_params, pitem);
00325
00326 retval = makeNode(Param);
00327 retval->paramkind = PARAM_EXEC;
00328 retval->paramid = pitem->paramId;
00329 retval->paramtype = agg->aggtype;
00330 retval->paramtypmod = -1;
00331 retval->paramcollid = agg->aggcollid;
00332 retval->location = agg->location;
00333
00334 return retval;
00335 }
00336
00337
00338
00339
00340
00341
00342
00343
00344 static Param *
00345 generate_new_param(PlannerInfo *root, Oid paramtype, int32 paramtypmod,
00346 Oid paramcollation)
00347 {
00348 Param *retval;
00349
00350 retval = makeNode(Param);
00351 retval->paramkind = PARAM_EXEC;
00352 retval->paramid = root->glob->nParamExec++;
00353 retval->paramtype = paramtype;
00354 retval->paramtypmod = paramtypmod;
00355 retval->paramcollid = paramcollation;
00356 retval->location = -1;
00357
00358 return retval;
00359 }
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 int
00370 SS_assign_special_param(PlannerInfo *root)
00371 {
00372 return root->glob->nParamExec++;
00373 }
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384 static void
00385 get_first_col_type(Plan *plan, Oid *coltype, int32 *coltypmod,
00386 Oid *colcollation)
00387 {
00388
00389 if (plan->targetlist)
00390 {
00391 TargetEntry *tent = (TargetEntry *) linitial(plan->targetlist);
00392
00393 Assert(IsA(tent, TargetEntry));
00394 if (!tent->resjunk)
00395 {
00396 *coltype = exprType((Node *) tent->expr);
00397 *coltypmod = exprTypmod((Node *) tent->expr);
00398 *colcollation = exprCollation((Node *) tent->expr);
00399 return;
00400 }
00401 }
00402 *coltype = VOIDOID;
00403 *coltypmod = -1;
00404 *colcollation = InvalidOid;
00405 }
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424 static Node *
00425 make_subplan(PlannerInfo *root, Query *orig_subquery, SubLinkType subLinkType,
00426 Node *testexpr, bool isTopQual)
00427 {
00428 Query *subquery;
00429 bool simple_exists = false;
00430 double tuple_fraction;
00431 Plan *plan;
00432 PlannerInfo *subroot;
00433 List *plan_params;
00434 Node *result;
00435
00436
00437
00438
00439
00440
00441
00442 subquery = (Query *) copyObject(orig_subquery);
00443
00444
00445
00446
00447 if (subLinkType == EXISTS_SUBLINK)
00448 simple_exists = simplify_EXISTS_query(subquery);
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 if (subLinkType == EXISTS_SUBLINK)
00470 tuple_fraction = 1.0;
00471 else if (subLinkType == ALL_SUBLINK ||
00472 subLinkType == ANY_SUBLINK)
00473 tuple_fraction = 0.5;
00474 else
00475 tuple_fraction = 0.0;
00476
00477
00478 Assert(root->plan_params == NIL);
00479
00480
00481
00482
00483 plan = subquery_planner(root->glob, subquery,
00484 root,
00485 false, tuple_fraction,
00486 &subroot);
00487
00488
00489 plan_params = root->plan_params;
00490 root->plan_params = NIL;
00491
00492
00493 result = build_subplan(root, plan, subroot, plan_params,
00494 subLinkType, testexpr, true, isTopQual);
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505 if (simple_exists && IsA(result, SubPlan))
00506 {
00507 Node *newtestexpr;
00508 List *paramIds;
00509
00510
00511 subquery = (Query *) copyObject(orig_subquery);
00512
00513 simple_exists = simplify_EXISTS_query(subquery);
00514 Assert(simple_exists);
00515
00516 subquery = convert_EXISTS_to_ANY(root, subquery,
00517 &newtestexpr, ¶mIds);
00518 if (subquery)
00519 {
00520
00521 plan = subquery_planner(root->glob, subquery,
00522 root,
00523 false, 0.0,
00524 &subroot);
00525
00526
00527 plan_params = root->plan_params;
00528 root->plan_params = NIL;
00529
00530
00531 if (subplan_is_hashable(plan))
00532 {
00533 SubPlan *hashplan;
00534 AlternativeSubPlan *asplan;
00535
00536
00537 hashplan = (SubPlan *) build_subplan(root, plan, subroot,
00538 plan_params,
00539 ANY_SUBLINK, newtestexpr,
00540 false, true);
00541
00542 Assert(IsA(hashplan, SubPlan));
00543 Assert(hashplan->parParam == NIL);
00544 Assert(hashplan->useHashTable);
00545
00546 hashplan->paramIds = paramIds;
00547
00548
00549 asplan = makeNode(AlternativeSubPlan);
00550 asplan->subplans = list_make2(result, hashplan);
00551 result = (Node *) asplan;
00552 }
00553 }
00554 }
00555
00556 return result;
00557 }
00558
00559
00560
00561
00562
00563
00564
00565 static Node *
00566 build_subplan(PlannerInfo *root, Plan *plan, PlannerInfo *subroot,
00567 List *plan_params,
00568 SubLinkType subLinkType, Node *testexpr,
00569 bool adjust_testexpr, bool unknownEqFalse)
00570 {
00571 Node *result;
00572 SubPlan *splan;
00573 bool isInitPlan;
00574 ListCell *lc;
00575
00576
00577
00578
00579
00580 splan = makeNode(SubPlan);
00581 splan->subLinkType = subLinkType;
00582 splan->testexpr = NULL;
00583 splan->paramIds = NIL;
00584 get_first_col_type(plan, &splan->firstColType, &splan->firstColTypmod,
00585 &splan->firstColCollation);
00586 splan->useHashTable = false;
00587 splan->unknownEqFalse = unknownEqFalse;
00588 splan->setParam = NIL;
00589 splan->parParam = NIL;
00590 splan->args = NIL;
00591
00592
00593
00594
00595
00596 foreach(lc, plan_params)
00597 {
00598 PlannerParamItem *pitem = (PlannerParamItem *) lfirst(lc);
00599 Node *arg = pitem->item;
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609 if (IsA(arg, PlaceHolderVar) ||
00610 IsA(arg, Aggref))
00611 arg = SS_process_sublinks(root, arg, false);
00612
00613 splan->parParam = lappend_int(splan->parParam, pitem->paramId);
00614 splan->args = lappend(splan->args, arg);
00615 }
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625 if (splan->parParam == NIL && subLinkType == EXISTS_SUBLINK)
00626 {
00627 Param *prm;
00628
00629 Assert(testexpr == NULL);
00630 prm = generate_new_param(root, BOOLOID, -1, InvalidOid);
00631 splan->setParam = list_make1_int(prm->paramid);
00632 isInitPlan = true;
00633 result = (Node *) prm;
00634 }
00635 else if (splan->parParam == NIL && subLinkType == EXPR_SUBLINK)
00636 {
00637 TargetEntry *te = linitial(plan->targetlist);
00638 Param *prm;
00639
00640 Assert(!te->resjunk);
00641 Assert(testexpr == NULL);
00642 prm = generate_new_param(root,
00643 exprType((Node *) te->expr),
00644 exprTypmod((Node *) te->expr),
00645 exprCollation((Node *) te->expr));
00646 splan->setParam = list_make1_int(prm->paramid);
00647 isInitPlan = true;
00648 result = (Node *) prm;
00649 }
00650 else if (splan->parParam == NIL && subLinkType == ARRAY_SUBLINK)
00651 {
00652 TargetEntry *te = linitial(plan->targetlist);
00653 Oid arraytype;
00654 Param *prm;
00655
00656 Assert(!te->resjunk);
00657 Assert(testexpr == NULL);
00658 arraytype = get_array_type(exprType((Node *) te->expr));
00659 if (!OidIsValid(arraytype))
00660 elog(ERROR, "could not find array type for datatype %s",
00661 format_type_be(exprType((Node *) te->expr)));
00662 prm = generate_new_param(root,
00663 arraytype,
00664 exprTypmod((Node *) te->expr),
00665 exprCollation((Node *) te->expr));
00666 splan->setParam = list_make1_int(prm->paramid);
00667 isInitPlan = true;
00668 result = (Node *) prm;
00669 }
00670 else if (splan->parParam == NIL && subLinkType == ROWCOMPARE_SUBLINK)
00671 {
00672
00673 List *params;
00674
00675 Assert(testexpr != NULL);
00676 params = generate_subquery_params(root,
00677 plan->targetlist,
00678 &splan->paramIds);
00679 result = convert_testexpr(root,
00680 testexpr,
00681 params);
00682 splan->setParam = list_copy(splan->paramIds);
00683 isInitPlan = true;
00684
00685
00686
00687
00688
00689 }
00690 else
00691 {
00692
00693
00694
00695
00696 if (testexpr && adjust_testexpr)
00697 {
00698 List *params;
00699
00700 params = generate_subquery_params(root,
00701 plan->targetlist,
00702 &splan->paramIds);
00703 splan->testexpr = convert_testexpr(root,
00704 testexpr,
00705 params);
00706 }
00707 else
00708 splan->testexpr = testexpr;
00709
00710
00711
00712
00713
00714
00715
00716
00717 if (subLinkType == ANY_SUBLINK &&
00718 splan->parParam == NIL &&
00719 subplan_is_hashable(plan) &&
00720 testexpr_is_hashable(splan->testexpr))
00721 splan->useHashTable = true;
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733 else if (splan->parParam == NIL && enable_material &&
00734 !ExecMaterializesOutput(nodeTag(plan)))
00735 plan = materialize_finished_plan(plan);
00736
00737 result = (Node *) splan;
00738 isInitPlan = false;
00739 }
00740
00741
00742
00743
00744 root->glob->subplans = lappend(root->glob->subplans, plan);
00745 root->glob->subroots = lappend(root->glob->subroots, subroot);
00746 splan->plan_id = list_length(root->glob->subplans);
00747
00748 if (isInitPlan)
00749 root->init_plans = lappend(root->init_plans, splan);
00750
00751
00752
00753
00754
00755
00756
00757
00758 if (splan->parParam == NIL && !isInitPlan && !splan->useHashTable)
00759 root->glob->rewindPlanIDs = bms_add_member(root->glob->rewindPlanIDs,
00760 splan->plan_id);
00761
00762
00763 if (isInitPlan)
00764 {
00765 ListCell *lc;
00766 int offset;
00767
00768 splan->plan_name = palloc(32 + 12 * list_length(splan->setParam));
00769 sprintf(splan->plan_name, "InitPlan %d (returns ", splan->plan_id);
00770 offset = strlen(splan->plan_name);
00771 foreach(lc, splan->setParam)
00772 {
00773 sprintf(splan->plan_name + offset, "$%d%s",
00774 lfirst_int(lc),
00775 lnext(lc) ? "," : "");
00776 offset += strlen(splan->plan_name + offset);
00777 }
00778 sprintf(splan->plan_name + offset, ")");
00779 }
00780 else
00781 {
00782 splan->plan_name = palloc(32);
00783 sprintf(splan->plan_name, "SubPlan %d", splan->plan_id);
00784 }
00785
00786
00787 cost_subplan(root, splan, plan);
00788
00789 return result;
00790 }
00791
00792
00793
00794
00795
00796
00797
00798 static List *
00799 generate_subquery_params(PlannerInfo *root, List *tlist, List **paramIds)
00800 {
00801 List *result;
00802 List *ids;
00803 ListCell *lc;
00804
00805 result = ids = NIL;
00806 foreach(lc, tlist)
00807 {
00808 TargetEntry *tent = (TargetEntry *) lfirst(lc);
00809 Param *param;
00810
00811 if (tent->resjunk)
00812 continue;
00813
00814 param = generate_new_param(root,
00815 exprType((Node *) tent->expr),
00816 exprTypmod((Node *) tent->expr),
00817 exprCollation((Node *) tent->expr));
00818 result = lappend(result, param);
00819 ids = lappend_int(ids, param->paramid);
00820 }
00821
00822 *paramIds = ids;
00823 return result;
00824 }
00825
00826
00827
00828
00829
00830
00831 static List *
00832 generate_subquery_vars(PlannerInfo *root, List *tlist, Index varno)
00833 {
00834 List *result;
00835 ListCell *lc;
00836
00837 result = NIL;
00838 foreach(lc, tlist)
00839 {
00840 TargetEntry *tent = (TargetEntry *) lfirst(lc);
00841 Var *var;
00842
00843 if (tent->resjunk)
00844 continue;
00845
00846 var = makeVarFromTargetEntry(varno, tent);
00847 result = lappend(result, var);
00848 }
00849
00850 return result;
00851 }
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865 static Node *
00866 convert_testexpr(PlannerInfo *root,
00867 Node *testexpr,
00868 List *subst_nodes)
00869 {
00870 convert_testexpr_context context;
00871
00872 context.root = root;
00873 context.subst_nodes = subst_nodes;
00874 return convert_testexpr_mutator(testexpr, &context);
00875 }
00876
00877 static Node *
00878 convert_testexpr_mutator(Node *node,
00879 convert_testexpr_context *context)
00880 {
00881 if (node == NULL)
00882 return NULL;
00883 if (IsA(node, Param))
00884 {
00885 Param *param = (Param *) node;
00886
00887 if (param->paramkind == PARAM_SUBLINK)
00888 {
00889 if (param->paramid <= 0 ||
00890 param->paramid > list_length(context->subst_nodes))
00891 elog(ERROR, "unexpected PARAM_SUBLINK ID: %d", param->paramid);
00892
00893
00894
00895
00896
00897
00898 return (Node *) copyObject(list_nth(context->subst_nodes,
00899 param->paramid - 1));
00900 }
00901 }
00902 return expression_tree_mutator(node,
00903 convert_testexpr_mutator,
00904 (void *) context);
00905 }
00906
00907
00908
00909
00910 static bool
00911 subplan_is_hashable(Plan *plan)
00912 {
00913 double subquery_size;
00914
00915
00916
00917
00918
00919
00920
00921 subquery_size = plan->plan_rows *
00922 (MAXALIGN(plan->plan_width) + MAXALIGN(sizeof(HeapTupleHeaderData)));
00923 if (subquery_size > work_mem * 1024L)
00924 return false;
00925
00926 return true;
00927 }
00928
00929
00930
00931
00932 static bool
00933 testexpr_is_hashable(Node *testexpr)
00934 {
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946 if (testexpr && IsA(testexpr, OpExpr))
00947 {
00948 if (hash_ok_operator((OpExpr *) testexpr))
00949 return true;
00950 }
00951 else if (and_clause(testexpr))
00952 {
00953 ListCell *l;
00954
00955 foreach(l, ((BoolExpr *) testexpr)->args)
00956 {
00957 Node *andarg = (Node *) lfirst(l);
00958
00959 if (!IsA(andarg, OpExpr))
00960 return false;
00961 if (!hash_ok_operator((OpExpr *) andarg))
00962 return false;
00963 }
00964 return true;
00965 }
00966
00967 return false;
00968 }
00969
00970
00971
00972
00973
00974
00975
00976 static bool
00977 hash_ok_operator(OpExpr *expr)
00978 {
00979 Oid opid = expr->opno;
00980
00981
00982 if (list_length(expr->args) != 2)
00983 return false;
00984 if (opid == ARRAY_EQ_OP)
00985 {
00986
00987
00988 Node *leftarg = linitial(expr->args);
00989
00990 return op_hashjoinable(opid, exprType(leftarg));
00991 }
00992 else
00993 {
00994
00995 HeapTuple tup;
00996 Form_pg_operator optup;
00997
00998 tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(opid));
00999 if (!HeapTupleIsValid(tup))
01000 elog(ERROR, "cache lookup failed for operator %u", opid);
01001 optup = (Form_pg_operator) GETSTRUCT(tup);
01002 if (!optup->oprcanhash || !func_strict(optup->oprcode))
01003 {
01004 ReleaseSysCache(tup);
01005 return false;
01006 }
01007 ReleaseSysCache(tup);
01008 return true;
01009 }
01010 }
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021 void
01022 SS_process_ctes(PlannerInfo *root)
01023 {
01024 ListCell *lc;
01025
01026 Assert(root->cte_plan_ids == NIL);
01027
01028 foreach(lc, root->parse->cteList)
01029 {
01030 CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
01031 CmdType cmdType = ((Query *) cte->ctequery)->commandType;
01032 Query *subquery;
01033 Plan *plan;
01034 PlannerInfo *subroot;
01035 SubPlan *splan;
01036 int paramid;
01037
01038
01039
01040
01041 if (cte->cterefcount == 0 && cmdType == CMD_SELECT)
01042 {
01043
01044 root->cte_plan_ids = lappend_int(root->cte_plan_ids, -1);
01045 continue;
01046 }
01047
01048
01049
01050
01051
01052 subquery = (Query *) copyObject(cte->ctequery);
01053
01054
01055 Assert(root->plan_params == NIL);
01056
01057
01058
01059
01060
01061 plan = subquery_planner(root->glob, subquery,
01062 root,
01063 cte->cterecursive, 0.0,
01064 &subroot);
01065
01066
01067
01068
01069
01070
01071 if (root->plan_params)
01072 elog(ERROR, "unexpected outer reference in CTE query");
01073
01074
01075
01076
01077
01078
01079
01080 splan = makeNode(SubPlan);
01081 splan->subLinkType = CTE_SUBLINK;
01082 splan->testexpr = NULL;
01083 splan->paramIds = NIL;
01084 get_first_col_type(plan, &splan->firstColType, &splan->firstColTypmod,
01085 &splan->firstColCollation);
01086 splan->useHashTable = false;
01087 splan->unknownEqFalse = false;
01088 splan->setParam = NIL;
01089 splan->parParam = NIL;
01090 splan->args = NIL;
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107 paramid = SS_assign_special_param(root);
01108 splan->setParam = list_make1_int(paramid);
01109
01110
01111
01112
01113 root->glob->subplans = lappend(root->glob->subplans, plan);
01114 root->glob->subroots = lappend(root->glob->subroots, subroot);
01115 splan->plan_id = list_length(root->glob->subplans);
01116
01117 root->init_plans = lappend(root->init_plans, splan);
01118
01119 root->cte_plan_ids = lappend_int(root->cte_plan_ids, splan->plan_id);
01120
01121
01122 splan->plan_name = palloc(4 + strlen(cte->ctename) + 1);
01123 sprintf(splan->plan_name, "CTE %s", cte->ctename);
01124
01125
01126 cost_subplan(root, splan, plan);
01127 }
01128 }
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164 JoinExpr *
01165 convert_ANY_sublink_to_join(PlannerInfo *root, SubLink *sublink,
01166 Relids available_rels)
01167 {
01168 JoinExpr *result;
01169 Query *parse = root->parse;
01170 Query *subselect = (Query *) sublink->subselect;
01171 Relids upper_varnos;
01172 int rtindex;
01173 RangeTblEntry *rte;
01174 RangeTblRef *rtr;
01175 List *subquery_vars;
01176 Node *quals;
01177
01178 Assert(sublink->subLinkType == ANY_SUBLINK);
01179
01180
01181
01182
01183
01184 if (contain_vars_of_level((Node *) subselect, 1))
01185 return NULL;
01186
01187
01188
01189
01190
01191
01192 upper_varnos = pull_varnos(sublink->testexpr);
01193 if (bms_is_empty(upper_varnos))
01194 return NULL;
01195
01196
01197
01198
01199 if (!bms_is_subset(upper_varnos, available_rels))
01200 return NULL;
01201
01202
01203
01204
01205 if (contain_volatile_functions(sublink->testexpr))
01206 return NULL;
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216 rte = addRangeTableEntryForSubquery(NULL,
01217 subselect,
01218 makeAlias("ANY_subquery", NIL),
01219 false,
01220 false);
01221 parse->rtable = lappend(parse->rtable, rte);
01222 rtindex = list_length(parse->rtable);
01223
01224
01225
01226
01227 rtr = makeNode(RangeTblRef);
01228 rtr->rtindex = rtindex;
01229
01230
01231
01232
01233 subquery_vars = generate_subquery_vars(root,
01234 subselect->targetList,
01235 rtindex);
01236
01237
01238
01239
01240 quals = convert_testexpr(root, sublink->testexpr, subquery_vars);
01241
01242
01243
01244
01245 result = makeNode(JoinExpr);
01246 result->jointype = JOIN_SEMI;
01247 result->isNatural = false;
01248 result->larg = NULL;
01249 result->rarg = (Node *) rtr;
01250 result->usingClause = NIL;
01251 result->quals = quals;
01252 result->alias = NULL;
01253 result->rtindex = 0;
01254
01255 return result;
01256 }
01257
01258
01259
01260
01261
01262
01263
01264
01265 JoinExpr *
01266 convert_EXISTS_sublink_to_join(PlannerInfo *root, SubLink *sublink,
01267 bool under_not, Relids available_rels)
01268 {
01269 JoinExpr *result;
01270 Query *parse = root->parse;
01271 Query *subselect = (Query *) sublink->subselect;
01272 Node *whereClause;
01273 int rtoffset;
01274 int varno;
01275 Relids clause_varnos;
01276 Relids upper_varnos;
01277
01278 Assert(sublink->subLinkType == EXISTS_SUBLINK);
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288 if (subselect->cteList)
01289 return NULL;
01290
01291
01292
01293
01294
01295 subselect = (Query *) copyObject(subselect);
01296
01297
01298
01299
01300
01301
01302
01303 if (!simplify_EXISTS_query(subselect))
01304 return NULL;
01305
01306
01307
01308
01309 if (subselect->jointree->fromlist == NIL)
01310 return NULL;
01311
01312
01313
01314
01315
01316
01317 whereClause = subselect->jointree->quals;
01318 subselect->jointree->quals = NULL;
01319
01320
01321
01322
01323
01324 if (contain_vars_of_level((Node *) subselect, 1))
01325 return NULL;
01326
01327
01328
01329
01330
01331 if (!contain_vars_of_level(whereClause, 1))
01332 return NULL;
01333
01334
01335
01336
01337 if (contain_volatile_functions(whereClause))
01338 return NULL;
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355 rtoffset = list_length(parse->rtable);
01356 OffsetVarNodes((Node *) subselect, rtoffset, 0);
01357 OffsetVarNodes(whereClause, rtoffset, 0);
01358
01359
01360
01361
01362
01363
01364 IncrementVarSublevelsUp((Node *) subselect, -1, 1);
01365 IncrementVarSublevelsUp(whereClause, -1, 1);
01366
01367
01368
01369
01370
01371
01372
01373 clause_varnos = pull_varnos(whereClause);
01374 upper_varnos = NULL;
01375 while ((varno = bms_first_member(clause_varnos)) >= 0)
01376 {
01377 if (varno <= rtoffset)
01378 upper_varnos = bms_add_member(upper_varnos, varno);
01379 }
01380 bms_free(clause_varnos);
01381 Assert(!bms_is_empty(upper_varnos));
01382
01383
01384
01385
01386
01387 if (!bms_is_subset(upper_varnos, available_rels))
01388 return NULL;
01389
01390
01391 parse->rtable = list_concat(parse->rtable, subselect->rtable);
01392
01393
01394
01395
01396 result = makeNode(JoinExpr);
01397 result->jointype = under_not ? JOIN_ANTI : JOIN_SEMI;
01398 result->isNatural = false;
01399 result->larg = NULL;
01400
01401 if (list_length(subselect->jointree->fromlist) == 1)
01402 result->rarg = (Node *) linitial(subselect->jointree->fromlist);
01403 else
01404 result->rarg = (Node *) subselect->jointree;
01405 result->usingClause = NIL;
01406 result->quals = whereClause;
01407 result->alias = NULL;
01408 result->rtindex = 0;
01409
01410 return result;
01411 }
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429 static bool
01430 simplify_EXISTS_query(Query *query)
01431 {
01432
01433
01434
01435
01436
01437
01438 if (query->commandType != CMD_SELECT ||
01439 query->setOperations ||
01440 query->hasAggs ||
01441 query->hasWindowFuncs ||
01442 query->hasModifyingCTE ||
01443 query->havingQual ||
01444 query->limitOffset ||
01445 query->limitCount ||
01446 query->rowMarks)
01447 return false;
01448
01449
01450
01451
01452
01453 if (expression_returns_set((Node *) query->targetList))
01454 return false;
01455
01456
01457
01458
01459
01460
01461
01462
01463 query->targetList = NIL;
01464 query->groupClause = NIL;
01465 query->windowClause = NIL;
01466 query->distinctClause = NIL;
01467 query->sortClause = NIL;
01468 query->hasDistinctOn = false;
01469
01470 return true;
01471 }
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487 static Query *
01488 convert_EXISTS_to_ANY(PlannerInfo *root, Query *subselect,
01489 Node **testexpr, List **paramIds)
01490 {
01491 Node *whereClause;
01492 List *leftargs,
01493 *rightargs,
01494 *opids,
01495 *opcollations,
01496 *newWhere,
01497 *tlist,
01498 *testlist,
01499 *paramids;
01500 ListCell *lc,
01501 *rc,
01502 *oc,
01503 *cc;
01504 AttrNumber resno;
01505
01506
01507
01508
01509
01510 Assert(subselect->targetList == NIL);
01511
01512
01513
01514
01515
01516
01517 whereClause = subselect->jointree->quals;
01518 subselect->jointree->quals = NULL;
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528 if (contain_vars_of_level((Node *) subselect, 1))
01529 return NULL;
01530
01531
01532
01533
01534 if (contain_volatile_functions(whereClause))
01535 return NULL;
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556 whereClause = eval_const_expressions(root, whereClause);
01557 whereClause = (Node *) canonicalize_qual((Expr *) whereClause);
01558 whereClause = (Node *) make_ands_implicit((Expr *) whereClause);
01559
01560
01561
01562
01563
01564
01565
01566
01567 leftargs = rightargs = opids = opcollations = newWhere = NIL;
01568 foreach(lc, (List *) whereClause)
01569 {
01570 OpExpr *expr = (OpExpr *) lfirst(lc);
01571
01572 if (IsA(expr, OpExpr) &&
01573 hash_ok_operator(expr))
01574 {
01575 Node *leftarg = (Node *) linitial(expr->args);
01576 Node *rightarg = (Node *) lsecond(expr->args);
01577
01578 if (contain_vars_of_level(leftarg, 1))
01579 {
01580 leftargs = lappend(leftargs, leftarg);
01581 rightargs = lappend(rightargs, rightarg);
01582 opids = lappend_oid(opids, expr->opno);
01583 opcollations = lappend_oid(opcollations, expr->inputcollid);
01584 continue;
01585 }
01586 if (contain_vars_of_level(rightarg, 1))
01587 {
01588
01589
01590
01591
01592
01593
01594 expr->opno = get_commutator(expr->opno);
01595 if (OidIsValid(expr->opno) && hash_ok_operator(expr))
01596 {
01597 leftargs = lappend(leftargs, rightarg);
01598 rightargs = lappend(rightargs, leftarg);
01599 opids = lappend_oid(opids, expr->opno);
01600 opcollations = lappend_oid(opcollations, expr->inputcollid);
01601 continue;
01602 }
01603
01604 return NULL;
01605 }
01606 }
01607
01608 newWhere = lappend(newWhere, expr);
01609 }
01610
01611
01612
01613
01614 if (leftargs == NIL)
01615 return NULL;
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626 if (contain_vars_of_level((Node *) newWhere, 1) ||
01627 contain_vars_of_level((Node *) rightargs, 1))
01628 return NULL;
01629 if (root->parse->hasAggs &&
01630 (contain_aggs_of_level((Node *) newWhere, 1) ||
01631 contain_aggs_of_level((Node *) rightargs, 1)))
01632 return NULL;
01633
01634
01635
01636
01637
01638
01639
01640 if (contain_vars_of_level((Node *) leftargs, 0))
01641 return NULL;
01642
01643
01644
01645
01646
01647 if (contain_subplans((Node *) leftargs))
01648 return NULL;
01649
01650
01651
01652
01653 IncrementVarSublevelsUp((Node *) leftargs, -1, 1);
01654
01655
01656
01657
01658 if (newWhere)
01659 subselect->jointree->quals = (Node *) make_ands_explicit(newWhere);
01660
01661
01662
01663
01664
01665
01666
01667 tlist = testlist = paramids = NIL;
01668 resno = 1;
01669
01670 cc = list_head(opcollations);
01671 forthree(lc, leftargs, rc, rightargs, oc, opids)
01672 {
01673 Node *leftarg = (Node *) lfirst(lc);
01674 Node *rightarg = (Node *) lfirst(rc);
01675 Oid opid = lfirst_oid(oc);
01676 Oid opcollation = lfirst_oid(cc);
01677 Param *param;
01678
01679 cc = lnext(cc);
01680 param = generate_new_param(root,
01681 exprType(rightarg),
01682 exprTypmod(rightarg),
01683 exprCollation(rightarg));
01684 tlist = lappend(tlist,
01685 makeTargetEntry((Expr *) rightarg,
01686 resno++,
01687 NULL,
01688 false));
01689 testlist = lappend(testlist,
01690 make_opclause(opid, BOOLOID, false,
01691 (Expr *) leftarg, (Expr *) param,
01692 InvalidOid, opcollation));
01693 paramids = lappend_int(paramids, param->paramid);
01694 }
01695
01696
01697 subselect->targetList = tlist;
01698 *testexpr = (Node *) make_ands_explicit(testlist);
01699 *paramIds = paramids;
01700
01701 return subselect;
01702 }
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729 Node *
01730 SS_replace_correlation_vars(PlannerInfo *root, Node *expr)
01731 {
01732
01733 return replace_correlation_vars_mutator(expr, root);
01734 }
01735
01736 static Node *
01737 replace_correlation_vars_mutator(Node *node, PlannerInfo *root)
01738 {
01739 if (node == NULL)
01740 return NULL;
01741 if (IsA(node, Var))
01742 {
01743 if (((Var *) node)->varlevelsup > 0)
01744 return (Node *) replace_outer_var(root, (Var *) node);
01745 }
01746 if (IsA(node, PlaceHolderVar))
01747 {
01748 if (((PlaceHolderVar *) node)->phlevelsup > 0)
01749 return (Node *) replace_outer_placeholdervar(root,
01750 (PlaceHolderVar *) node);
01751 }
01752 if (IsA(node, Aggref))
01753 {
01754 if (((Aggref *) node)->agglevelsup > 0)
01755 return (Node *) replace_outer_agg(root, (Aggref *) node);
01756 }
01757 return expression_tree_mutator(node,
01758 replace_correlation_vars_mutator,
01759 (void *) root);
01760 }
01761
01762
01763
01764
01765
01766
01767
01768
01769 Node *
01770 SS_process_sublinks(PlannerInfo *root, Node *expr, bool isQual)
01771 {
01772 process_sublinks_context context;
01773
01774 context.root = root;
01775 context.isTopQual = isQual;
01776 return process_sublinks_mutator(expr, &context);
01777 }
01778
01779 static Node *
01780 process_sublinks_mutator(Node *node, process_sublinks_context *context)
01781 {
01782 process_sublinks_context locContext;
01783
01784 locContext.root = context->root;
01785
01786 if (node == NULL)
01787 return NULL;
01788 if (IsA(node, SubLink))
01789 {
01790 SubLink *sublink = (SubLink *) node;
01791 Node *testexpr;
01792
01793
01794
01795
01796
01797 locContext.isTopQual = false;
01798 testexpr = process_sublinks_mutator(sublink->testexpr, &locContext);
01799
01800
01801
01802
01803 return make_subplan(context->root,
01804 (Query *) sublink->subselect,
01805 sublink->subLinkType,
01806 testexpr,
01807 context->isTopQual);
01808 }
01809
01810
01811
01812
01813
01814
01815
01816 if (IsA(node, PlaceHolderVar))
01817 {
01818 if (((PlaceHolderVar *) node)->phlevelsup > 0)
01819 return node;
01820 }
01821 else if (IsA(node, Aggref))
01822 {
01823 if (((Aggref *) node)->agglevelsup > 0)
01824 return node;
01825 }
01826
01827
01828
01829
01830
01831
01832 Assert(!IsA(node, SubPlan));
01833 Assert(!IsA(node, AlternativeSubPlan));
01834 Assert(!IsA(node, Query));
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850 if (and_clause(node))
01851 {
01852 List *newargs = NIL;
01853 ListCell *l;
01854
01855
01856 locContext.isTopQual = context->isTopQual;
01857
01858 foreach(l, ((BoolExpr *) node)->args)
01859 {
01860 Node *newarg;
01861
01862 newarg = process_sublinks_mutator(lfirst(l), &locContext);
01863 if (and_clause(newarg))
01864 newargs = list_concat(newargs, ((BoolExpr *) newarg)->args);
01865 else
01866 newargs = lappend(newargs, newarg);
01867 }
01868 return (Node *) make_andclause(newargs);
01869 }
01870
01871 if (or_clause(node))
01872 {
01873 List *newargs = NIL;
01874 ListCell *l;
01875
01876
01877 locContext.isTopQual = context->isTopQual;
01878
01879 foreach(l, ((BoolExpr *) node)->args)
01880 {
01881 Node *newarg;
01882
01883 newarg = process_sublinks_mutator(lfirst(l), &locContext);
01884 if (or_clause(newarg))
01885 newargs = list_concat(newargs, ((BoolExpr *) newarg)->args);
01886 else
01887 newargs = lappend(newargs, newarg);
01888 }
01889 return (Node *) make_orclause(newargs);
01890 }
01891
01892
01893
01894
01895
01896 locContext.isTopQual = false;
01897
01898 return expression_tree_mutator(node,
01899 process_sublinks_mutator,
01900 (void *) &locContext);
01901 }
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912 void
01913 SS_finalize_plan(PlannerInfo *root, Plan *plan, bool attach_initplans)
01914 {
01915 Bitmapset *valid_params,
01916 *initExtParam,
01917 *initSetParam;
01918 Cost initplan_cost;
01919 PlannerInfo *proot;
01920 ListCell *l;
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932 initExtParam = initSetParam = NULL;
01933 initplan_cost = 0;
01934 foreach(l, root->init_plans)
01935 {
01936 SubPlan *initsubplan = (SubPlan *) lfirst(l);
01937 Plan *initplan = planner_subplan_get_plan(root, initsubplan);
01938 ListCell *l2;
01939
01940 initExtParam = bms_add_members(initExtParam, initplan->extParam);
01941 foreach(l2, initsubplan->setParam)
01942 {
01943 initSetParam = bms_add_member(initSetParam, lfirst_int(l2));
01944 }
01945 initplan_cost += initsubplan->startup_cost + initsubplan->per_call_cost;
01946 }
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957 valid_params = bms_copy(initSetParam);
01958 for (proot = root->parent_root; proot != NULL; proot = proot->parent_root)
01959 {
01960
01961 foreach(l, proot->plan_params)
01962 {
01963 PlannerParamItem *pitem = (PlannerParamItem *) lfirst(l);
01964
01965 valid_params = bms_add_member(valid_params, pitem->paramId);
01966 }
01967
01968 foreach(l, proot->init_plans)
01969 {
01970 SubPlan *initsubplan = (SubPlan *) lfirst(l);
01971 ListCell *l2;
01972
01973 foreach(l2, initsubplan->setParam)
01974 {
01975 valid_params = bms_add_member(valid_params, lfirst_int(l2));
01976 }
01977 }
01978
01979 if (proot->wt_param_id >= 0)
01980 valid_params = bms_add_member(valid_params, proot->wt_param_id);
01981 }
01982
01983
01984
01985
01986 (void) finalize_plan(root, plan, valid_params, NULL);
01987
01988 bms_free(valid_params);
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002 if (attach_initplans)
02003 {
02004 plan->initPlan = root->init_plans;
02005 root->init_plans = NIL;
02006
02007
02008 plan->allParam = bms_add_members(plan->allParam, initExtParam);
02009 plan->allParam = bms_add_members(plan->allParam, initSetParam);
02010
02011 plan->extParam = bms_add_members(plan->extParam, initExtParam);
02012
02013 plan->extParam = bms_del_members(plan->extParam, initSetParam);
02014
02015 if (bms_is_empty(plan->extParam))
02016 plan->extParam = NULL;
02017
02018 plan->startup_cost += initplan_cost;
02019 plan->total_cost += initplan_cost;
02020 }
02021 }
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035 static Bitmapset *
02036 finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params,
02037 Bitmapset *scan_params)
02038 {
02039 finalize_primnode_context context;
02040 int locally_added_param;
02041 Bitmapset *nestloop_params;
02042 Bitmapset *child_params;
02043
02044 if (plan == NULL)
02045 return NULL;
02046
02047 context.root = root;
02048 context.paramids = NULL;
02049 locally_added_param = -1;
02050 nestloop_params = NULL;
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060 finalize_primnode((Node *) plan->targetlist, &context);
02061 finalize_primnode((Node *) plan->qual, &context);
02062
02063
02064 switch (nodeTag(plan))
02065 {
02066 case T_Result:
02067 finalize_primnode(((Result *) plan)->resconstantqual,
02068 &context);
02069 break;
02070
02071 case T_SeqScan:
02072 context.paramids = bms_add_members(context.paramids, scan_params);
02073 break;
02074
02075 case T_IndexScan:
02076 finalize_primnode((Node *) ((IndexScan *) plan)->indexqual,
02077 &context);
02078 finalize_primnode((Node *) ((IndexScan *) plan)->indexorderby,
02079 &context);
02080
02081
02082
02083
02084
02085
02086 context.paramids = bms_add_members(context.paramids, scan_params);
02087 break;
02088
02089 case T_IndexOnlyScan:
02090 finalize_primnode((Node *) ((IndexOnlyScan *) plan)->indexqual,
02091 &context);
02092 finalize_primnode((Node *) ((IndexOnlyScan *) plan)->indexorderby,
02093 &context);
02094
02095
02096
02097
02098 context.paramids = bms_add_members(context.paramids, scan_params);
02099 break;
02100
02101 case T_BitmapIndexScan:
02102 finalize_primnode((Node *) ((BitmapIndexScan *) plan)->indexqual,
02103 &context);
02104
02105
02106
02107
02108
02109 break;
02110
02111 case T_BitmapHeapScan:
02112 finalize_primnode((Node *) ((BitmapHeapScan *) plan)->bitmapqualorig,
02113 &context);
02114 context.paramids = bms_add_members(context.paramids, scan_params);
02115 break;
02116
02117 case T_TidScan:
02118 finalize_primnode((Node *) ((TidScan *) plan)->tidquals,
02119 &context);
02120 context.paramids = bms_add_members(context.paramids, scan_params);
02121 break;
02122
02123 case T_SubqueryScan:
02124
02125
02126
02127
02128
02129
02130
02131
02132 context.paramids = bms_add_members(context.paramids,
02133 ((SubqueryScan *) plan)->subplan->extParam);
02134
02135 context.paramids = bms_add_members(context.paramids, scan_params);
02136 break;
02137
02138 case T_FunctionScan:
02139 finalize_primnode(((FunctionScan *) plan)->funcexpr,
02140 &context);
02141 context.paramids = bms_add_members(context.paramids, scan_params);
02142 break;
02143
02144 case T_ValuesScan:
02145 finalize_primnode((Node *) ((ValuesScan *) plan)->values_lists,
02146 &context);
02147 context.paramids = bms_add_members(context.paramids, scan_params);
02148 break;
02149
02150 case T_CteScan:
02151 {
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162 int plan_id = ((CteScan *) plan)->ctePlanId;
02163 Plan *cteplan;
02164
02165
02166 if (plan_id < 1 || plan_id > list_length(root->glob->subplans))
02167 elog(ERROR, "could not find plan for CteScan referencing plan ID %d",
02168 plan_id);
02169 cteplan = (Plan *) list_nth(root->glob->subplans, plan_id - 1);
02170 context.paramids =
02171 bms_add_members(context.paramids, cteplan->extParam);
02172
02173 #ifdef NOT_USED
02174
02175 context.paramids =
02176 bms_add_member(context.paramids,
02177 ((CteScan *) plan)->cteParam);
02178 #endif
02179
02180 context.paramids = bms_add_members(context.paramids,
02181 scan_params);
02182 }
02183 break;
02184
02185 case T_WorkTableScan:
02186 context.paramids =
02187 bms_add_member(context.paramids,
02188 ((WorkTableScan *) plan)->wtParam);
02189 context.paramids = bms_add_members(context.paramids, scan_params);
02190 break;
02191
02192 case T_ForeignScan:
02193 finalize_primnode((Node *) ((ForeignScan *) plan)->fdw_exprs,
02194 &context);
02195 context.paramids = bms_add_members(context.paramids, scan_params);
02196 break;
02197
02198 case T_ModifyTable:
02199 {
02200 ModifyTable *mtplan = (ModifyTable *) plan;
02201 ListCell *l;
02202
02203
02204 locally_added_param = mtplan->epqParam;
02205 valid_params = bms_add_member(bms_copy(valid_params),
02206 locally_added_param);
02207 scan_params = bms_add_member(bms_copy(scan_params),
02208 locally_added_param);
02209 finalize_primnode((Node *) mtplan->returningLists,
02210 &context);
02211 foreach(l, mtplan->plans)
02212 {
02213 context.paramids =
02214 bms_add_members(context.paramids,
02215 finalize_plan(root,
02216 (Plan *) lfirst(l),
02217 valid_params,
02218 scan_params));
02219 }
02220 }
02221 break;
02222
02223 case T_Append:
02224 {
02225 ListCell *l;
02226
02227 foreach(l, ((Append *) plan)->appendplans)
02228 {
02229 context.paramids =
02230 bms_add_members(context.paramids,
02231 finalize_plan(root,
02232 (Plan *) lfirst(l),
02233 valid_params,
02234 scan_params));
02235 }
02236 }
02237 break;
02238
02239 case T_MergeAppend:
02240 {
02241 ListCell *l;
02242
02243 foreach(l, ((MergeAppend *) plan)->mergeplans)
02244 {
02245 context.paramids =
02246 bms_add_members(context.paramids,
02247 finalize_plan(root,
02248 (Plan *) lfirst(l),
02249 valid_params,
02250 scan_params));
02251 }
02252 }
02253 break;
02254
02255 case T_BitmapAnd:
02256 {
02257 ListCell *l;
02258
02259 foreach(l, ((BitmapAnd *) plan)->bitmapplans)
02260 {
02261 context.paramids =
02262 bms_add_members(context.paramids,
02263 finalize_plan(root,
02264 (Plan *) lfirst(l),
02265 valid_params,
02266 scan_params));
02267 }
02268 }
02269 break;
02270
02271 case T_BitmapOr:
02272 {
02273 ListCell *l;
02274
02275 foreach(l, ((BitmapOr *) plan)->bitmapplans)
02276 {
02277 context.paramids =
02278 bms_add_members(context.paramids,
02279 finalize_plan(root,
02280 (Plan *) lfirst(l),
02281 valid_params,
02282 scan_params));
02283 }
02284 }
02285 break;
02286
02287 case T_NestLoop:
02288 {
02289 ListCell *l;
02290
02291 finalize_primnode((Node *) ((Join *) plan)->joinqual,
02292 &context);
02293
02294 foreach(l, ((NestLoop *) plan)->nestParams)
02295 {
02296 NestLoopParam *nlp = (NestLoopParam *) lfirst(l);
02297
02298 nestloop_params = bms_add_member(nestloop_params,
02299 nlp->paramno);
02300 }
02301 }
02302 break;
02303
02304 case T_MergeJoin:
02305 finalize_primnode((Node *) ((Join *) plan)->joinqual,
02306 &context);
02307 finalize_primnode((Node *) ((MergeJoin *) plan)->mergeclauses,
02308 &context);
02309 break;
02310
02311 case T_HashJoin:
02312 finalize_primnode((Node *) ((Join *) plan)->joinqual,
02313 &context);
02314 finalize_primnode((Node *) ((HashJoin *) plan)->hashclauses,
02315 &context);
02316 break;
02317
02318 case T_Limit:
02319 finalize_primnode(((Limit *) plan)->limitOffset,
02320 &context);
02321 finalize_primnode(((Limit *) plan)->limitCount,
02322 &context);
02323 break;
02324
02325 case T_RecursiveUnion:
02326
02327 locally_added_param = ((RecursiveUnion *) plan)->wtParam;
02328 valid_params = bms_add_member(bms_copy(valid_params),
02329 locally_added_param);
02330
02331 break;
02332
02333 case T_LockRows:
02334
02335 locally_added_param = ((LockRows *) plan)->epqParam;
02336 valid_params = bms_add_member(bms_copy(valid_params),
02337 locally_added_param);
02338 scan_params = bms_add_member(bms_copy(scan_params),
02339 locally_added_param);
02340 break;
02341
02342 case T_WindowAgg:
02343 finalize_primnode(((WindowAgg *) plan)->startOffset,
02344 &context);
02345 finalize_primnode(((WindowAgg *) plan)->endOffset,
02346 &context);
02347 break;
02348
02349 case T_Hash:
02350 case T_Agg:
02351 case T_Material:
02352 case T_Sort:
02353 case T_Unique:
02354 case T_SetOp:
02355 case T_Group:
02356 break;
02357
02358 default:
02359 elog(ERROR, "unrecognized node type: %d",
02360 (int) nodeTag(plan));
02361 }
02362
02363
02364 child_params = finalize_plan(root,
02365 plan->lefttree,
02366 valid_params,
02367 scan_params);
02368 context.paramids = bms_add_members(context.paramids, child_params);
02369
02370 if (nestloop_params)
02371 {
02372
02373 child_params = finalize_plan(root,
02374 plan->righttree,
02375 bms_union(nestloop_params, valid_params),
02376 scan_params);
02377
02378 child_params = bms_difference(child_params, nestloop_params);
02379 bms_free(nestloop_params);
02380 }
02381 else
02382 {
02383
02384 child_params = finalize_plan(root,
02385 plan->righttree,
02386 valid_params,
02387 scan_params);
02388 }
02389 context.paramids = bms_add_members(context.paramids, child_params);
02390
02391
02392
02393
02394
02395
02396
02397 if (locally_added_param >= 0)
02398 {
02399 context.paramids = bms_del_member(context.paramids,
02400 locally_added_param);
02401 }
02402
02403
02404
02405 if (!bms_is_subset(context.paramids, valid_params))
02406 elog(ERROR, "plan should not reference subplan's variable");
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417 if (bms_is_empty(context.paramids))
02418 {
02419 plan->extParam = NULL;
02420 plan->allParam = NULL;
02421 }
02422 else
02423 {
02424 plan->extParam = context.paramids;
02425 plan->allParam = bms_copy(context.paramids);
02426 }
02427
02428 return plan->allParam;
02429 }
02430
02431
02432
02433
02434
02435 static bool
02436 finalize_primnode(Node *node, finalize_primnode_context *context)
02437 {
02438 if (node == NULL)
02439 return false;
02440 if (IsA(node, Param))
02441 {
02442 if (((Param *) node)->paramkind == PARAM_EXEC)
02443 {
02444 int paramid = ((Param *) node)->paramid;
02445
02446 context->paramids = bms_add_member(context->paramids, paramid);
02447 }
02448 return false;
02449 }
02450 if (IsA(node, SubPlan))
02451 {
02452 SubPlan *subplan = (SubPlan *) node;
02453 Plan *plan = planner_subplan_get_plan(context->root, subplan);
02454 ListCell *lc;
02455 Bitmapset *subparamids;
02456
02457
02458 finalize_primnode(subplan->testexpr, context);
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468 foreach(lc, subplan->paramIds)
02469 {
02470 context->paramids = bms_del_member(context->paramids,
02471 lfirst_int(lc));
02472 }
02473
02474
02475 finalize_primnode((Node *) subplan->args, context);
02476
02477
02478
02479
02480
02481 subparamids = bms_copy(plan->extParam);
02482 foreach(lc, subplan->parParam)
02483 {
02484 subparamids = bms_del_member(subparamids, lfirst_int(lc));
02485 }
02486 context->paramids = bms_join(context->paramids, subparamids);
02487
02488 return false;
02489 }
02490 return expression_tree_walker(node, finalize_primnode,
02491 (void *) context);
02492 }
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502
02503
02504 Param *
02505 SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
02506 Oid resulttype, int32 resulttypmod,
02507 Oid resultcollation)
02508 {
02509 SubPlan *node;
02510 Param *prm;
02511
02512
02513
02514
02515
02516
02517
02518
02519
02520
02521
02522
02523
02524 SS_finalize_plan(root, plan, false);
02525
02526
02527
02528
02529 root->glob->subplans = lappend(root->glob->subplans, plan);
02530 root->glob->subroots = lappend(root->glob->subroots, root);
02531
02532
02533
02534
02535
02536
02537 node = makeNode(SubPlan);
02538 node->subLinkType = EXPR_SUBLINK;
02539 get_first_col_type(plan, &node->firstColType, &node->firstColTypmod,
02540 &node->firstColCollation);
02541 node->plan_id = list_length(root->glob->subplans);
02542
02543 root->init_plans = lappend(root->init_plans, node);
02544
02545
02546
02547
02548
02549
02550 cost_subplan(root, node, plan);
02551
02552
02553
02554
02555 prm = generate_new_param(root, resulttype, resulttypmod, resultcollation);
02556 node->setParam = list_make1_int(prm->paramid);
02557
02558
02559 node->plan_name = palloc(64);
02560 sprintf(node->plan_name, "InitPlan %d (returns $%d)",
02561 node->plan_id, prm->paramid);
02562
02563 return prm;
02564 }