00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "postgres.h"
00022
00023 #include "access/sysattr.h"
00024 #include "nodes/nodeFuncs.h"
00025 #include "optimizer/prep.h"
00026 #include "optimizer/var.h"
00027 #include "parser/parsetree.h"
00028 #include "rewrite/rewriteManip.h"
00029
00030
00031 typedef struct
00032 {
00033 Relids varnos;
00034 int sublevels_up;
00035 } pull_varnos_context;
00036
00037 typedef struct
00038 {
00039 Bitmapset *varattnos;
00040 Index varno;
00041 } pull_varattnos_context;
00042
00043 typedef struct
00044 {
00045 List *vars;
00046 int sublevels_up;
00047 } pull_vars_context;
00048
00049 typedef struct
00050 {
00051 int var_location;
00052 int sublevels_up;
00053 } locate_var_of_level_context;
00054
00055 typedef struct
00056 {
00057 List *varlist;
00058 PVCAggregateBehavior aggbehavior;
00059 PVCPlaceHolderBehavior phbehavior;
00060 } pull_var_clause_context;
00061
00062 typedef struct
00063 {
00064 PlannerInfo *root;
00065 int sublevels_up;
00066 bool possible_sublink;
00067 bool inserted_sublink;
00068 } flatten_join_alias_vars_context;
00069
00070 static bool pull_varnos_walker(Node *node,
00071 pull_varnos_context *context);
00072 static bool pull_varattnos_walker(Node *node, pull_varattnos_context *context);
00073 static bool pull_vars_walker(Node *node, pull_vars_context *context);
00074 static bool contain_var_clause_walker(Node *node, void *context);
00075 static bool contain_vars_of_level_walker(Node *node, int *sublevels_up);
00076 static bool locate_var_of_level_walker(Node *node,
00077 locate_var_of_level_context *context);
00078 static bool pull_var_clause_walker(Node *node,
00079 pull_var_clause_context *context);
00080 static Node *flatten_join_alias_vars_mutator(Node *node,
00081 flatten_join_alias_vars_context *context);
00082 static Relids alias_relid_set(PlannerInfo *root, Relids relids);
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 Relids
00096 pull_varnos(Node *node)
00097 {
00098 pull_varnos_context context;
00099
00100 context.varnos = NULL;
00101 context.sublevels_up = 0;
00102
00103
00104
00105
00106
00107 query_or_expression_tree_walker(node,
00108 pull_varnos_walker,
00109 (void *) &context,
00110 0);
00111
00112 return context.varnos;
00113 }
00114
00115
00116
00117
00118
00119
00120 Relids
00121 pull_varnos_of_level(Node *node, int levelsup)
00122 {
00123 pull_varnos_context context;
00124
00125 context.varnos = NULL;
00126 context.sublevels_up = levelsup;
00127
00128
00129
00130
00131
00132 query_or_expression_tree_walker(node,
00133 pull_varnos_walker,
00134 (void *) &context,
00135 0);
00136
00137 return context.varnos;
00138 }
00139
00140 static bool
00141 pull_varnos_walker(Node *node, pull_varnos_context *context)
00142 {
00143 if (node == NULL)
00144 return false;
00145 if (IsA(node, Var))
00146 {
00147 Var *var = (Var *) node;
00148
00149 if (var->varlevelsup == context->sublevels_up)
00150 context->varnos = bms_add_member(context->varnos, var->varno);
00151 return false;
00152 }
00153 if (IsA(node, CurrentOfExpr))
00154 {
00155 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
00156
00157 if (context->sublevels_up == 0)
00158 context->varnos = bms_add_member(context->varnos, cexpr->cvarno);
00159 return false;
00160 }
00161 if (IsA(node, PlaceHolderVar))
00162 {
00163
00164
00165
00166
00167 PlaceHolderVar *phv = (PlaceHolderVar *) node;
00168 pull_varnos_context subcontext;
00169
00170 subcontext.varnos = NULL;
00171 subcontext.sublevels_up = context->sublevels_up;
00172 (void) pull_varnos_walker((Node *) phv->phexpr, &subcontext);
00173
00174 if (bms_is_empty(subcontext.varnos) &&
00175 phv->phlevelsup == context->sublevels_up)
00176 context->varnos = bms_add_members(context->varnos, phv->phrels);
00177 else
00178 context->varnos = bms_join(context->varnos, subcontext.varnos);
00179 return false;
00180 }
00181 if (IsA(node, Query))
00182 {
00183
00184 bool result;
00185
00186 context->sublevels_up++;
00187 result = query_tree_walker((Query *) node, pull_varnos_walker,
00188 (void *) context, 0);
00189 context->sublevels_up--;
00190 return result;
00191 }
00192 return expression_tree_walker(node, pull_varnos_walker,
00193 (void *) context);
00194 }
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 void
00212 pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
00213 {
00214 pull_varattnos_context context;
00215
00216 context.varattnos = *varattnos;
00217 context.varno = varno;
00218
00219 (void) pull_varattnos_walker(node, &context);
00220
00221 *varattnos = context.varattnos;
00222 }
00223
00224 static bool
00225 pull_varattnos_walker(Node *node, pull_varattnos_context *context)
00226 {
00227 if (node == NULL)
00228 return false;
00229 if (IsA(node, Var))
00230 {
00231 Var *var = (Var *) node;
00232
00233 if (var->varno == context->varno && var->varlevelsup == 0)
00234 context->varattnos =
00235 bms_add_member(context->varattnos,
00236 var->varattno - FirstLowInvalidHeapAttributeNumber);
00237 return false;
00238 }
00239
00240
00241 Assert(!IsA(node, Query));
00242
00243 return expression_tree_walker(node, pull_varattnos_walker,
00244 (void *) context);
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 List *
00256 pull_vars_of_level(Node *node, int levelsup)
00257 {
00258 pull_vars_context context;
00259
00260 context.vars = NIL;
00261 context.sublevels_up = levelsup;
00262
00263
00264
00265
00266
00267 query_or_expression_tree_walker(node,
00268 pull_vars_walker,
00269 (void *) &context,
00270 0);
00271
00272 return context.vars;
00273 }
00274
00275 static bool
00276 pull_vars_walker(Node *node, pull_vars_context *context)
00277 {
00278 if (node == NULL)
00279 return false;
00280 if (IsA(node, Var))
00281 {
00282 Var *var = (Var *) node;
00283
00284 if (var->varlevelsup == context->sublevels_up)
00285 context->vars = lappend(context->vars, var);
00286 return false;
00287 }
00288 if (IsA(node, PlaceHolderVar))
00289 {
00290 PlaceHolderVar *phv = (PlaceHolderVar *) node;
00291
00292 if (phv->phlevelsup == context->sublevels_up)
00293 context->vars = lappend(context->vars, phv);
00294
00295 return false;
00296 }
00297 if (IsA(node, Query))
00298 {
00299
00300 bool result;
00301
00302 context->sublevels_up++;
00303 result = query_tree_walker((Query *) node, pull_vars_walker,
00304 (void *) context, 0);
00305 context->sublevels_up--;
00306 return result;
00307 }
00308 return expression_tree_walker(node, pull_vars_walker,
00309 (void *) context);
00310 }
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 bool
00324 contain_var_clause(Node *node)
00325 {
00326 return contain_var_clause_walker(node, NULL);
00327 }
00328
00329 static bool
00330 contain_var_clause_walker(Node *node, void *context)
00331 {
00332 if (node == NULL)
00333 return false;
00334 if (IsA(node, Var))
00335 {
00336 if (((Var *) node)->varlevelsup == 0)
00337 return true;
00338 return false;
00339 }
00340 if (IsA(node, CurrentOfExpr))
00341 return true;
00342 if (IsA(node, PlaceHolderVar))
00343 {
00344 if (((PlaceHolderVar *) node)->phlevelsup == 0)
00345 return true;
00346
00347 }
00348 return expression_tree_walker(node, contain_var_clause_walker, context);
00349 }
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 bool
00362 contain_vars_of_level(Node *node, int levelsup)
00363 {
00364 int sublevels_up = levelsup;
00365
00366 return query_or_expression_tree_walker(node,
00367 contain_vars_of_level_walker,
00368 (void *) &sublevels_up,
00369 0);
00370 }
00371
00372 static bool
00373 contain_vars_of_level_walker(Node *node, int *sublevels_up)
00374 {
00375 if (node == NULL)
00376 return false;
00377 if (IsA(node, Var))
00378 {
00379 if (((Var *) node)->varlevelsup == *sublevels_up)
00380 return true;
00381 return false;
00382 }
00383 if (IsA(node, CurrentOfExpr))
00384 {
00385 if (*sublevels_up == 0)
00386 return true;
00387 return false;
00388 }
00389 if (IsA(node, PlaceHolderVar))
00390 {
00391 if (((PlaceHolderVar *) node)->phlevelsup == *sublevels_up)
00392 return true;
00393
00394 }
00395 if (IsA(node, Query))
00396 {
00397
00398 bool result;
00399
00400 (*sublevels_up)++;
00401 result = query_tree_walker((Query *) node,
00402 contain_vars_of_level_walker,
00403 (void *) sublevels_up,
00404 0);
00405 (*sublevels_up)--;
00406 return result;
00407 }
00408 return expression_tree_walker(node,
00409 contain_vars_of_level_walker,
00410 (void *) sublevels_up);
00411 }
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429 int
00430 locate_var_of_level(Node *node, int levelsup)
00431 {
00432 locate_var_of_level_context context;
00433
00434 context.var_location = -1;
00435 context.sublevels_up = levelsup;
00436
00437 (void) query_or_expression_tree_walker(node,
00438 locate_var_of_level_walker,
00439 (void *) &context,
00440 0);
00441
00442 return context.var_location;
00443 }
00444
00445 static bool
00446 locate_var_of_level_walker(Node *node,
00447 locate_var_of_level_context *context)
00448 {
00449 if (node == NULL)
00450 return false;
00451 if (IsA(node, Var))
00452 {
00453 Var *var = (Var *) node;
00454
00455 if (var->varlevelsup == context->sublevels_up &&
00456 var->location >= 0)
00457 {
00458 context->var_location = var->location;
00459 return true;
00460 }
00461 return false;
00462 }
00463 if (IsA(node, CurrentOfExpr))
00464 {
00465
00466 return false;
00467 }
00468
00469 if (IsA(node, Query))
00470 {
00471
00472 bool result;
00473
00474 context->sublevels_up++;
00475 result = query_tree_walker((Query *) node,
00476 locate_var_of_level_walker,
00477 (void *) context,
00478 0);
00479 context->sublevels_up--;
00480 return result;
00481 }
00482 return expression_tree_walker(node,
00483 locate_var_of_level_walker,
00484 (void *) context);
00485 }
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515 List *
00516 pull_var_clause(Node *node, PVCAggregateBehavior aggbehavior,
00517 PVCPlaceHolderBehavior phbehavior)
00518 {
00519 pull_var_clause_context context;
00520
00521 context.varlist = NIL;
00522 context.aggbehavior = aggbehavior;
00523 context.phbehavior = phbehavior;
00524
00525 pull_var_clause_walker(node, &context);
00526 return context.varlist;
00527 }
00528
00529 static bool
00530 pull_var_clause_walker(Node *node, pull_var_clause_context *context)
00531 {
00532 if (node == NULL)
00533 return false;
00534 if (IsA(node, Var))
00535 {
00536 if (((Var *) node)->varlevelsup != 0)
00537 elog(ERROR, "Upper-level Var found where not expected");
00538 context->varlist = lappend(context->varlist, node);
00539 return false;
00540 }
00541 else if (IsA(node, Aggref))
00542 {
00543 if (((Aggref *) node)->agglevelsup != 0)
00544 elog(ERROR, "Upper-level Aggref found where not expected");
00545 switch (context->aggbehavior)
00546 {
00547 case PVC_REJECT_AGGREGATES:
00548 elog(ERROR, "Aggref found where not expected");
00549 break;
00550 case PVC_INCLUDE_AGGREGATES:
00551 context->varlist = lappend(context->varlist, node);
00552
00553 return false;
00554 case PVC_RECURSE_AGGREGATES:
00555
00556 break;
00557 }
00558 }
00559 else if (IsA(node, PlaceHolderVar))
00560 {
00561 if (((PlaceHolderVar *) node)->phlevelsup != 0)
00562 elog(ERROR, "Upper-level PlaceHolderVar found where not expected");
00563 switch (context->phbehavior)
00564 {
00565 case PVC_REJECT_PLACEHOLDERS:
00566 elog(ERROR, "PlaceHolderVar found where not expected");
00567 break;
00568 case PVC_INCLUDE_PLACEHOLDERS:
00569 context->varlist = lappend(context->varlist, node);
00570
00571 return false;
00572 case PVC_RECURSE_PLACEHOLDERS:
00573
00574 break;
00575 }
00576 }
00577 return expression_tree_walker(node, pull_var_clause_walker,
00578 (void *) context);
00579 }
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607 Node *
00608 flatten_join_alias_vars(PlannerInfo *root, Node *node)
00609 {
00610 flatten_join_alias_vars_context context;
00611
00612 context.root = root;
00613 context.sublevels_up = 0;
00614
00615 context.possible_sublink = root->parse->hasSubLinks;
00616
00617 context.inserted_sublink = root->parse->hasSubLinks;
00618
00619 return flatten_join_alias_vars_mutator(node, &context);
00620 }
00621
00622 static Node *
00623 flatten_join_alias_vars_mutator(Node *node,
00624 flatten_join_alias_vars_context *context)
00625 {
00626 if (node == NULL)
00627 return NULL;
00628 if (IsA(node, Var))
00629 {
00630 Var *var = (Var *) node;
00631 RangeTblEntry *rte;
00632 Node *newvar;
00633
00634
00635 if (var->varlevelsup != context->sublevels_up)
00636 return node;
00637 rte = rt_fetch(var->varno, context->root->parse->rtable);
00638 if (rte->rtekind != RTE_JOIN)
00639 return node;
00640 if (var->varattno == InvalidAttrNumber)
00641 {
00642
00643 RowExpr *rowexpr;
00644 List *fields = NIL;
00645 List *colnames = NIL;
00646 AttrNumber attnum;
00647 ListCell *lv;
00648 ListCell *ln;
00649
00650 attnum = 0;
00651 Assert(list_length(rte->joinaliasvars) == list_length(rte->eref->colnames));
00652 forboth(lv, rte->joinaliasvars, ln, rte->eref->colnames)
00653 {
00654 newvar = (Node *) lfirst(lv);
00655 attnum++;
00656
00657 if (IsA(newvar, Const))
00658 continue;
00659 newvar = copyObject(newvar);
00660
00661
00662
00663
00664
00665 if (context->sublevels_up != 0)
00666 IncrementVarSublevelsUp(newvar, context->sublevels_up, 0);
00667
00668 if (IsA(newvar, Var))
00669 ((Var *) newvar)->location = var->location;
00670
00671
00672 newvar = flatten_join_alias_vars_mutator(newvar, context);
00673 fields = lappend(fields, newvar);
00674
00675 colnames = lappend(colnames, copyObject((Node *) lfirst(ln)));
00676 }
00677 rowexpr = makeNode(RowExpr);
00678 rowexpr->args = fields;
00679 rowexpr->row_typeid = var->vartype;
00680 rowexpr->row_format = COERCE_IMPLICIT_CAST;
00681 rowexpr->colnames = colnames;
00682 rowexpr->location = var->location;
00683
00684 return (Node *) rowexpr;
00685 }
00686
00687
00688 Assert(var->varattno > 0);
00689 newvar = (Node *) list_nth(rte->joinaliasvars, var->varattno - 1);
00690 newvar = copyObject(newvar);
00691
00692
00693
00694
00695
00696 if (context->sublevels_up != 0)
00697 IncrementVarSublevelsUp(newvar, context->sublevels_up, 0);
00698
00699
00700 if (IsA(newvar, Var))
00701 ((Var *) newvar)->location = var->location;
00702
00703
00704 newvar = flatten_join_alias_vars_mutator(newvar, context);
00705
00706
00707 if (context->possible_sublink && !context->inserted_sublink)
00708 context->inserted_sublink = checkExprHasSubLink(newvar);
00709
00710 return newvar;
00711 }
00712 if (IsA(node, PlaceHolderVar))
00713 {
00714
00715 PlaceHolderVar *phv;
00716
00717 phv = (PlaceHolderVar *) expression_tree_mutator(node,
00718 flatten_join_alias_vars_mutator,
00719 (void *) context);
00720
00721 if (phv->phlevelsup == context->sublevels_up)
00722 {
00723 phv->phrels = alias_relid_set(context->root,
00724 phv->phrels);
00725 }
00726 return (Node *) phv;
00727 }
00728
00729 if (IsA(node, Query))
00730 {
00731
00732 Query *newnode;
00733 bool save_inserted_sublink;
00734
00735 context->sublevels_up++;
00736 save_inserted_sublink = context->inserted_sublink;
00737 context->inserted_sublink = ((Query *) node)->hasSubLinks;
00738 newnode = query_tree_mutator((Query *) node,
00739 flatten_join_alias_vars_mutator,
00740 (void *) context,
00741 QTW_IGNORE_JOINALIASES);
00742 newnode->hasSubLinks |= context->inserted_sublink;
00743 context->inserted_sublink = save_inserted_sublink;
00744 context->sublevels_up--;
00745 return (Node *) newnode;
00746 }
00747
00748 Assert(!IsA(node, SubPlan));
00749
00750 Assert(!IsA(node, SpecialJoinInfo));
00751 Assert(!IsA(node, LateralJoinInfo));
00752 Assert(!IsA(node, PlaceHolderInfo));
00753 Assert(!IsA(node, MinMaxAggInfo));
00754
00755 return expression_tree_mutator(node, flatten_join_alias_vars_mutator,
00756 (void *) context);
00757 }
00758
00759
00760
00761
00762
00763 static Relids
00764 alias_relid_set(PlannerInfo *root, Relids relids)
00765 {
00766 Relids result = NULL;
00767 Relids tmprelids;
00768 int rtindex;
00769
00770 tmprelids = bms_copy(relids);
00771 while ((rtindex = bms_first_member(tmprelids)) >= 0)
00772 {
00773 RangeTblEntry *rte = rt_fetch(rtindex, root->parse->rtable);
00774
00775 if (rte->rtekind == RTE_JOIN)
00776 result = bms_join(result, get_relids_for_join(root, rtindex));
00777 else
00778 result = bms_add_member(result, rtindex);
00779 }
00780 bms_free(tmprelids);
00781 return result;
00782 }