00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "postgres.h"
00017
00018 #include "access/transam.h"
00019 #include "catalog/pg_type.h"
00020 #include "nodes/makefuncs.h"
00021 #include "nodes/nodeFuncs.h"
00022 #include "optimizer/pathnode.h"
00023 #include "optimizer/planmain.h"
00024 #include "optimizer/tlist.h"
00025 #include "tcop/utility.h"
00026 #include "utils/lsyscache.h"
00027 #include "utils/syscache.h"
00028
00029
00030 typedef struct
00031 {
00032 Index varno;
00033 AttrNumber varattno;
00034 AttrNumber resno;
00035 } tlist_vinfo;
00036
00037 typedef struct
00038 {
00039 List *tlist;
00040 int num_vars;
00041 bool has_ph_vars;
00042 bool has_non_vars;
00043
00044 tlist_vinfo vars[1];
00045 } indexed_tlist;
00046
00047 typedef struct
00048 {
00049 PlannerInfo *root;
00050 int rtoffset;
00051 } fix_scan_expr_context;
00052
00053 typedef struct
00054 {
00055 PlannerInfo *root;
00056 indexed_tlist *outer_itlist;
00057 indexed_tlist *inner_itlist;
00058 Index acceptable_rel;
00059 int rtoffset;
00060 } fix_join_expr_context;
00061
00062 typedef struct
00063 {
00064 PlannerInfo *root;
00065 indexed_tlist *subplan_itlist;
00066 Index newvarno;
00067 int rtoffset;
00068 } fix_upper_expr_context;
00069
00070
00071
00072
00073
00074
00075
00076
00077 #define ISREGCLASSCONST(con) \
00078 (((con)->consttype == REGCLASSOID || (con)->consttype == OIDOID) && \
00079 !(con)->constisnull)
00080
00081 #define fix_scan_list(root, lst, rtoffset) \
00082 ((List *) fix_scan_expr(root, (Node *) (lst), rtoffset))
00083
00084 static Plan *set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset);
00085 static Plan *set_indexonlyscan_references(PlannerInfo *root,
00086 IndexOnlyScan *plan,
00087 int rtoffset);
00088 static Plan *set_subqueryscan_references(PlannerInfo *root,
00089 SubqueryScan *plan,
00090 int rtoffset);
00091 static bool trivial_subqueryscan(SubqueryScan *plan);
00092 static Node *fix_scan_expr(PlannerInfo *root, Node *node, int rtoffset);
00093 static Node *fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context);
00094 static bool fix_scan_expr_walker(Node *node, fix_scan_expr_context *context);
00095 static void set_join_references(PlannerInfo *root, Join *join, int rtoffset);
00096 static void set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset);
00097 static void set_dummy_tlist_references(Plan *plan, int rtoffset);
00098 static indexed_tlist *build_tlist_index(List *tlist);
00099 static Var *search_indexed_tlist_for_var(Var *var,
00100 indexed_tlist *itlist,
00101 Index newvarno,
00102 int rtoffset);
00103 static Var *search_indexed_tlist_for_non_var(Node *node,
00104 indexed_tlist *itlist,
00105 Index newvarno);
00106 static Var *search_indexed_tlist_for_sortgroupref(Node *node,
00107 Index sortgroupref,
00108 indexed_tlist *itlist,
00109 Index newvarno);
00110 static List *fix_join_expr(PlannerInfo *root,
00111 List *clauses,
00112 indexed_tlist *outer_itlist,
00113 indexed_tlist *inner_itlist,
00114 Index acceptable_rel, int rtoffset);
00115 static Node *fix_join_expr_mutator(Node *node,
00116 fix_join_expr_context *context);
00117 static Node *fix_upper_expr(PlannerInfo *root,
00118 Node *node,
00119 indexed_tlist *subplan_itlist,
00120 Index newvarno,
00121 int rtoffset);
00122 static Node *fix_upper_expr_mutator(Node *node,
00123 fix_upper_expr_context *context);
00124 static List *set_returning_clause_references(PlannerInfo *root,
00125 List *rlist,
00126 Plan *topplan,
00127 Index resultRelation,
00128 int rtoffset);
00129 static bool fix_opfuncids_walker(Node *node, void *context);
00130 static bool extract_query_dependencies_walker(Node *node,
00131 PlannerInfo *context);
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 Plan *
00192 set_plan_references(PlannerInfo *root, Plan *plan)
00193 {
00194 PlannerGlobal *glob = root->glob;
00195 int rtoffset = list_length(glob->finalrtable);
00196 ListCell *lc;
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 foreach(lc, root->parse->rtable)
00207 {
00208 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
00209 RangeTblEntry *newrte;
00210
00211
00212 newrte = (RangeTblEntry *) palloc(sizeof(RangeTblEntry));
00213 memcpy(newrte, rte, sizeof(RangeTblEntry));
00214
00215
00216 newrte->subquery = NULL;
00217 newrte->joinaliasvars = NIL;
00218 newrte->funcexpr = NULL;
00219 newrte->funccoltypes = NIL;
00220 newrte->funccoltypmods = NIL;
00221 newrte->funccolcollations = NIL;
00222 newrte->values_lists = NIL;
00223 newrte->values_collations = NIL;
00224 newrte->ctecoltypes = NIL;
00225 newrte->ctecoltypmods = NIL;
00226 newrte->ctecolcollations = NIL;
00227
00228 glob->finalrtable = lappend(glob->finalrtable, newrte);
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 if (newrte->rtekind == RTE_RELATION)
00243 glob->relationOids = lappend_oid(glob->relationOids,
00244 newrte->relid);
00245 }
00246
00247
00248
00249
00250
00251
00252 if (IS_SPECIAL_VARNO(list_length(glob->finalrtable)))
00253 ereport(ERROR,
00254 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
00255 errmsg("too many range table entries")));
00256
00257
00258
00259
00260 foreach(lc, root->rowMarks)
00261 {
00262 PlanRowMark *rc = (PlanRowMark *) lfirst(lc);
00263 PlanRowMark *newrc;
00264
00265 Assert(IsA(rc, PlanRowMark));
00266
00267
00268 newrc = (PlanRowMark *) palloc(sizeof(PlanRowMark));
00269 memcpy(newrc, rc, sizeof(PlanRowMark));
00270
00271
00272 newrc->rti += rtoffset;
00273 newrc->prti += rtoffset;
00274
00275 glob->finalrowmarks = lappend(glob->finalrowmarks, newrc);
00276 }
00277
00278
00279 return set_plan_refs(root, plan, rtoffset);
00280 }
00281
00282
00283
00284
00285 static Plan *
00286 set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
00287 {
00288 ListCell *l;
00289
00290 if (plan == NULL)
00291 return NULL;
00292
00293
00294
00295
00296 switch (nodeTag(plan))
00297 {
00298 case T_SeqScan:
00299 {
00300 SeqScan *splan = (SeqScan *) plan;
00301
00302 splan->scanrelid += rtoffset;
00303 splan->plan.targetlist =
00304 fix_scan_list(root, splan->plan.targetlist, rtoffset);
00305 splan->plan.qual =
00306 fix_scan_list(root, splan->plan.qual, rtoffset);
00307 }
00308 break;
00309 case T_IndexScan:
00310 {
00311 IndexScan *splan = (IndexScan *) plan;
00312
00313 splan->scan.scanrelid += rtoffset;
00314 splan->scan.plan.targetlist =
00315 fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
00316 splan->scan.plan.qual =
00317 fix_scan_list(root, splan->scan.plan.qual, rtoffset);
00318 splan->indexqual =
00319 fix_scan_list(root, splan->indexqual, rtoffset);
00320 splan->indexqualorig =
00321 fix_scan_list(root, splan->indexqualorig, rtoffset);
00322 splan->indexorderby =
00323 fix_scan_list(root, splan->indexorderby, rtoffset);
00324 splan->indexorderbyorig =
00325 fix_scan_list(root, splan->indexorderbyorig, rtoffset);
00326 }
00327 break;
00328 case T_IndexOnlyScan:
00329 {
00330 IndexOnlyScan *splan = (IndexOnlyScan *) plan;
00331
00332 return set_indexonlyscan_references(root, splan, rtoffset);
00333 }
00334 break;
00335 case T_BitmapIndexScan:
00336 {
00337 BitmapIndexScan *splan = (BitmapIndexScan *) plan;
00338
00339 splan->scan.scanrelid += rtoffset;
00340
00341 Assert(splan->scan.plan.targetlist == NIL);
00342 Assert(splan->scan.plan.qual == NIL);
00343 splan->indexqual =
00344 fix_scan_list(root, splan->indexqual, rtoffset);
00345 splan->indexqualorig =
00346 fix_scan_list(root, splan->indexqualorig, rtoffset);
00347 }
00348 break;
00349 case T_BitmapHeapScan:
00350 {
00351 BitmapHeapScan *splan = (BitmapHeapScan *) plan;
00352
00353 splan->scan.scanrelid += rtoffset;
00354 splan->scan.plan.targetlist =
00355 fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
00356 splan->scan.plan.qual =
00357 fix_scan_list(root, splan->scan.plan.qual, rtoffset);
00358 splan->bitmapqualorig =
00359 fix_scan_list(root, splan->bitmapqualorig, rtoffset);
00360 }
00361 break;
00362 case T_TidScan:
00363 {
00364 TidScan *splan = (TidScan *) plan;
00365
00366 splan->scan.scanrelid += rtoffset;
00367 splan->scan.plan.targetlist =
00368 fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
00369 splan->scan.plan.qual =
00370 fix_scan_list(root, splan->scan.plan.qual, rtoffset);
00371 splan->tidquals =
00372 fix_scan_list(root, splan->tidquals, rtoffset);
00373 }
00374 break;
00375 case T_SubqueryScan:
00376
00377 return set_subqueryscan_references(root,
00378 (SubqueryScan *) plan,
00379 rtoffset);
00380 case T_FunctionScan:
00381 {
00382 FunctionScan *splan = (FunctionScan *) plan;
00383
00384 splan->scan.scanrelid += rtoffset;
00385 splan->scan.plan.targetlist =
00386 fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
00387 splan->scan.plan.qual =
00388 fix_scan_list(root, splan->scan.plan.qual, rtoffset);
00389 splan->funcexpr =
00390 fix_scan_expr(root, splan->funcexpr, rtoffset);
00391 }
00392 break;
00393 case T_ValuesScan:
00394 {
00395 ValuesScan *splan = (ValuesScan *) plan;
00396
00397 splan->scan.scanrelid += rtoffset;
00398 splan->scan.plan.targetlist =
00399 fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
00400 splan->scan.plan.qual =
00401 fix_scan_list(root, splan->scan.plan.qual, rtoffset);
00402 splan->values_lists =
00403 fix_scan_list(root, splan->values_lists, rtoffset);
00404 }
00405 break;
00406 case T_CteScan:
00407 {
00408 CteScan *splan = (CteScan *) plan;
00409
00410 splan->scan.scanrelid += rtoffset;
00411 splan->scan.plan.targetlist =
00412 fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
00413 splan->scan.plan.qual =
00414 fix_scan_list(root, splan->scan.plan.qual, rtoffset);
00415 }
00416 break;
00417 case T_WorkTableScan:
00418 {
00419 WorkTableScan *splan = (WorkTableScan *) plan;
00420
00421 splan->scan.scanrelid += rtoffset;
00422 splan->scan.plan.targetlist =
00423 fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
00424 splan->scan.plan.qual =
00425 fix_scan_list(root, splan->scan.plan.qual, rtoffset);
00426 }
00427 break;
00428 case T_ForeignScan:
00429 {
00430 ForeignScan *splan = (ForeignScan *) plan;
00431
00432 splan->scan.scanrelid += rtoffset;
00433 splan->scan.plan.targetlist =
00434 fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
00435 splan->scan.plan.qual =
00436 fix_scan_list(root, splan->scan.plan.qual, rtoffset);
00437 splan->fdw_exprs =
00438 fix_scan_list(root, splan->fdw_exprs, rtoffset);
00439 }
00440 break;
00441
00442 case T_NestLoop:
00443 case T_MergeJoin:
00444 case T_HashJoin:
00445 set_join_references(root, (Join *) plan, rtoffset);
00446 break;
00447
00448 case T_Hash:
00449 case T_Material:
00450 case T_Sort:
00451 case T_Unique:
00452 case T_SetOp:
00453
00454
00455
00456
00457
00458
00459
00460
00461 set_dummy_tlist_references(plan, rtoffset);
00462
00463
00464
00465
00466
00467 Assert(plan->qual == NIL);
00468 break;
00469 case T_LockRows:
00470 {
00471 LockRows *splan = (LockRows *) plan;
00472
00473
00474
00475
00476
00477
00478 set_dummy_tlist_references(plan, rtoffset);
00479 Assert(splan->plan.qual == NIL);
00480
00481 foreach(l, splan->rowMarks)
00482 {
00483 PlanRowMark *rc = (PlanRowMark *) lfirst(l);
00484
00485 rc->rti += rtoffset;
00486 rc->prti += rtoffset;
00487 }
00488 }
00489 break;
00490 case T_Limit:
00491 {
00492 Limit *splan = (Limit *) plan;
00493
00494
00495
00496
00497
00498
00499
00500 set_dummy_tlist_references(plan, rtoffset);
00501 Assert(splan->plan.qual == NIL);
00502
00503 splan->limitOffset =
00504 fix_scan_expr(root, splan->limitOffset, rtoffset);
00505 splan->limitCount =
00506 fix_scan_expr(root, splan->limitCount, rtoffset);
00507 }
00508 break;
00509 case T_Agg:
00510 case T_Group:
00511 set_upper_references(root, plan, rtoffset);
00512 break;
00513 case T_WindowAgg:
00514 {
00515 WindowAgg *wplan = (WindowAgg *) plan;
00516
00517 set_upper_references(root, plan, rtoffset);
00518
00519
00520
00521
00522
00523
00524 wplan->startOffset =
00525 fix_scan_expr(root, wplan->startOffset, rtoffset);
00526 wplan->endOffset =
00527 fix_scan_expr(root, wplan->endOffset, rtoffset);
00528 }
00529 break;
00530 case T_Result:
00531 {
00532 Result *splan = (Result *) plan;
00533
00534
00535
00536
00537
00538 if (splan->plan.lefttree != NULL)
00539 set_upper_references(root, plan, rtoffset);
00540 else
00541 {
00542 splan->plan.targetlist =
00543 fix_scan_list(root, splan->plan.targetlist, rtoffset);
00544 splan->plan.qual =
00545 fix_scan_list(root, splan->plan.qual, rtoffset);
00546 }
00547
00548 splan->resconstantqual =
00549 fix_scan_expr(root, splan->resconstantqual, rtoffset);
00550 }
00551 break;
00552 case T_ModifyTable:
00553 {
00554 ModifyTable *splan = (ModifyTable *) plan;
00555
00556 Assert(splan->plan.targetlist == NIL);
00557 Assert(splan->plan.qual == NIL);
00558
00559 if (splan->returningLists)
00560 {
00561 List *newRL = NIL;
00562 ListCell *lcrl,
00563 *lcrr,
00564 *lcp;
00565
00566
00567
00568
00569
00570 Assert(list_length(splan->returningLists) == list_length(splan->resultRelations));
00571 Assert(list_length(splan->returningLists) == list_length(splan->plans));
00572 forthree(lcrl, splan->returningLists,
00573 lcrr, splan->resultRelations,
00574 lcp, splan->plans)
00575 {
00576 List *rlist = (List *) lfirst(lcrl);
00577 Index resultrel = lfirst_int(lcrr);
00578 Plan *subplan = (Plan *) lfirst(lcp);
00579
00580 rlist = set_returning_clause_references(root,
00581 rlist,
00582 subplan,
00583 resultrel,
00584 rtoffset);
00585 newRL = lappend(newRL, rlist);
00586 }
00587 splan->returningLists = newRL;
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597 splan->plan.targetlist = copyObject(linitial(newRL));
00598 }
00599
00600 foreach(l, splan->resultRelations)
00601 {
00602 lfirst_int(l) += rtoffset;
00603 }
00604 foreach(l, splan->rowMarks)
00605 {
00606 PlanRowMark *rc = (PlanRowMark *) lfirst(l);
00607
00608 rc->rti += rtoffset;
00609 rc->prti += rtoffset;
00610 }
00611 foreach(l, splan->plans)
00612 {
00613 lfirst(l) = set_plan_refs(root,
00614 (Plan *) lfirst(l),
00615 rtoffset);
00616 }
00617
00618
00619
00620
00621
00622
00623
00624 splan->resultRelIndex = list_length(root->glob->resultRelations);
00625 root->glob->resultRelations =
00626 list_concat(root->glob->resultRelations,
00627 list_copy(splan->resultRelations));
00628 }
00629 break;
00630 case T_Append:
00631 {
00632 Append *splan = (Append *) plan;
00633
00634
00635
00636
00637
00638 set_dummy_tlist_references(plan, rtoffset);
00639 Assert(splan->plan.qual == NIL);
00640 foreach(l, splan->appendplans)
00641 {
00642 lfirst(l) = set_plan_refs(root,
00643 (Plan *) lfirst(l),
00644 rtoffset);
00645 }
00646 }
00647 break;
00648 case T_MergeAppend:
00649 {
00650 MergeAppend *splan = (MergeAppend *) plan;
00651
00652
00653
00654
00655
00656 set_dummy_tlist_references(plan, rtoffset);
00657 Assert(splan->plan.qual == NIL);
00658 foreach(l, splan->mergeplans)
00659 {
00660 lfirst(l) = set_plan_refs(root,
00661 (Plan *) lfirst(l),
00662 rtoffset);
00663 }
00664 }
00665 break;
00666 case T_RecursiveUnion:
00667
00668 set_dummy_tlist_references(plan, rtoffset);
00669 Assert(plan->qual == NIL);
00670 break;
00671 case T_BitmapAnd:
00672 {
00673 BitmapAnd *splan = (BitmapAnd *) plan;
00674
00675
00676 Assert(splan->plan.targetlist == NIL);
00677 Assert(splan->plan.qual == NIL);
00678 foreach(l, splan->bitmapplans)
00679 {
00680 lfirst(l) = set_plan_refs(root,
00681 (Plan *) lfirst(l),
00682 rtoffset);
00683 }
00684 }
00685 break;
00686 case T_BitmapOr:
00687 {
00688 BitmapOr *splan = (BitmapOr *) plan;
00689
00690
00691 Assert(splan->plan.targetlist == NIL);
00692 Assert(splan->plan.qual == NIL);
00693 foreach(l, splan->bitmapplans)
00694 {
00695 lfirst(l) = set_plan_refs(root,
00696 (Plan *) lfirst(l),
00697 rtoffset);
00698 }
00699 }
00700 break;
00701 default:
00702 elog(ERROR, "unrecognized node type: %d",
00703 (int) nodeTag(plan));
00704 break;
00705 }
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715 plan->lefttree = set_plan_refs(root, plan->lefttree, rtoffset);
00716 plan->righttree = set_plan_refs(root, plan->righttree, rtoffset);
00717
00718 return plan;
00719 }
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730 static Plan *
00731 set_indexonlyscan_references(PlannerInfo *root,
00732 IndexOnlyScan *plan,
00733 int rtoffset)
00734 {
00735 indexed_tlist *index_itlist;
00736
00737 index_itlist = build_tlist_index(plan->indextlist);
00738
00739 plan->scan.scanrelid += rtoffset;
00740 plan->scan.plan.targetlist = (List *)
00741 fix_upper_expr(root,
00742 (Node *) plan->scan.plan.targetlist,
00743 index_itlist,
00744 INDEX_VAR,
00745 rtoffset);
00746 plan->scan.plan.qual = (List *)
00747 fix_upper_expr(root,
00748 (Node *) plan->scan.plan.qual,
00749 index_itlist,
00750 INDEX_VAR,
00751 rtoffset);
00752
00753 plan->indexqual = fix_scan_list(root, plan->indexqual, rtoffset);
00754
00755 plan->indexorderby = fix_scan_list(root, plan->indexorderby, rtoffset);
00756
00757 plan->indextlist = fix_scan_list(root, plan->indextlist, rtoffset);
00758
00759 pfree(index_itlist);
00760
00761 return (Plan *) plan;
00762 }
00763
00764
00765
00766
00767
00768
00769
00770
00771 static Plan *
00772 set_subqueryscan_references(PlannerInfo *root,
00773 SubqueryScan *plan,
00774 int rtoffset)
00775 {
00776 RelOptInfo *rel;
00777 Plan *result;
00778
00779
00780 rel = find_base_rel(root, plan->scan.scanrelid);
00781 Assert(rel->subplan == plan->subplan);
00782
00783
00784 plan->subplan = set_plan_references(rel->subroot, plan->subplan);
00785
00786 if (trivial_subqueryscan(plan))
00787 {
00788
00789
00790
00791 ListCell *lp,
00792 *lc;
00793
00794 result = plan->subplan;
00795
00796
00797 result->initPlan = list_concat(plan->scan.plan.initPlan,
00798 result->initPlan);
00799
00800
00801
00802
00803
00804
00805
00806 forboth(lp, plan->scan.plan.targetlist, lc, result->targetlist)
00807 {
00808 TargetEntry *ptle = (TargetEntry *) lfirst(lp);
00809 TargetEntry *ctle = (TargetEntry *) lfirst(lc);
00810
00811 ctle->resname = ptle->resname;
00812 ctle->resorigtbl = ptle->resorigtbl;
00813 ctle->resorigcol = ptle->resorigcol;
00814 }
00815 }
00816 else
00817 {
00818
00819
00820
00821
00822
00823
00824
00825 plan->scan.scanrelid += rtoffset;
00826 plan->scan.plan.targetlist =
00827 fix_scan_list(root, plan->scan.plan.targetlist, rtoffset);
00828 plan->scan.plan.qual =
00829 fix_scan_list(root, plan->scan.plan.qual, rtoffset);
00830
00831 result = (Plan *) plan;
00832 }
00833
00834 return result;
00835 }
00836
00837
00838
00839
00840
00841
00842
00843
00844 static bool
00845 trivial_subqueryscan(SubqueryScan *plan)
00846 {
00847 int attrno;
00848 ListCell *lp,
00849 *lc;
00850
00851 if (plan->scan.plan.qual != NIL)
00852 return false;
00853
00854 if (list_length(plan->scan.plan.targetlist) !=
00855 list_length(plan->subplan->targetlist))
00856 return false;
00857
00858 attrno = 1;
00859 forboth(lp, plan->scan.plan.targetlist, lc, plan->subplan->targetlist)
00860 {
00861 TargetEntry *ptle = (TargetEntry *) lfirst(lp);
00862 TargetEntry *ctle = (TargetEntry *) lfirst(lc);
00863
00864 if (ptle->resjunk != ctle->resjunk)
00865 return false;
00866
00867
00868
00869
00870
00871
00872 if (ptle->expr && IsA(ptle->expr, Var))
00873 {
00874 Var *var = (Var *) ptle->expr;
00875
00876 Assert(var->varno == plan->scan.scanrelid);
00877 Assert(var->varlevelsup == 0);
00878 if (var->varattno != attrno)
00879 return false;
00880 }
00881 else if (ptle->expr && IsA(ptle->expr, Const))
00882 {
00883 if (!equal(ptle->expr, ctle->expr))
00884 return false;
00885 }
00886 else
00887 return false;
00888
00889 attrno++;
00890 }
00891
00892 return true;
00893 }
00894
00895
00896
00897
00898
00899
00900
00901
00902 static inline Var *
00903 copyVar(Var *var)
00904 {
00905 Var *newvar = (Var *) palloc(sizeof(Var));
00906
00907 *newvar = *var;
00908 return newvar;
00909 }
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923 static void
00924 fix_expr_common(PlannerInfo *root, Node *node)
00925 {
00926
00927 if (IsA(node, Aggref))
00928 {
00929 record_plan_function_dependency(root,
00930 ((Aggref *) node)->aggfnoid);
00931 }
00932 else if (IsA(node, WindowFunc))
00933 {
00934 record_plan_function_dependency(root,
00935 ((WindowFunc *) node)->winfnoid);
00936 }
00937 else if (IsA(node, FuncExpr))
00938 {
00939 record_plan_function_dependency(root,
00940 ((FuncExpr *) node)->funcid);
00941 }
00942 else if (IsA(node, OpExpr))
00943 {
00944 set_opfuncid((OpExpr *) node);
00945 record_plan_function_dependency(root,
00946 ((OpExpr *) node)->opfuncid);
00947 }
00948 else if (IsA(node, DistinctExpr))
00949 {
00950 set_opfuncid((OpExpr *) node);
00951 record_plan_function_dependency(root,
00952 ((DistinctExpr *) node)->opfuncid);
00953 }
00954 else if (IsA(node, NullIfExpr))
00955 {
00956 set_opfuncid((OpExpr *) node);
00957 record_plan_function_dependency(root,
00958 ((NullIfExpr *) node)->opfuncid);
00959 }
00960 else if (IsA(node, ScalarArrayOpExpr))
00961 {
00962 set_sa_opfuncid((ScalarArrayOpExpr *) node);
00963 record_plan_function_dependency(root,
00964 ((ScalarArrayOpExpr *) node)->opfuncid);
00965 }
00966 else if (IsA(node, ArrayCoerceExpr))
00967 {
00968 if (OidIsValid(((ArrayCoerceExpr *) node)->elemfuncid))
00969 record_plan_function_dependency(root,
00970 ((ArrayCoerceExpr *) node)->elemfuncid);
00971 }
00972 else if (IsA(node, Const))
00973 {
00974 Const *con = (Const *) node;
00975
00976
00977 if (ISREGCLASSCONST(con))
00978 root->glob->relationOids =
00979 lappend_oid(root->glob->relationOids,
00980 DatumGetObjectId(con->constvalue));
00981 }
00982 }
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992 static Node *
00993 fix_scan_expr(PlannerInfo *root, Node *node, int rtoffset)
00994 {
00995 fix_scan_expr_context context;
00996
00997 context.root = root;
00998 context.rtoffset = rtoffset;
00999
01000 if (rtoffset != 0 || root->glob->lastPHId != 0)
01001 {
01002 return fix_scan_expr_mutator(node, &context);
01003 }
01004 else
01005 {
01006
01007
01008
01009
01010
01011
01012
01013
01014 (void) fix_scan_expr_walker(node, &context);
01015 return node;
01016 }
01017 }
01018
01019 static Node *
01020 fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context)
01021 {
01022 if (node == NULL)
01023 return NULL;
01024 if (IsA(node, Var))
01025 {
01026 Var *var = copyVar((Var *) node);
01027
01028 Assert(var->varlevelsup == 0);
01029
01030
01031
01032
01033
01034 Assert(var->varno != INNER_VAR);
01035 Assert(var->varno != OUTER_VAR);
01036 if (!IS_SPECIAL_VARNO(var->varno))
01037 var->varno += context->rtoffset;
01038 if (var->varnoold > 0)
01039 var->varnoold += context->rtoffset;
01040 return (Node *) var;
01041 }
01042 if (IsA(node, CurrentOfExpr))
01043 {
01044 CurrentOfExpr *cexpr = (CurrentOfExpr *) copyObject(node);
01045
01046 Assert(cexpr->cvarno != INNER_VAR);
01047 Assert(cexpr->cvarno != OUTER_VAR);
01048 if (!IS_SPECIAL_VARNO(cexpr->cvarno))
01049 cexpr->cvarno += context->rtoffset;
01050 return (Node *) cexpr;
01051 }
01052 if (IsA(node, PlaceHolderVar))
01053 {
01054
01055 PlaceHolderVar *phv = (PlaceHolderVar *) node;
01056
01057 return fix_scan_expr_mutator((Node *) phv->phexpr, context);
01058 }
01059 fix_expr_common(context->root, node);
01060 return expression_tree_mutator(node, fix_scan_expr_mutator,
01061 (void *) context);
01062 }
01063
01064 static bool
01065 fix_scan_expr_walker(Node *node, fix_scan_expr_context *context)
01066 {
01067 if (node == NULL)
01068 return false;
01069 Assert(!IsA(node, PlaceHolderVar));
01070 fix_expr_common(context->root, node);
01071 return expression_tree_walker(node, fix_scan_expr_walker,
01072 (void *) context);
01073 }
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083 static void
01084 set_join_references(PlannerInfo *root, Join *join, int rtoffset)
01085 {
01086 Plan *outer_plan = join->plan.lefttree;
01087 Plan *inner_plan = join->plan.righttree;
01088 indexed_tlist *outer_itlist;
01089 indexed_tlist *inner_itlist;
01090
01091 outer_itlist = build_tlist_index(outer_plan->targetlist);
01092 inner_itlist = build_tlist_index(inner_plan->targetlist);
01093
01094
01095 join->plan.targetlist = fix_join_expr(root,
01096 join->plan.targetlist,
01097 outer_itlist,
01098 inner_itlist,
01099 (Index) 0,
01100 rtoffset);
01101 join->plan.qual = fix_join_expr(root,
01102 join->plan.qual,
01103 outer_itlist,
01104 inner_itlist,
01105 (Index) 0,
01106 rtoffset);
01107 join->joinqual = fix_join_expr(root,
01108 join->joinqual,
01109 outer_itlist,
01110 inner_itlist,
01111 (Index) 0,
01112 rtoffset);
01113
01114
01115 if (IsA(join, NestLoop))
01116 {
01117 NestLoop *nl = (NestLoop *) join;
01118 ListCell *lc;
01119
01120 foreach(lc, nl->nestParams)
01121 {
01122 NestLoopParam *nlp = (NestLoopParam *) lfirst(lc);
01123
01124 nlp->paramval = (Var *) fix_upper_expr(root,
01125 (Node *) nlp->paramval,
01126 outer_itlist,
01127 OUTER_VAR,
01128 rtoffset);
01129
01130 if (!(IsA(nlp->paramval, Var) &&
01131 nlp->paramval->varno == OUTER_VAR))
01132 elog(ERROR, "NestLoopParam was not reduced to a simple Var");
01133 }
01134 }
01135 else if (IsA(join, MergeJoin))
01136 {
01137 MergeJoin *mj = (MergeJoin *) join;
01138
01139 mj->mergeclauses = fix_join_expr(root,
01140 mj->mergeclauses,
01141 outer_itlist,
01142 inner_itlist,
01143 (Index) 0,
01144 rtoffset);
01145 }
01146 else if (IsA(join, HashJoin))
01147 {
01148 HashJoin *hj = (HashJoin *) join;
01149
01150 hj->hashclauses = fix_join_expr(root,
01151 hj->hashclauses,
01152 outer_itlist,
01153 inner_itlist,
01154 (Index) 0,
01155 rtoffset);
01156 }
01157
01158 pfree(outer_itlist);
01159 pfree(inner_itlist);
01160 }
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180 static void
01181 set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
01182 {
01183 Plan *subplan = plan->lefttree;
01184 indexed_tlist *subplan_itlist;
01185 List *output_targetlist;
01186 ListCell *l;
01187
01188 subplan_itlist = build_tlist_index(subplan->targetlist);
01189
01190 output_targetlist = NIL;
01191 foreach(l, plan->targetlist)
01192 {
01193 TargetEntry *tle = (TargetEntry *) lfirst(l);
01194 Node *newexpr;
01195
01196
01197 if (tle->ressortgroupref != 0 && !IsA(tle->expr, Var))
01198 {
01199 newexpr = (Node *)
01200 search_indexed_tlist_for_sortgroupref((Node *) tle->expr,
01201 tle->ressortgroupref,
01202 subplan_itlist,
01203 OUTER_VAR);
01204 if (!newexpr)
01205 newexpr = fix_upper_expr(root,
01206 (Node *) tle->expr,
01207 subplan_itlist,
01208 OUTER_VAR,
01209 rtoffset);
01210 }
01211 else
01212 newexpr = fix_upper_expr(root,
01213 (Node *) tle->expr,
01214 subplan_itlist,
01215 OUTER_VAR,
01216 rtoffset);
01217 tle = flatCopyTargetEntry(tle);
01218 tle->expr = (Expr *) newexpr;
01219 output_targetlist = lappend(output_targetlist, tle);
01220 }
01221 plan->targetlist = output_targetlist;
01222
01223 plan->qual = (List *)
01224 fix_upper_expr(root,
01225 (Node *) plan->qual,
01226 subplan_itlist,
01227 OUTER_VAR,
01228 rtoffset);
01229
01230 pfree(subplan_itlist);
01231 }
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246 static void
01247 set_dummy_tlist_references(Plan *plan, int rtoffset)
01248 {
01249 List *output_targetlist;
01250 ListCell *l;
01251
01252 output_targetlist = NIL;
01253 foreach(l, plan->targetlist)
01254 {
01255 TargetEntry *tle = (TargetEntry *) lfirst(l);
01256 Var *oldvar = (Var *) tle->expr;
01257 Var *newvar;
01258
01259 newvar = makeVar(OUTER_VAR,
01260 tle->resno,
01261 exprType((Node *) oldvar),
01262 exprTypmod((Node *) oldvar),
01263 exprCollation((Node *) oldvar),
01264 0);
01265 if (IsA(oldvar, Var))
01266 {
01267 newvar->varnoold = oldvar->varno + rtoffset;
01268 newvar->varoattno = oldvar->varattno;
01269 }
01270 else
01271 {
01272 newvar->varnoold = 0;
01273 newvar->varoattno = 0;
01274 }
01275
01276 tle = flatCopyTargetEntry(tle);
01277 tle->expr = (Expr *) newvar;
01278 output_targetlist = lappend(output_targetlist, tle);
01279 }
01280 plan->targetlist = output_targetlist;
01281
01282
01283 }
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299 static indexed_tlist *
01300 build_tlist_index(List *tlist)
01301 {
01302 indexed_tlist *itlist;
01303 tlist_vinfo *vinfo;
01304 ListCell *l;
01305
01306
01307 itlist = (indexed_tlist *)
01308 palloc(offsetof(indexed_tlist, vars) +
01309 list_length(tlist) * sizeof(tlist_vinfo));
01310
01311 itlist->tlist = tlist;
01312 itlist->has_ph_vars = false;
01313 itlist->has_non_vars = false;
01314
01315
01316 vinfo = itlist->vars;
01317 foreach(l, tlist)
01318 {
01319 TargetEntry *tle = (TargetEntry *) lfirst(l);
01320
01321 if (tle->expr && IsA(tle->expr, Var))
01322 {
01323 Var *var = (Var *) tle->expr;
01324
01325 vinfo->varno = var->varno;
01326 vinfo->varattno = var->varattno;
01327 vinfo->resno = tle->resno;
01328 vinfo++;
01329 }
01330 else if (tle->expr && IsA(tle->expr, PlaceHolderVar))
01331 itlist->has_ph_vars = true;
01332 else
01333 itlist->has_non_vars = true;
01334 }
01335
01336 itlist->num_vars = (vinfo - itlist->vars);
01337
01338 return itlist;
01339 }
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349 static indexed_tlist *
01350 build_tlist_index_other_vars(List *tlist, Index ignore_rel)
01351 {
01352 indexed_tlist *itlist;
01353 tlist_vinfo *vinfo;
01354 ListCell *l;
01355
01356
01357 itlist = (indexed_tlist *)
01358 palloc(offsetof(indexed_tlist, vars) +
01359 list_length(tlist) * sizeof(tlist_vinfo));
01360
01361 itlist->tlist = tlist;
01362 itlist->has_ph_vars = false;
01363 itlist->has_non_vars = false;
01364
01365
01366 vinfo = itlist->vars;
01367 foreach(l, tlist)
01368 {
01369 TargetEntry *tle = (TargetEntry *) lfirst(l);
01370
01371 if (tle->expr && IsA(tle->expr, Var))
01372 {
01373 Var *var = (Var *) tle->expr;
01374
01375 if (var->varno != ignore_rel)
01376 {
01377 vinfo->varno = var->varno;
01378 vinfo->varattno = var->varattno;
01379 vinfo->resno = tle->resno;
01380 vinfo++;
01381 }
01382 }
01383 else if (tle->expr && IsA(tle->expr, PlaceHolderVar))
01384 itlist->has_ph_vars = true;
01385 }
01386
01387 itlist->num_vars = (vinfo - itlist->vars);
01388
01389 return itlist;
01390 }
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400 static Var *
01401 search_indexed_tlist_for_var(Var *var, indexed_tlist *itlist,
01402 Index newvarno, int rtoffset)
01403 {
01404 Index varno = var->varno;
01405 AttrNumber varattno = var->varattno;
01406 tlist_vinfo *vinfo;
01407 int i;
01408
01409 vinfo = itlist->vars;
01410 i = itlist->num_vars;
01411 while (i-- > 0)
01412 {
01413 if (vinfo->varno == varno && vinfo->varattno == varattno)
01414 {
01415
01416 Var *newvar = copyVar(var);
01417
01418 newvar->varno = newvarno;
01419 newvar->varattno = vinfo->resno;
01420 if (newvar->varnoold > 0)
01421 newvar->varnoold += rtoffset;
01422 return newvar;
01423 }
01424 vinfo++;
01425 }
01426 return NULL;
01427 }
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438 static Var *
01439 search_indexed_tlist_for_non_var(Node *node,
01440 indexed_tlist *itlist, Index newvarno)
01441 {
01442 TargetEntry *tle;
01443
01444 tle = tlist_member(node, itlist->tlist);
01445 if (tle)
01446 {
01447
01448 Var *newvar;
01449
01450 newvar = makeVarFromTargetEntry(newvarno, tle);
01451 newvar->varnoold = 0;
01452 newvar->varoattno = 0;
01453 return newvar;
01454 }
01455 return NULL;
01456 }
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469 static Var *
01470 search_indexed_tlist_for_sortgroupref(Node *node,
01471 Index sortgroupref,
01472 indexed_tlist *itlist,
01473 Index newvarno)
01474 {
01475 ListCell *lc;
01476
01477 foreach(lc, itlist->tlist)
01478 {
01479 TargetEntry *tle = (TargetEntry *) lfirst(lc);
01480
01481
01482 if (tle->ressortgroupref == sortgroupref &&
01483 equal(node, tle->expr))
01484 {
01485
01486 Var *newvar;
01487
01488 newvar = makeVarFromTargetEntry(newvarno, tle);
01489 newvar->varnoold = 0;
01490 newvar->varoattno = 0;
01491 return newvar;
01492 }
01493 }
01494 return NULL;
01495 }
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527 static List *
01528 fix_join_expr(PlannerInfo *root,
01529 List *clauses,
01530 indexed_tlist *outer_itlist,
01531 indexed_tlist *inner_itlist,
01532 Index acceptable_rel,
01533 int rtoffset)
01534 {
01535 fix_join_expr_context context;
01536
01537 context.root = root;
01538 context.outer_itlist = outer_itlist;
01539 context.inner_itlist = inner_itlist;
01540 context.acceptable_rel = acceptable_rel;
01541 context.rtoffset = rtoffset;
01542 return (List *) fix_join_expr_mutator((Node *) clauses, &context);
01543 }
01544
01545 static Node *
01546 fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
01547 {
01548 Var *newvar;
01549
01550 if (node == NULL)
01551 return NULL;
01552 if (IsA(node, Var))
01553 {
01554 Var *var = (Var *) node;
01555
01556
01557 newvar = search_indexed_tlist_for_var(var,
01558 context->outer_itlist,
01559 OUTER_VAR,
01560 context->rtoffset);
01561 if (newvar)
01562 return (Node *) newvar;
01563 if (context->inner_itlist)
01564 {
01565 newvar = search_indexed_tlist_for_var(var,
01566 context->inner_itlist,
01567 INNER_VAR,
01568 context->rtoffset);
01569 if (newvar)
01570 return (Node *) newvar;
01571 }
01572
01573
01574 if (var->varno == context->acceptable_rel)
01575 {
01576 var = copyVar(var);
01577 var->varno += context->rtoffset;
01578 if (var->varnoold > 0)
01579 var->varnoold += context->rtoffset;
01580 return (Node *) var;
01581 }
01582
01583
01584 elog(ERROR, "variable not found in subplan target lists");
01585 }
01586 if (IsA(node, PlaceHolderVar))
01587 {
01588 PlaceHolderVar *phv = (PlaceHolderVar *) node;
01589
01590
01591 if (context->outer_itlist->has_ph_vars)
01592 {
01593 newvar = search_indexed_tlist_for_non_var((Node *) phv,
01594 context->outer_itlist,
01595 OUTER_VAR);
01596 if (newvar)
01597 return (Node *) newvar;
01598 }
01599 if (context->inner_itlist && context->inner_itlist->has_ph_vars)
01600 {
01601 newvar = search_indexed_tlist_for_non_var((Node *) phv,
01602 context->inner_itlist,
01603 INNER_VAR);
01604 if (newvar)
01605 return (Node *) newvar;
01606 }
01607
01608
01609 return fix_join_expr_mutator((Node *) phv->phexpr, context);
01610 }
01611
01612 if (context->outer_itlist->has_non_vars)
01613 {
01614 newvar = search_indexed_tlist_for_non_var(node,
01615 context->outer_itlist,
01616 OUTER_VAR);
01617 if (newvar)
01618 return (Node *) newvar;
01619 }
01620 if (context->inner_itlist && context->inner_itlist->has_non_vars)
01621 {
01622 newvar = search_indexed_tlist_for_non_var(node,
01623 context->inner_itlist,
01624 INNER_VAR);
01625 if (newvar)
01626 return (Node *) newvar;
01627 }
01628 fix_expr_common(context->root, node);
01629 return expression_tree_mutator(node,
01630 fix_join_expr_mutator,
01631 (void *) context);
01632 }
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662 static Node *
01663 fix_upper_expr(PlannerInfo *root,
01664 Node *node,
01665 indexed_tlist *subplan_itlist,
01666 Index newvarno,
01667 int rtoffset)
01668 {
01669 fix_upper_expr_context context;
01670
01671 context.root = root;
01672 context.subplan_itlist = subplan_itlist;
01673 context.newvarno = newvarno;
01674 context.rtoffset = rtoffset;
01675 return fix_upper_expr_mutator(node, &context);
01676 }
01677
01678 static Node *
01679 fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
01680 {
01681 Var *newvar;
01682
01683 if (node == NULL)
01684 return NULL;
01685 if (IsA(node, Var))
01686 {
01687 Var *var = (Var *) node;
01688
01689 newvar = search_indexed_tlist_for_var(var,
01690 context->subplan_itlist,
01691 context->newvarno,
01692 context->rtoffset);
01693 if (!newvar)
01694 elog(ERROR, "variable not found in subplan target list");
01695 return (Node *) newvar;
01696 }
01697 if (IsA(node, PlaceHolderVar))
01698 {
01699 PlaceHolderVar *phv = (PlaceHolderVar *) node;
01700
01701
01702 if (context->subplan_itlist->has_ph_vars)
01703 {
01704 newvar = search_indexed_tlist_for_non_var((Node *) phv,
01705 context->subplan_itlist,
01706 context->newvarno);
01707 if (newvar)
01708 return (Node *) newvar;
01709 }
01710
01711 return fix_upper_expr_mutator((Node *) phv->phexpr, context);
01712 }
01713
01714 if (context->subplan_itlist->has_non_vars)
01715 {
01716 newvar = search_indexed_tlist_for_non_var(node,
01717 context->subplan_itlist,
01718 context->newvarno);
01719 if (newvar)
01720 return (Node *) newvar;
01721 }
01722 fix_expr_common(context->root, node);
01723 return expression_tree_mutator(node,
01724 fix_upper_expr_mutator,
01725 (void *) context);
01726 }
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756 static List *
01757 set_returning_clause_references(PlannerInfo *root,
01758 List *rlist,
01759 Plan *topplan,
01760 Index resultRelation,
01761 int rtoffset)
01762 {
01763 indexed_tlist *itlist;
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779 itlist = build_tlist_index_other_vars(topplan->targetlist, resultRelation);
01780
01781 rlist = fix_join_expr(root,
01782 rlist,
01783 itlist,
01784 NULL,
01785 resultRelation,
01786 rtoffset);
01787
01788 pfree(itlist);
01789
01790 return rlist;
01791 }
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806 void
01807 fix_opfuncids(Node *node)
01808 {
01809
01810 fix_opfuncids_walker(node, NULL);
01811 }
01812
01813 static bool
01814 fix_opfuncids_walker(Node *node, void *context)
01815 {
01816 if (node == NULL)
01817 return false;
01818 if (IsA(node, OpExpr))
01819 set_opfuncid((OpExpr *) node);
01820 else if (IsA(node, DistinctExpr))
01821 set_opfuncid((OpExpr *) node);
01822 else if (IsA(node, NullIfExpr))
01823 set_opfuncid((OpExpr *) node);
01824 else if (IsA(node, ScalarArrayOpExpr))
01825 set_sa_opfuncid((ScalarArrayOpExpr *) node);
01826 return expression_tree_walker(node, fix_opfuncids_walker, context);
01827 }
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837 void
01838 set_opfuncid(OpExpr *opexpr)
01839 {
01840 if (opexpr->opfuncid == InvalidOid)
01841 opexpr->opfuncid = get_opcode(opexpr->opno);
01842 }
01843
01844
01845
01846
01847
01848 void
01849 set_sa_opfuncid(ScalarArrayOpExpr *opexpr)
01850 {
01851 if (opexpr->opfuncid == InvalidOid)
01852 opexpr->opfuncid = get_opcode(opexpr->opno);
01853 }
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866 void
01867 record_plan_function_dependency(PlannerInfo *root, Oid funcid)
01868 {
01869
01870
01871
01872
01873
01874
01875
01876
01877 if (funcid >= (Oid) FirstBootstrapObjectId)
01878 {
01879 PlanInvalItem *inval_item = makeNode(PlanInvalItem);
01880
01881
01882
01883
01884
01885
01886 inval_item->cacheId = PROCOID;
01887 inval_item->hashValue = GetSysCacheHashValue1(PROCOID,
01888 ObjectIdGetDatum(funcid));
01889
01890 root->glob->invalItems = lappend(root->glob->invalItems, inval_item);
01891 }
01892 }
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903 void
01904 extract_query_dependencies(Node *query,
01905 List **relationOids,
01906 List **invalItems)
01907 {
01908 PlannerGlobal glob;
01909 PlannerInfo root;
01910
01911
01912 MemSet(&glob, 0, sizeof(glob));
01913 glob.type = T_PlannerGlobal;
01914 glob.relationOids = NIL;
01915 glob.invalItems = NIL;
01916
01917 MemSet(&root, 0, sizeof(root));
01918 root.type = T_PlannerInfo;
01919 root.glob = &glob;
01920
01921 (void) extract_query_dependencies_walker(query, &root);
01922
01923 *relationOids = glob.relationOids;
01924 *invalItems = glob.invalItems;
01925 }
01926
01927 static bool
01928 extract_query_dependencies_walker(Node *node, PlannerInfo *context)
01929 {
01930 if (node == NULL)
01931 return false;
01932 Assert(!IsA(node, PlaceHolderVar));
01933
01934 fix_expr_common(context, node);
01935 if (IsA(node, Query))
01936 {
01937 Query *query = (Query *) node;
01938 ListCell *lc;
01939
01940 if (query->commandType == CMD_UTILITY)
01941 {
01942
01943
01944
01945
01946 query = UtilityContainsQuery(query->utilityStmt);
01947 if (query == NULL)
01948 return false;
01949 }
01950
01951
01952 foreach(lc, query->rtable)
01953 {
01954 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
01955
01956 if (rte->rtekind == RTE_RELATION)
01957 context->glob->relationOids =
01958 lappend_oid(context->glob->relationOids, rte->relid);
01959 }
01960
01961
01962 return query_tree_walker(query, extract_query_dependencies_walker,
01963 (void *) context, 0);
01964 }
01965 return expression_tree_walker(node, extract_query_dependencies_walker,
01966 (void *) context);
01967 }