00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "postgres.h"
00015
00016 #include "catalog/pg_type.h"
00017 #include "nodes/makefuncs.h"
00018 #include "nodes/nodeFuncs.h"
00019 #include "nodes/plannodes.h"
00020 #include "optimizer/clauses.h"
00021 #include "parser/parse_coerce.h"
00022 #include "parser/parse_relation.h"
00023 #include "parser/parsetree.h"
00024 #include "rewrite/rewriteManip.h"
00025
00026
00027 typedef struct
00028 {
00029 int sublevels_up;
00030 } contain_aggs_of_level_context;
00031
00032 typedef struct
00033 {
00034 int agg_location;
00035 int sublevels_up;
00036 } locate_agg_of_level_context;
00037
00038 typedef struct
00039 {
00040 int win_location;
00041 } locate_windowfunc_context;
00042
00043 static bool contain_aggs_of_level_walker(Node *node,
00044 contain_aggs_of_level_context *context);
00045 static bool locate_agg_of_level_walker(Node *node,
00046 locate_agg_of_level_context *context);
00047 static bool contain_windowfuncs_walker(Node *node, void *context);
00048 static bool locate_windowfunc_walker(Node *node,
00049 locate_windowfunc_context *context);
00050 static bool checkExprHasSubLink_walker(Node *node, void *context);
00051 static Relids offset_relid_set(Relids relids, int offset);
00052 static Relids adjust_relid_set(Relids relids, int oldrelid, int newrelid);
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 bool
00067 contain_aggs_of_level(Node *node, int levelsup)
00068 {
00069 contain_aggs_of_level_context context;
00070
00071 context.sublevels_up = levelsup;
00072
00073
00074
00075
00076
00077 return query_or_expression_tree_walker(node,
00078 contain_aggs_of_level_walker,
00079 (void *) &context,
00080 0);
00081 }
00082
00083 static bool
00084 contain_aggs_of_level_walker(Node *node,
00085 contain_aggs_of_level_context *context)
00086 {
00087 if (node == NULL)
00088 return false;
00089 if (IsA(node, Aggref))
00090 {
00091 if (((Aggref *) node)->agglevelsup == context->sublevels_up)
00092 return true;
00093
00094 }
00095 if (IsA(node, Query))
00096 {
00097
00098 bool result;
00099
00100 context->sublevels_up++;
00101 result = query_tree_walker((Query *) node,
00102 contain_aggs_of_level_walker,
00103 (void *) context, 0);
00104 context->sublevels_up--;
00105 return result;
00106 }
00107 return expression_tree_walker(node, contain_aggs_of_level_walker,
00108 (void *) context);
00109 }
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 int
00125 locate_agg_of_level(Node *node, int levelsup)
00126 {
00127 locate_agg_of_level_context context;
00128
00129 context.agg_location = -1;
00130 context.sublevels_up = levelsup;
00131
00132
00133
00134
00135
00136 (void) query_or_expression_tree_walker(node,
00137 locate_agg_of_level_walker,
00138 (void *) &context,
00139 0);
00140
00141 return context.agg_location;
00142 }
00143
00144 static bool
00145 locate_agg_of_level_walker(Node *node,
00146 locate_agg_of_level_context *context)
00147 {
00148 if (node == NULL)
00149 return false;
00150 if (IsA(node, Aggref))
00151 {
00152 if (((Aggref *) node)->agglevelsup == context->sublevels_up &&
00153 ((Aggref *) node)->location >= 0)
00154 {
00155 context->agg_location = ((Aggref *) node)->location;
00156 return true;
00157 }
00158
00159 }
00160 if (IsA(node, Query))
00161 {
00162
00163 bool result;
00164
00165 context->sublevels_up++;
00166 result = query_tree_walker((Query *) node,
00167 locate_agg_of_level_walker,
00168 (void *) context, 0);
00169 context->sublevels_up--;
00170 return result;
00171 }
00172 return expression_tree_walker(node, locate_agg_of_level_walker,
00173 (void *) context);
00174 }
00175
00176
00177
00178
00179
00180
00181 bool
00182 contain_windowfuncs(Node *node)
00183 {
00184
00185
00186
00187
00188 return query_or_expression_tree_walker(node,
00189 contain_windowfuncs_walker,
00190 NULL,
00191 0);
00192 }
00193
00194 static bool
00195 contain_windowfuncs_walker(Node *node, void *context)
00196 {
00197 if (node == NULL)
00198 return false;
00199 if (IsA(node, WindowFunc))
00200 return true;
00201
00202 return expression_tree_walker(node, contain_windowfuncs_walker,
00203 (void *) context);
00204 }
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 int
00220 locate_windowfunc(Node *node)
00221 {
00222 locate_windowfunc_context context;
00223
00224 context.win_location = -1;
00225
00226
00227
00228
00229
00230 (void) query_or_expression_tree_walker(node,
00231 locate_windowfunc_walker,
00232 (void *) &context,
00233 0);
00234
00235 return context.win_location;
00236 }
00237
00238 static bool
00239 locate_windowfunc_walker(Node *node, locate_windowfunc_context *context)
00240 {
00241 if (node == NULL)
00242 return false;
00243 if (IsA(node, WindowFunc))
00244 {
00245 if (((WindowFunc *) node)->location >= 0)
00246 {
00247 context->win_location = ((WindowFunc *) node)->location;
00248 return true;
00249 }
00250
00251 }
00252
00253 return expression_tree_walker(node, locate_windowfunc_walker,
00254 (void *) context);
00255 }
00256
00257
00258
00259
00260
00261 bool
00262 checkExprHasSubLink(Node *node)
00263 {
00264
00265
00266
00267
00268 return query_or_expression_tree_walker(node,
00269 checkExprHasSubLink_walker,
00270 NULL,
00271 QTW_IGNORE_RC_SUBQUERIES);
00272 }
00273
00274 static bool
00275 checkExprHasSubLink_walker(Node *node, void *context)
00276 {
00277 if (node == NULL)
00278 return false;
00279 if (IsA(node, SubLink))
00280 return true;
00281 return expression_tree_walker(node, checkExprHasSubLink_walker, context);
00282 }
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 typedef struct
00299 {
00300 int offset;
00301 int sublevels_up;
00302 } OffsetVarNodes_context;
00303
00304 static bool
00305 OffsetVarNodes_walker(Node *node, OffsetVarNodes_context *context)
00306 {
00307 if (node == NULL)
00308 return false;
00309 if (IsA(node, Var))
00310 {
00311 Var *var = (Var *) node;
00312
00313 if (var->varlevelsup == context->sublevels_up)
00314 {
00315 var->varno += context->offset;
00316 var->varnoold += context->offset;
00317 }
00318 return false;
00319 }
00320 if (IsA(node, CurrentOfExpr))
00321 {
00322 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
00323
00324 if (context->sublevels_up == 0)
00325 cexpr->cvarno += context->offset;
00326 return false;
00327 }
00328 if (IsA(node, RangeTblRef))
00329 {
00330 RangeTblRef *rtr = (RangeTblRef *) node;
00331
00332 if (context->sublevels_up == 0)
00333 rtr->rtindex += context->offset;
00334
00335 return false;
00336 }
00337 if (IsA(node, JoinExpr))
00338 {
00339 JoinExpr *j = (JoinExpr *) node;
00340
00341 if (j->rtindex && context->sublevels_up == 0)
00342 j->rtindex += context->offset;
00343
00344 }
00345 if (IsA(node, PlaceHolderVar))
00346 {
00347 PlaceHolderVar *phv = (PlaceHolderVar *) node;
00348
00349 if (phv->phlevelsup == context->sublevels_up)
00350 {
00351 phv->phrels = offset_relid_set(phv->phrels,
00352 context->offset);
00353 }
00354
00355 }
00356 if (IsA(node, AppendRelInfo))
00357 {
00358 AppendRelInfo *appinfo = (AppendRelInfo *) node;
00359
00360 if (context->sublevels_up == 0)
00361 {
00362 appinfo->parent_relid += context->offset;
00363 appinfo->child_relid += context->offset;
00364 }
00365
00366 }
00367
00368 Assert(!IsA(node, PlanRowMark));
00369 Assert(!IsA(node, SpecialJoinInfo));
00370 Assert(!IsA(node, LateralJoinInfo));
00371 Assert(!IsA(node, PlaceHolderInfo));
00372 Assert(!IsA(node, MinMaxAggInfo));
00373
00374 if (IsA(node, Query))
00375 {
00376
00377 bool result;
00378
00379 context->sublevels_up++;
00380 result = query_tree_walker((Query *) node, OffsetVarNodes_walker,
00381 (void *) context, 0);
00382 context->sublevels_up--;
00383 return result;
00384 }
00385 return expression_tree_walker(node, OffsetVarNodes_walker,
00386 (void *) context);
00387 }
00388
00389 void
00390 OffsetVarNodes(Node *node, int offset, int sublevels_up)
00391 {
00392 OffsetVarNodes_context context;
00393
00394 context.offset = offset;
00395 context.sublevels_up = sublevels_up;
00396
00397
00398
00399
00400
00401
00402 if (node && IsA(node, Query))
00403 {
00404 Query *qry = (Query *) node;
00405
00406
00407
00408
00409
00410
00411
00412
00413 if (sublevels_up == 0)
00414 {
00415 ListCell *l;
00416
00417 if (qry->resultRelation)
00418 qry->resultRelation += offset;
00419 foreach(l, qry->rowMarks)
00420 {
00421 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
00422
00423 rc->rti += offset;
00424 }
00425 }
00426 query_tree_walker(qry, OffsetVarNodes_walker,
00427 (void *) &context, 0);
00428 }
00429 else
00430 OffsetVarNodes_walker(node, &context);
00431 }
00432
00433 static Relids
00434 offset_relid_set(Relids relids, int offset)
00435 {
00436 Relids result = NULL;
00437 Relids tmprelids;
00438 int rtindex;
00439
00440 tmprelids = bms_copy(relids);
00441 while ((rtindex = bms_first_member(tmprelids)) >= 0)
00442 result = bms_add_member(result, rtindex + offset);
00443 bms_free(tmprelids);
00444 return result;
00445 }
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460 typedef struct
00461 {
00462 int rt_index;
00463 int new_index;
00464 int sublevels_up;
00465 } ChangeVarNodes_context;
00466
00467 static bool
00468 ChangeVarNodes_walker(Node *node, ChangeVarNodes_context *context)
00469 {
00470 if (node == NULL)
00471 return false;
00472 if (IsA(node, Var))
00473 {
00474 Var *var = (Var *) node;
00475
00476 if (var->varlevelsup == context->sublevels_up &&
00477 var->varno == context->rt_index)
00478 {
00479 var->varno = context->new_index;
00480 var->varnoold = context->new_index;
00481 }
00482 return false;
00483 }
00484 if (IsA(node, CurrentOfExpr))
00485 {
00486 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
00487
00488 if (context->sublevels_up == 0 &&
00489 cexpr->cvarno == context->rt_index)
00490 cexpr->cvarno = context->new_index;
00491 return false;
00492 }
00493 if (IsA(node, RangeTblRef))
00494 {
00495 RangeTblRef *rtr = (RangeTblRef *) node;
00496
00497 if (context->sublevels_up == 0 &&
00498 rtr->rtindex == context->rt_index)
00499 rtr->rtindex = context->new_index;
00500
00501 return false;
00502 }
00503 if (IsA(node, JoinExpr))
00504 {
00505 JoinExpr *j = (JoinExpr *) node;
00506
00507 if (context->sublevels_up == 0 &&
00508 j->rtindex == context->rt_index)
00509 j->rtindex = context->new_index;
00510
00511 }
00512 if (IsA(node, PlaceHolderVar))
00513 {
00514 PlaceHolderVar *phv = (PlaceHolderVar *) node;
00515
00516 if (phv->phlevelsup == context->sublevels_up)
00517 {
00518 phv->phrels = adjust_relid_set(phv->phrels,
00519 context->rt_index,
00520 context->new_index);
00521 }
00522
00523 }
00524 if (IsA(node, PlanRowMark))
00525 {
00526 PlanRowMark *rowmark = (PlanRowMark *) node;
00527
00528 if (context->sublevels_up == 0)
00529 {
00530 if (rowmark->rti == context->rt_index)
00531 rowmark->rti = context->new_index;
00532 if (rowmark->prti == context->rt_index)
00533 rowmark->prti = context->new_index;
00534 }
00535 return false;
00536 }
00537 if (IsA(node, AppendRelInfo))
00538 {
00539 AppendRelInfo *appinfo = (AppendRelInfo *) node;
00540
00541 if (context->sublevels_up == 0)
00542 {
00543 if (appinfo->parent_relid == context->rt_index)
00544 appinfo->parent_relid = context->new_index;
00545 if (appinfo->child_relid == context->rt_index)
00546 appinfo->child_relid = context->new_index;
00547 }
00548
00549 }
00550
00551 Assert(!IsA(node, SpecialJoinInfo));
00552 Assert(!IsA(node, LateralJoinInfo));
00553 Assert(!IsA(node, PlaceHolderInfo));
00554 Assert(!IsA(node, MinMaxAggInfo));
00555
00556 if (IsA(node, Query))
00557 {
00558
00559 bool result;
00560
00561 context->sublevels_up++;
00562 result = query_tree_walker((Query *) node, ChangeVarNodes_walker,
00563 (void *) context, 0);
00564 context->sublevels_up--;
00565 return result;
00566 }
00567 return expression_tree_walker(node, ChangeVarNodes_walker,
00568 (void *) context);
00569 }
00570
00571 void
00572 ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
00573 {
00574 ChangeVarNodes_context context;
00575
00576 context.rt_index = rt_index;
00577 context.new_index = new_index;
00578 context.sublevels_up = sublevels_up;
00579
00580
00581
00582
00583
00584
00585 if (node && IsA(node, Query))
00586 {
00587 Query *qry = (Query *) node;
00588
00589
00590
00591
00592
00593
00594
00595
00596 if (sublevels_up == 0)
00597 {
00598 ListCell *l;
00599
00600 if (qry->resultRelation == rt_index)
00601 qry->resultRelation = new_index;
00602 foreach(l, qry->rowMarks)
00603 {
00604 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
00605
00606 if (rc->rti == rt_index)
00607 rc->rti = new_index;
00608 }
00609 }
00610 query_tree_walker(qry, ChangeVarNodes_walker,
00611 (void *) &context, 0);
00612 }
00613 else
00614 ChangeVarNodes_walker(node, &context);
00615 }
00616
00617
00618
00619
00620 static Relids
00621 adjust_relid_set(Relids relids, int oldrelid, int newrelid)
00622 {
00623 if (bms_is_member(oldrelid, relids))
00624 {
00625
00626 relids = bms_copy(relids);
00627
00628 relids = bms_del_member(relids, oldrelid);
00629 relids = bms_add_member(relids, newrelid);
00630 }
00631 return relids;
00632 }
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653 typedef struct
00654 {
00655 int delta_sublevels_up;
00656 int min_sublevels_up;
00657 } IncrementVarSublevelsUp_context;
00658
00659 static bool
00660 IncrementVarSublevelsUp_walker(Node *node,
00661 IncrementVarSublevelsUp_context *context)
00662 {
00663 if (node == NULL)
00664 return false;
00665 if (IsA(node, Var))
00666 {
00667 Var *var = (Var *) node;
00668
00669 if (var->varlevelsup >= context->min_sublevels_up)
00670 var->varlevelsup += context->delta_sublevels_up;
00671 return false;
00672 }
00673 if (IsA(node, CurrentOfExpr))
00674 {
00675
00676 if (context->min_sublevels_up == 0)
00677 elog(ERROR, "cannot push down CurrentOfExpr");
00678 return false;
00679 }
00680 if (IsA(node, Aggref))
00681 {
00682 Aggref *agg = (Aggref *) node;
00683
00684 if (agg->agglevelsup >= context->min_sublevels_up)
00685 agg->agglevelsup += context->delta_sublevels_up;
00686
00687 }
00688 if (IsA(node, PlaceHolderVar))
00689 {
00690 PlaceHolderVar *phv = (PlaceHolderVar *) node;
00691
00692 if (phv->phlevelsup >= context->min_sublevels_up)
00693 phv->phlevelsup += context->delta_sublevels_up;
00694
00695 }
00696 if (IsA(node, RangeTblEntry))
00697 {
00698 RangeTblEntry *rte = (RangeTblEntry *) node;
00699
00700 if (rte->rtekind == RTE_CTE)
00701 {
00702 if (rte->ctelevelsup >= context->min_sublevels_up)
00703 rte->ctelevelsup += context->delta_sublevels_up;
00704 }
00705 return false;
00706 }
00707 if (IsA(node, Query))
00708 {
00709
00710 bool result;
00711
00712 context->min_sublevels_up++;
00713 result = query_tree_walker((Query *) node,
00714 IncrementVarSublevelsUp_walker,
00715 (void *) context,
00716 QTW_EXAMINE_RTES);
00717 context->min_sublevels_up--;
00718 return result;
00719 }
00720 return expression_tree_walker(node, IncrementVarSublevelsUp_walker,
00721 (void *) context);
00722 }
00723
00724 void
00725 IncrementVarSublevelsUp(Node *node, int delta_sublevels_up,
00726 int min_sublevels_up)
00727 {
00728 IncrementVarSublevelsUp_context context;
00729
00730 context.delta_sublevels_up = delta_sublevels_up;
00731 context.min_sublevels_up = min_sublevels_up;
00732
00733
00734
00735
00736
00737 query_or_expression_tree_walker(node,
00738 IncrementVarSublevelsUp_walker,
00739 (void *) &context,
00740 QTW_EXAMINE_RTES);
00741 }
00742
00743
00744
00745
00746
00747 void
00748 IncrementVarSublevelsUp_rtable(List *rtable, int delta_sublevels_up,
00749 int min_sublevels_up)
00750 {
00751 IncrementVarSublevelsUp_context context;
00752
00753 context.delta_sublevels_up = delta_sublevels_up;
00754 context.min_sublevels_up = min_sublevels_up;
00755
00756 range_table_walker(rtable,
00757 IncrementVarSublevelsUp_walker,
00758 (void *) &context,
00759 QTW_EXAMINE_RTES);
00760 }
00761
00762
00763
00764
00765
00766
00767
00768 typedef struct
00769 {
00770 int rt_index;
00771 int sublevels_up;
00772 } rangeTableEntry_used_context;
00773
00774 static bool
00775 rangeTableEntry_used_walker(Node *node,
00776 rangeTableEntry_used_context *context)
00777 {
00778 if (node == NULL)
00779 return false;
00780 if (IsA(node, Var))
00781 {
00782 Var *var = (Var *) node;
00783
00784 if (var->varlevelsup == context->sublevels_up &&
00785 var->varno == context->rt_index)
00786 return true;
00787 return false;
00788 }
00789 if (IsA(node, CurrentOfExpr))
00790 {
00791 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
00792
00793 if (context->sublevels_up == 0 &&
00794 cexpr->cvarno == context->rt_index)
00795 return true;
00796 return false;
00797 }
00798 if (IsA(node, RangeTblRef))
00799 {
00800 RangeTblRef *rtr = (RangeTblRef *) node;
00801
00802 if (rtr->rtindex == context->rt_index &&
00803 context->sublevels_up == 0)
00804 return true;
00805
00806 return false;
00807 }
00808 if (IsA(node, JoinExpr))
00809 {
00810 JoinExpr *j = (JoinExpr *) node;
00811
00812 if (j->rtindex == context->rt_index &&
00813 context->sublevels_up == 0)
00814 return true;
00815
00816 }
00817
00818 Assert(!IsA(node, PlaceHolderVar));
00819 Assert(!IsA(node, PlanRowMark));
00820 Assert(!IsA(node, SpecialJoinInfo));
00821 Assert(!IsA(node, LateralJoinInfo));
00822 Assert(!IsA(node, AppendRelInfo));
00823 Assert(!IsA(node, PlaceHolderInfo));
00824 Assert(!IsA(node, MinMaxAggInfo));
00825
00826 if (IsA(node, Query))
00827 {
00828
00829 bool result;
00830
00831 context->sublevels_up++;
00832 result = query_tree_walker((Query *) node, rangeTableEntry_used_walker,
00833 (void *) context, 0);
00834 context->sublevels_up--;
00835 return result;
00836 }
00837 return expression_tree_walker(node, rangeTableEntry_used_walker,
00838 (void *) context);
00839 }
00840
00841 bool
00842 rangeTableEntry_used(Node *node, int rt_index, int sublevels_up)
00843 {
00844 rangeTableEntry_used_context context;
00845
00846 context.rt_index = rt_index;
00847 context.sublevels_up = sublevels_up;
00848
00849
00850
00851
00852
00853 return query_or_expression_tree_walker(node,
00854 rangeTableEntry_used_walker,
00855 (void *) &context,
00856 0);
00857 }
00858
00859
00860
00861
00862
00863
00864
00865
00866 typedef struct
00867 {
00868 int rt_index;
00869 int attno;
00870 int sublevels_up;
00871 } attribute_used_context;
00872
00873 static bool
00874 attribute_used_walker(Node *node,
00875 attribute_used_context *context)
00876 {
00877 if (node == NULL)
00878 return false;
00879 if (IsA(node, Var))
00880 {
00881 Var *var = (Var *) node;
00882
00883 if (var->varlevelsup == context->sublevels_up &&
00884 var->varno == context->rt_index &&
00885 var->varattno == context->attno)
00886 return true;
00887 return false;
00888 }
00889 if (IsA(node, Query))
00890 {
00891
00892 bool result;
00893
00894 context->sublevels_up++;
00895 result = query_tree_walker((Query *) node, attribute_used_walker,
00896 (void *) context, 0);
00897 context->sublevels_up--;
00898 return result;
00899 }
00900 return expression_tree_walker(node, attribute_used_walker,
00901 (void *) context);
00902 }
00903
00904 bool
00905 attribute_used(Node *node, int rt_index, int attno, int sublevels_up)
00906 {
00907 attribute_used_context context;
00908
00909 context.rt_index = rt_index;
00910 context.attno = attno;
00911 context.sublevels_up = sublevels_up;
00912
00913
00914
00915
00916
00917 return query_or_expression_tree_walker(node,
00918 attribute_used_walker,
00919 (void *) &context,
00920 0);
00921 }
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937 Query *
00938 getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr)
00939 {
00940 Query *selectquery;
00941 RangeTblEntry *selectrte;
00942 RangeTblRef *rtr;
00943
00944 if (subquery_ptr)
00945 *subquery_ptr = NULL;
00946
00947 if (parsetree == NULL)
00948 return parsetree;
00949 if (parsetree->commandType != CMD_INSERT)
00950 return parsetree;
00951
00952
00953
00954
00955
00956
00957
00958 if (list_length(parsetree->rtable) >= 2 &&
00959 strcmp(rt_fetch(PRS2_OLD_VARNO, parsetree->rtable)->eref->aliasname,
00960 "old") == 0 &&
00961 strcmp(rt_fetch(PRS2_NEW_VARNO, parsetree->rtable)->eref->aliasname,
00962 "new") == 0)
00963 return parsetree;
00964 Assert(parsetree->jointree && IsA(parsetree->jointree, FromExpr));
00965 if (list_length(parsetree->jointree->fromlist) != 1)
00966 elog(ERROR, "expected to find SELECT subquery");
00967 rtr = (RangeTblRef *) linitial(parsetree->jointree->fromlist);
00968 Assert(IsA(rtr, RangeTblRef));
00969 selectrte = rt_fetch(rtr->rtindex, parsetree->rtable);
00970 selectquery = selectrte->subquery;
00971 if (!(selectquery && IsA(selectquery, Query) &&
00972 selectquery->commandType == CMD_SELECT))
00973 elog(ERROR, "expected to find SELECT subquery");
00974 if (list_length(selectquery->rtable) >= 2 &&
00975 strcmp(rt_fetch(PRS2_OLD_VARNO, selectquery->rtable)->eref->aliasname,
00976 "old") == 0 &&
00977 strcmp(rt_fetch(PRS2_NEW_VARNO, selectquery->rtable)->eref->aliasname,
00978 "new") == 0)
00979 {
00980 if (subquery_ptr)
00981 *subquery_ptr = &(selectrte->subquery);
00982 return selectquery;
00983 }
00984 elog(ERROR, "could not find rule placeholders");
00985 return NULL;
00986 }
00987
00988
00989
00990
00991
00992 void
00993 AddQual(Query *parsetree, Node *qual)
00994 {
00995 Node *copy;
00996
00997 if (qual == NULL)
00998 return;
00999
01000 if (parsetree->commandType == CMD_UTILITY)
01001 {
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015 if (parsetree->utilityStmt && IsA(parsetree->utilityStmt, NotifyStmt))
01016 return;
01017 else
01018 ereport(ERROR,
01019 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01020 errmsg("conditional utility statements are not implemented")));
01021 }
01022
01023 if (parsetree->setOperations != NULL)
01024 {
01025
01026
01027
01028
01029
01030 ereport(ERROR,
01031 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01032 errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
01033 }
01034
01035
01036 copy = copyObject(qual);
01037
01038 parsetree->jointree->quals = make_and_qual(parsetree->jointree->quals,
01039 copy);
01040
01041
01042
01043
01044 Assert(!contain_aggs_of_level(copy, 0));
01045
01046
01047
01048
01049
01050 if (!parsetree->hasSubLinks)
01051 parsetree->hasSubLinks = checkExprHasSubLink(copy);
01052 }
01053
01054
01055
01056
01057
01058
01059
01060 void
01061 AddInvertedQual(Query *parsetree, Node *qual)
01062 {
01063 BooleanTest *invqual;
01064
01065 if (qual == NULL)
01066 return;
01067
01068
01069 invqual = makeNode(BooleanTest);
01070 invqual->arg = (Expr *) qual;
01071 invqual->booltesttype = IS_NOT_TRUE;
01072
01073 AddQual(parsetree, (Node *) invqual);
01074 }
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099 Node *
01100 replace_rte_variables(Node *node, int target_varno, int sublevels_up,
01101 replace_rte_variables_callback callback,
01102 void *callback_arg,
01103 bool *outer_hasSubLinks)
01104 {
01105 Node *result;
01106 replace_rte_variables_context context;
01107
01108 context.callback = callback;
01109 context.callback_arg = callback_arg;
01110 context.target_varno = target_varno;
01111 context.sublevels_up = sublevels_up;
01112
01113
01114
01115
01116
01117 if (node && IsA(node, Query))
01118 context.inserted_sublink = ((Query *) node)->hasSubLinks;
01119 else if (outer_hasSubLinks)
01120 context.inserted_sublink = *outer_hasSubLinks;
01121 else
01122 context.inserted_sublink = false;
01123
01124
01125
01126
01127
01128 result = query_or_expression_tree_mutator(node,
01129 replace_rte_variables_mutator,
01130 (void *) &context,
01131 0);
01132
01133 if (context.inserted_sublink)
01134 {
01135 if (result && IsA(result, Query))
01136 ((Query *) result)->hasSubLinks = true;
01137 else if (outer_hasSubLinks)
01138 *outer_hasSubLinks = true;
01139 else
01140 elog(ERROR, "replace_rte_variables inserted a SubLink, but has noplace to record it");
01141 }
01142
01143 return result;
01144 }
01145
01146 Node *
01147 replace_rte_variables_mutator(Node *node,
01148 replace_rte_variables_context *context)
01149 {
01150 if (node == NULL)
01151 return NULL;
01152 if (IsA(node, Var))
01153 {
01154 Var *var = (Var *) node;
01155
01156 if (var->varno == context->target_varno &&
01157 var->varlevelsup == context->sublevels_up)
01158 {
01159
01160 Node *newnode;
01161
01162 newnode = (*context->callback) (var, context);
01163
01164 if (!context->inserted_sublink)
01165 context->inserted_sublink = checkExprHasSubLink(newnode);
01166 return newnode;
01167 }
01168
01169 }
01170 else if (IsA(node, CurrentOfExpr))
01171 {
01172 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
01173
01174 if (cexpr->cvarno == context->target_varno &&
01175 context->sublevels_up == 0)
01176 {
01177
01178
01179
01180
01181
01182
01183 ereport(ERROR,
01184 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01185 errmsg("WHERE CURRENT OF on a view is not implemented")));
01186 }
01187
01188 }
01189 else if (IsA(node, Query))
01190 {
01191
01192 Query *newnode;
01193 bool save_inserted_sublink;
01194
01195 context->sublevels_up++;
01196 save_inserted_sublink = context->inserted_sublink;
01197 context->inserted_sublink = ((Query *) node)->hasSubLinks;
01198 newnode = query_tree_mutator((Query *) node,
01199 replace_rte_variables_mutator,
01200 (void *) context,
01201 0);
01202 newnode->hasSubLinks |= context->inserted_sublink;
01203 context->inserted_sublink = save_inserted_sublink;
01204 context->sublevels_up--;
01205 return (Node *) newnode;
01206 }
01207 return expression_tree_mutator(node, replace_rte_variables_mutator,
01208 (void *) context);
01209 }
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236 typedef struct
01237 {
01238 int target_varno;
01239 int sublevels_up;
01240 const AttrNumber *attno_map;
01241 int map_length;
01242 bool *found_whole_row;
01243 } map_variable_attnos_context;
01244
01245 static Node *
01246 map_variable_attnos_mutator(Node *node,
01247 map_variable_attnos_context *context)
01248 {
01249 if (node == NULL)
01250 return NULL;
01251 if (IsA(node, Var))
01252 {
01253 Var *var = (Var *) node;
01254
01255 if (var->varno == context->target_varno &&
01256 var->varlevelsup == context->sublevels_up)
01257 {
01258
01259 Var *newvar = (Var *) palloc(sizeof(Var));
01260 int attno = var->varattno;
01261
01262 *newvar = *var;
01263 if (attno > 0)
01264 {
01265
01266 if (attno > context->map_length ||
01267 context->attno_map[attno - 1] == 0)
01268 elog(ERROR, "unexpected varattno %d in expression to be mapped",
01269 attno);
01270 newvar->varattno = newvar->varoattno = context->attno_map[attno - 1];
01271 }
01272 else if (attno == 0)
01273 {
01274
01275 *(context->found_whole_row) = true;
01276 }
01277 return (Node *) newvar;
01278 }
01279
01280 }
01281 else if (IsA(node, Query))
01282 {
01283
01284 Query *newnode;
01285
01286 context->sublevels_up++;
01287 newnode = query_tree_mutator((Query *) node,
01288 map_variable_attnos_mutator,
01289 (void *) context,
01290 0);
01291 context->sublevels_up--;
01292 return (Node *) newnode;
01293 }
01294 return expression_tree_mutator(node, map_variable_attnos_mutator,
01295 (void *) context);
01296 }
01297
01298 Node *
01299 map_variable_attnos(Node *node,
01300 int target_varno, int sublevels_up,
01301 const AttrNumber *attno_map, int map_length,
01302 bool *found_whole_row)
01303 {
01304 map_variable_attnos_context context;
01305
01306 context.target_varno = target_varno;
01307 context.sublevels_up = sublevels_up;
01308 context.attno_map = attno_map;
01309 context.map_length = map_length;
01310 context.found_whole_row = found_whole_row;
01311
01312 *found_whole_row = false;
01313
01314
01315
01316
01317
01318 return query_or_expression_tree_mutator(node,
01319 map_variable_attnos_mutator,
01320 (void *) &context,
01321 0);
01322 }
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344 typedef struct
01345 {
01346 RangeTblEntry *target_rte;
01347 List *targetlist;
01348 ReplaceVarsNoMatchOption nomatch_option;
01349 int nomatch_varno;
01350 } ReplaceVarsFromTargetList_context;
01351
01352 static Node *
01353 ReplaceVarsFromTargetList_callback(Var *var,
01354 replace_rte_variables_context *context)
01355 {
01356 ReplaceVarsFromTargetList_context *rcon = (ReplaceVarsFromTargetList_context *) context->callback_arg;
01357 TargetEntry *tle;
01358
01359 if (var->varattno == InvalidAttrNumber)
01360 {
01361
01362 RowExpr *rowexpr;
01363 List *colnames;
01364 List *fields;
01365
01366
01367
01368
01369
01370
01371
01372
01373 expandRTE(rcon->target_rte,
01374 var->varno, var->varlevelsup, var->location,
01375 (var->vartype != RECORDOID),
01376 &colnames, &fields);
01377
01378 fields = (List *) replace_rte_variables_mutator((Node *) fields,
01379 context);
01380 rowexpr = makeNode(RowExpr);
01381 rowexpr->args = fields;
01382 rowexpr->row_typeid = var->vartype;
01383 rowexpr->row_format = COERCE_IMPLICIT_CAST;
01384 rowexpr->colnames = colnames;
01385 rowexpr->location = var->location;
01386
01387 return (Node *) rowexpr;
01388 }
01389
01390
01391 tle = get_tle_by_resno(rcon->targetlist, var->varattno);
01392
01393 if (tle == NULL || tle->resjunk)
01394 {
01395
01396 switch (rcon->nomatch_option)
01397 {
01398 case REPLACEVARS_REPORT_ERROR:
01399
01400 break;
01401
01402 case REPLACEVARS_CHANGE_VARNO:
01403 var = (Var *) copyObject(var);
01404 var->varno = rcon->nomatch_varno;
01405 var->varnoold = rcon->nomatch_varno;
01406 return (Node *) var;
01407
01408 case REPLACEVARS_SUBSTITUTE_NULL:
01409
01410
01411
01412
01413 return coerce_to_domain((Node *) makeNullConst(var->vartype,
01414 var->vartypmod,
01415 var->varcollid),
01416 InvalidOid, -1,
01417 var->vartype,
01418 COERCE_IMPLICIT_CAST,
01419 -1,
01420 false,
01421 false);
01422 }
01423 elog(ERROR, "could not find replacement targetlist entry for attno %d",
01424 var->varattno);
01425 return NULL;
01426 }
01427 else
01428 {
01429
01430 Node *newnode = copyObject(tle->expr);
01431
01432
01433 if (var->varlevelsup > 0)
01434 IncrementVarSublevelsUp(newnode, var->varlevelsup, 0);
01435
01436 return newnode;
01437 }
01438 }
01439
01440 Node *
01441 ReplaceVarsFromTargetList(Node *node,
01442 int target_varno, int sublevels_up,
01443 RangeTblEntry *target_rte,
01444 List *targetlist,
01445 ReplaceVarsNoMatchOption nomatch_option,
01446 int nomatch_varno,
01447 bool *outer_hasSubLinks)
01448 {
01449 ReplaceVarsFromTargetList_context context;
01450
01451 context.target_rte = target_rte;
01452 context.targetlist = targetlist;
01453 context.nomatch_option = nomatch_option;
01454 context.nomatch_varno = nomatch_varno;
01455
01456 return replace_rte_variables(node, target_varno, sublevels_up,
01457 ReplaceVarsFromTargetList_callback,
01458 (void *) &context,
01459 outer_hasSubLinks);
01460 }