00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "postgres.h"
00018
00019 #include "access/skey.h"
00020 #include "catalog/pg_type.h"
00021 #include "nodes/makefuncs.h"
00022 #include "nodes/nodeFuncs.h"
00023 #include "optimizer/clauses.h"
00024 #include "optimizer/pathnode.h"
00025 #include "optimizer/paths.h"
00026 #include "optimizer/planmain.h"
00027 #include "optimizer/prep.h"
00028 #include "optimizer/var.h"
00029 #include "utils/lsyscache.h"
00030
00031
00032 static EquivalenceMember *add_eq_member(EquivalenceClass *ec,
00033 Expr *expr, Relids relids, Relids nullable_relids,
00034 bool is_child, Oid datatype);
00035 static void generate_base_implied_equalities_const(PlannerInfo *root,
00036 EquivalenceClass *ec);
00037 static void generate_base_implied_equalities_no_const(PlannerInfo *root,
00038 EquivalenceClass *ec);
00039 static void generate_base_implied_equalities_broken(PlannerInfo *root,
00040 EquivalenceClass *ec);
00041 static List *generate_join_implied_equalities_normal(PlannerInfo *root,
00042 EquivalenceClass *ec,
00043 Relids join_relids,
00044 Relids outer_relids,
00045 Relids inner_relids);
00046 static List *generate_join_implied_equalities_broken(PlannerInfo *root,
00047 EquivalenceClass *ec,
00048 Relids nominal_join_relids,
00049 Relids outer_relids,
00050 Relids nominal_inner_relids,
00051 AppendRelInfo *inner_appinfo);
00052 static Oid select_equality_operator(EquivalenceClass *ec,
00053 Oid lefttype, Oid righttype);
00054 static RestrictInfo *create_join_clause(PlannerInfo *root,
00055 EquivalenceClass *ec, Oid opno,
00056 EquivalenceMember *leftem,
00057 EquivalenceMember *rightem,
00058 EquivalenceClass *parent_ec);
00059 static bool reconsider_outer_join_clause(PlannerInfo *root,
00060 RestrictInfo *rinfo,
00061 bool outer_on_left);
00062 static bool reconsider_full_join_clause(PlannerInfo *root,
00063 RestrictInfo *rinfo);
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 bool
00098 process_equivalence(PlannerInfo *root, RestrictInfo *restrictinfo,
00099 bool below_outer_join)
00100 {
00101 Expr *clause = restrictinfo->clause;
00102 Oid opno,
00103 collation,
00104 item1_type,
00105 item2_type;
00106 Expr *item1;
00107 Expr *item2;
00108 Relids item1_relids,
00109 item2_relids,
00110 item1_nullable_relids,
00111 item2_nullable_relids;
00112 List *opfamilies;
00113 EquivalenceClass *ec1,
00114 *ec2;
00115 EquivalenceMember *em1,
00116 *em2;
00117 ListCell *lc1;
00118
00119
00120 Assert(restrictinfo->left_ec == NULL);
00121 Assert(restrictinfo->right_ec == NULL);
00122
00123
00124 Assert(is_opclause(clause));
00125 opno = ((OpExpr *) clause)->opno;
00126 collation = ((OpExpr *) clause)->inputcollid;
00127 item1 = (Expr *) get_leftop(clause);
00128 item2 = (Expr *) get_rightop(clause);
00129 item1_relids = restrictinfo->left_relids;
00130 item2_relids = restrictinfo->right_relids;
00131
00132
00133
00134
00135
00136 item1 = canonicalize_ec_expression(item1,
00137 exprType((Node *) item1),
00138 collation);
00139 item2 = canonicalize_ec_expression(item2,
00140 exprType((Node *) item2),
00141 collation);
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 if (equal(item1, item2))
00153 return false;
00154
00155
00156
00157
00158 if (below_outer_join)
00159 {
00160 if (!bms_is_empty(item1_relids) &&
00161 contain_nonstrict_functions((Node *) item1))
00162 return false;
00163 if (!bms_is_empty(item2_relids) &&
00164 contain_nonstrict_functions((Node *) item2))
00165 return false;
00166 }
00167
00168
00169 item1_nullable_relids = bms_intersect(item1_relids,
00170 restrictinfo->nullable_relids);
00171 item2_nullable_relids = bms_intersect(item2_relids,
00172 restrictinfo->nullable_relids);
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 op_input_types(opno, &item1_type, &item2_type);
00183
00184 opfamilies = restrictinfo->mergeopfamilies;
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 ec1 = ec2 = NULL;
00205 em1 = em2 = NULL;
00206 foreach(lc1, root->eq_classes)
00207 {
00208 EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc1);
00209 ListCell *lc2;
00210
00211
00212 if (cur_ec->ec_has_volatile)
00213 continue;
00214
00215
00216
00217
00218
00219 if (collation != cur_ec->ec_collation)
00220 continue;
00221
00222
00223
00224
00225
00226
00227 if (!equal(opfamilies, cur_ec->ec_opfamilies))
00228 continue;
00229
00230 foreach(lc2, cur_ec->ec_members)
00231 {
00232 EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2);
00233
00234 Assert(!cur_em->em_is_child);
00235
00236
00237
00238
00239
00240 if ((below_outer_join || cur_ec->ec_below_outer_join) &&
00241 cur_em->em_is_const)
00242 continue;
00243
00244 if (!ec1 &&
00245 item1_type == cur_em->em_datatype &&
00246 equal(item1, cur_em->em_expr))
00247 {
00248 ec1 = cur_ec;
00249 em1 = cur_em;
00250 if (ec2)
00251 break;
00252 }
00253
00254 if (!ec2 &&
00255 item2_type == cur_em->em_datatype &&
00256 equal(item2, cur_em->em_expr))
00257 {
00258 ec2 = cur_ec;
00259 em2 = cur_em;
00260 if (ec1)
00261 break;
00262 }
00263 }
00264
00265 if (ec1 && ec2)
00266 break;
00267 }
00268
00269
00270
00271 if (ec1 && ec2)
00272 {
00273
00274 if (ec1 == ec2)
00275 {
00276 ec1->ec_sources = lappend(ec1->ec_sources, restrictinfo);
00277 ec1->ec_below_outer_join |= below_outer_join;
00278
00279 restrictinfo->left_ec = ec1;
00280 restrictinfo->right_ec = ec1;
00281
00282 restrictinfo->left_em = em1;
00283 restrictinfo->right_em = em2;
00284 return true;
00285 }
00286
00287
00288
00289
00290
00291
00292 if (root->canon_pathkeys != NIL)
00293 elog(ERROR, "too late to merge equivalence classes");
00294
00295
00296
00297
00298
00299
00300
00301
00302 ec1->ec_members = list_concat(ec1->ec_members, ec2->ec_members);
00303 ec1->ec_sources = list_concat(ec1->ec_sources, ec2->ec_sources);
00304 ec1->ec_derives = list_concat(ec1->ec_derives, ec2->ec_derives);
00305 ec1->ec_relids = bms_join(ec1->ec_relids, ec2->ec_relids);
00306 ec1->ec_has_const |= ec2->ec_has_const;
00307
00308 ec1->ec_below_outer_join |= ec2->ec_below_outer_join;
00309 ec2->ec_merged = ec1;
00310 root->eq_classes = list_delete_ptr(root->eq_classes, ec2);
00311
00312 ec2->ec_members = NIL;
00313 ec2->ec_sources = NIL;
00314 ec2->ec_derives = NIL;
00315 ec2->ec_relids = NULL;
00316 ec1->ec_sources = lappend(ec1->ec_sources, restrictinfo);
00317 ec1->ec_below_outer_join |= below_outer_join;
00318
00319 restrictinfo->left_ec = ec1;
00320 restrictinfo->right_ec = ec1;
00321
00322 restrictinfo->left_em = em1;
00323 restrictinfo->right_em = em2;
00324 }
00325 else if (ec1)
00326 {
00327
00328 em2 = add_eq_member(ec1, item2, item2_relids, item2_nullable_relids,
00329 false, item2_type);
00330 ec1->ec_sources = lappend(ec1->ec_sources, restrictinfo);
00331 ec1->ec_below_outer_join |= below_outer_join;
00332
00333 restrictinfo->left_ec = ec1;
00334 restrictinfo->right_ec = ec1;
00335
00336 restrictinfo->left_em = em1;
00337 restrictinfo->right_em = em2;
00338 }
00339 else if (ec2)
00340 {
00341
00342 em1 = add_eq_member(ec2, item1, item1_relids, item1_nullable_relids,
00343 false, item1_type);
00344 ec2->ec_sources = lappend(ec2->ec_sources, restrictinfo);
00345 ec2->ec_below_outer_join |= below_outer_join;
00346
00347 restrictinfo->left_ec = ec2;
00348 restrictinfo->right_ec = ec2;
00349
00350 restrictinfo->left_em = em1;
00351 restrictinfo->right_em = em2;
00352 }
00353 else
00354 {
00355
00356 EquivalenceClass *ec = makeNode(EquivalenceClass);
00357
00358 ec->ec_opfamilies = opfamilies;
00359 ec->ec_collation = collation;
00360 ec->ec_members = NIL;
00361 ec->ec_sources = list_make1(restrictinfo);
00362 ec->ec_derives = NIL;
00363 ec->ec_relids = NULL;
00364 ec->ec_has_const = false;
00365 ec->ec_has_volatile = false;
00366 ec->ec_below_outer_join = below_outer_join;
00367 ec->ec_broken = false;
00368 ec->ec_sortref = 0;
00369 ec->ec_merged = NULL;
00370 em1 = add_eq_member(ec, item1, item1_relids, item1_nullable_relids,
00371 false, item1_type);
00372 em2 = add_eq_member(ec, item2, item2_relids, item2_nullable_relids,
00373 false, item2_type);
00374
00375 root->eq_classes = lappend(root->eq_classes, ec);
00376
00377
00378 restrictinfo->left_ec = ec;
00379 restrictinfo->right_ec = ec;
00380
00381 restrictinfo->left_em = em1;
00382 restrictinfo->right_em = em2;
00383 }
00384
00385 return true;
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420 Expr *
00421 canonicalize_ec_expression(Expr *expr, Oid req_type, Oid req_collation)
00422 {
00423 Oid expr_type = exprType((Node *) expr);
00424
00425
00426
00427
00428 if (IsPolymorphicType(req_type))
00429 req_type = expr_type;
00430
00431
00432
00433
00434 if (expr_type != req_type ||
00435 exprCollation((Node *) expr) != req_collation)
00436 {
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446 while (expr && IsA(expr, RelabelType))
00447 expr = (Expr *) ((RelabelType *) expr)->arg;
00448
00449 if (exprType((Node *) expr) != req_type)
00450 expr = (Expr *) makeRelabelType(expr,
00451 req_type,
00452 -1,
00453 req_collation,
00454 COERCE_IMPLICIT_CAST);
00455 else if (exprCollation((Node *) expr) != req_collation)
00456 expr = (Expr *) makeRelabelType(expr,
00457 req_type,
00458 exprTypmod((Node *) expr),
00459 req_collation,
00460 COERCE_IMPLICIT_CAST);
00461 }
00462
00463 return expr;
00464 }
00465
00466
00467
00468
00469 static EquivalenceMember *
00470 add_eq_member(EquivalenceClass *ec, Expr *expr, Relids relids,
00471 Relids nullable_relids, bool is_child, Oid datatype)
00472 {
00473 EquivalenceMember *em = makeNode(EquivalenceMember);
00474
00475 em->em_expr = expr;
00476 em->em_relids = relids;
00477 em->em_nullable_relids = nullable_relids;
00478 em->em_is_const = false;
00479 em->em_is_child = is_child;
00480 em->em_datatype = datatype;
00481
00482 if (bms_is_empty(relids))
00483 {
00484
00485
00486
00487
00488
00489
00490
00491
00492 Assert(!is_child);
00493 em->em_is_const = true;
00494 ec->ec_has_const = true;
00495
00496 }
00497 else if (!is_child)
00498 {
00499 ec->ec_relids = bms_add_members(ec->ec_relids, relids);
00500 }
00501 ec->ec_members = lappend(ec->ec_members, em);
00502
00503 return em;
00504 }
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538 EquivalenceClass *
00539 get_eclass_for_sort_expr(PlannerInfo *root,
00540 Expr *expr,
00541 List *opfamilies,
00542 Oid opcintype,
00543 Oid collation,
00544 Index sortref,
00545 Relids rel,
00546 bool create_it)
00547 {
00548 EquivalenceClass *newec;
00549 EquivalenceMember *newem;
00550 ListCell *lc1;
00551 MemoryContext oldcontext;
00552
00553
00554
00555
00556 expr = canonicalize_ec_expression(expr, opcintype, collation);
00557
00558
00559
00560
00561 foreach(lc1, root->eq_classes)
00562 {
00563 EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc1);
00564 ListCell *lc2;
00565
00566
00567
00568
00569
00570 if (cur_ec->ec_has_volatile &&
00571 (sortref == 0 || sortref != cur_ec->ec_sortref))
00572 continue;
00573
00574 if (collation != cur_ec->ec_collation)
00575 continue;
00576 if (!equal(opfamilies, cur_ec->ec_opfamilies))
00577 continue;
00578
00579 foreach(lc2, cur_ec->ec_members)
00580 {
00581 EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2);
00582
00583
00584
00585
00586 if (cur_em->em_is_child &&
00587 !bms_equal(cur_em->em_relids, rel))
00588 continue;
00589
00590
00591
00592
00593
00594 if (cur_ec->ec_below_outer_join &&
00595 cur_em->em_is_const)
00596 continue;
00597
00598 if (opcintype == cur_em->em_datatype &&
00599 equal(expr, cur_em->em_expr))
00600 return cur_ec;
00601 }
00602 }
00603
00604
00605 if (!create_it)
00606 return NULL;
00607
00608
00609
00610
00611
00612
00613 oldcontext = MemoryContextSwitchTo(root->planner_cxt);
00614
00615 newec = makeNode(EquivalenceClass);
00616 newec->ec_opfamilies = list_copy(opfamilies);
00617 newec->ec_collation = collation;
00618 newec->ec_members = NIL;
00619 newec->ec_sources = NIL;
00620 newec->ec_derives = NIL;
00621 newec->ec_relids = NULL;
00622 newec->ec_has_const = false;
00623 newec->ec_has_volatile = contain_volatile_functions((Node *) expr);
00624 newec->ec_below_outer_join = false;
00625 newec->ec_broken = false;
00626 newec->ec_sortref = sortref;
00627 newec->ec_merged = NULL;
00628
00629 if (newec->ec_has_volatile && sortref == 0)
00630 elog(ERROR, "volatile EquivalenceClass has no sortref");
00631
00632 newem = add_eq_member(newec, copyObject(expr), pull_varnos((Node *) expr),
00633 NULL, false, opcintype);
00634
00635
00636
00637
00638
00639
00640
00641 if (newec->ec_has_const)
00642 {
00643 if (newec->ec_has_volatile ||
00644 expression_returns_set((Node *) expr) ||
00645 contain_agg_clause((Node *) expr) ||
00646 contain_window_function((Node *) expr))
00647 {
00648 newec->ec_has_const = false;
00649 newem->em_is_const = false;
00650 }
00651 }
00652
00653 root->eq_classes = lappend(root->eq_classes, newec);
00654
00655 MemoryContextSwitchTo(oldcontext);
00656
00657 return newec;
00658 }
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709 void
00710 generate_base_implied_equalities(PlannerInfo *root)
00711 {
00712 ListCell *lc;
00713 Index rti;
00714
00715 foreach(lc, root->eq_classes)
00716 {
00717 EquivalenceClass *ec = (EquivalenceClass *) lfirst(lc);
00718
00719 Assert(ec->ec_merged == NULL);
00720 Assert(!ec->ec_broken);
00721
00722
00723 if (list_length(ec->ec_members) <= 1)
00724 continue;
00725
00726 if (ec->ec_has_const)
00727 generate_base_implied_equalities_const(root, ec);
00728 else
00729 generate_base_implied_equalities_no_const(root, ec);
00730
00731
00732 if (ec->ec_broken)
00733 generate_base_implied_equalities_broken(root, ec);
00734 }
00735
00736
00737
00738
00739
00740 for (rti = 1; rti < root->simple_rel_array_size; rti++)
00741 {
00742 RelOptInfo *brel = root->simple_rel_array[rti];
00743
00744 if (brel == NULL)
00745 continue;
00746
00747 brel->has_eclass_joins = has_relevant_eclass_joinclause(root, brel);
00748 }
00749 }
00750
00751
00752
00753
00754 static void
00755 generate_base_implied_equalities_const(PlannerInfo *root,
00756 EquivalenceClass *ec)
00757 {
00758 EquivalenceMember *const_em = NULL;
00759 ListCell *lc;
00760
00761
00762
00763
00764
00765
00766
00767
00768 if (list_length(ec->ec_members) == 2 &&
00769 list_length(ec->ec_sources) == 1)
00770 {
00771 RestrictInfo *restrictinfo = (RestrictInfo *) linitial(ec->ec_sources);
00772
00773 if (bms_membership(restrictinfo->required_relids) != BMS_MULTIPLE)
00774 {
00775 distribute_restrictinfo_to_rels(root, restrictinfo);
00776 return;
00777 }
00778 }
00779
00780
00781
00782
00783
00784
00785
00786 foreach(lc, ec->ec_members)
00787 {
00788 EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc);
00789
00790 if (cur_em->em_is_const)
00791 {
00792 const_em = cur_em;
00793 if (IsA(cur_em->em_expr, Const))
00794 break;
00795 }
00796 }
00797 Assert(const_em != NULL);
00798
00799
00800 foreach(lc, ec->ec_members)
00801 {
00802 EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc);
00803 Oid eq_op;
00804
00805 Assert(!cur_em->em_is_child);
00806 if (cur_em == const_em)
00807 continue;
00808 eq_op = select_equality_operator(ec,
00809 cur_em->em_datatype,
00810 const_em->em_datatype);
00811 if (!OidIsValid(eq_op))
00812 {
00813
00814 ec->ec_broken = true;
00815 break;
00816 }
00817 process_implied_equality(root, eq_op, ec->ec_collation,
00818 cur_em->em_expr, const_em->em_expr,
00819 bms_copy(ec->ec_relids),
00820 bms_union(cur_em->em_nullable_relids,
00821 const_em->em_nullable_relids),
00822 ec->ec_below_outer_join,
00823 cur_em->em_is_const);
00824 }
00825 }
00826
00827
00828
00829
00830 static void
00831 generate_base_implied_equalities_no_const(PlannerInfo *root,
00832 EquivalenceClass *ec)
00833 {
00834 EquivalenceMember **prev_ems;
00835 ListCell *lc;
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846 prev_ems = (EquivalenceMember **)
00847 palloc0(root->simple_rel_array_size * sizeof(EquivalenceMember *));
00848
00849 foreach(lc, ec->ec_members)
00850 {
00851 EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc);
00852 int relid;
00853
00854 Assert(!cur_em->em_is_child);
00855 if (bms_membership(cur_em->em_relids) != BMS_SINGLETON)
00856 continue;
00857 relid = bms_singleton_member(cur_em->em_relids);
00858 Assert(relid < root->simple_rel_array_size);
00859
00860 if (prev_ems[relid] != NULL)
00861 {
00862 EquivalenceMember *prev_em = prev_ems[relid];
00863 Oid eq_op;
00864
00865 eq_op = select_equality_operator(ec,
00866 prev_em->em_datatype,
00867 cur_em->em_datatype);
00868 if (!OidIsValid(eq_op))
00869 {
00870
00871 ec->ec_broken = true;
00872 break;
00873 }
00874 process_implied_equality(root, eq_op, ec->ec_collation,
00875 prev_em->em_expr, cur_em->em_expr,
00876 bms_copy(ec->ec_relids),
00877 bms_union(prev_em->em_nullable_relids,
00878 cur_em->em_nullable_relids),
00879 ec->ec_below_outer_join,
00880 false);
00881 }
00882 prev_ems[relid] = cur_em;
00883 }
00884
00885 pfree(prev_ems);
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895 foreach(lc, ec->ec_members)
00896 {
00897 EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc);
00898 List *vars = pull_var_clause((Node *) cur_em->em_expr,
00899 PVC_RECURSE_AGGREGATES,
00900 PVC_INCLUDE_PLACEHOLDERS);
00901
00902 add_vars_to_targetlist(root, vars, ec->ec_relids, false);
00903 list_free(vars);
00904 }
00905 }
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921 static void
00922 generate_base_implied_equalities_broken(PlannerInfo *root,
00923 EquivalenceClass *ec)
00924 {
00925 ListCell *lc;
00926
00927 foreach(lc, ec->ec_sources)
00928 {
00929 RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(lc);
00930
00931 if (ec->ec_has_const ||
00932 bms_membership(restrictinfo->required_relids) != BMS_MULTIPLE)
00933 distribute_restrictinfo_to_rels(root, restrictinfo);
00934 }
00935 }
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978 List *
00979 generate_join_implied_equalities(PlannerInfo *root,
00980 Relids join_relids,
00981 Relids outer_relids,
00982 RelOptInfo *inner_rel)
00983 {
00984 List *result = NIL;
00985 Relids inner_relids = inner_rel->relids;
00986 Relids nominal_inner_relids;
00987 Relids nominal_join_relids;
00988 AppendRelInfo *inner_appinfo;
00989 ListCell *lc;
00990
00991
00992 if (inner_rel->reloptkind == RELOPT_OTHER_MEMBER_REL)
00993 {
00994
00995 inner_appinfo = find_childrel_appendrelinfo(root, inner_rel);
00996
00997 nominal_inner_relids = bms_make_singleton(inner_appinfo->parent_relid);
00998
00999 nominal_join_relids = bms_union(outer_relids, nominal_inner_relids);
01000 }
01001 else
01002 {
01003 inner_appinfo = NULL;
01004 nominal_inner_relids = inner_relids;
01005 nominal_join_relids = join_relids;
01006 }
01007
01008 foreach(lc, root->eq_classes)
01009 {
01010 EquivalenceClass *ec = (EquivalenceClass *) lfirst(lc);
01011 List *sublist = NIL;
01012
01013
01014 if (ec->ec_has_const)
01015 continue;
01016
01017
01018 if (list_length(ec->ec_members) <= 1)
01019 continue;
01020
01021
01022 if (!bms_overlap(ec->ec_relids, nominal_join_relids))
01023 continue;
01024
01025 if (!ec->ec_broken)
01026 sublist = generate_join_implied_equalities_normal(root,
01027 ec,
01028 join_relids,
01029 outer_relids,
01030 inner_relids);
01031
01032
01033 if (ec->ec_broken)
01034 sublist = generate_join_implied_equalities_broken(root,
01035 ec,
01036 nominal_join_relids,
01037 outer_relids,
01038 nominal_inner_relids,
01039 inner_appinfo);
01040
01041 result = list_concat(result, sublist);
01042 }
01043
01044 return result;
01045 }
01046
01047
01048
01049
01050 static List *
01051 generate_join_implied_equalities_normal(PlannerInfo *root,
01052 EquivalenceClass *ec,
01053 Relids join_relids,
01054 Relids outer_relids,
01055 Relids inner_relids)
01056 {
01057 List *result = NIL;
01058 List *new_members = NIL;
01059 List *outer_members = NIL;
01060 List *inner_members = NIL;
01061 ListCell *lc1;
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072 foreach(lc1, ec->ec_members)
01073 {
01074 EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc1);
01075
01076
01077
01078
01079
01080
01081 if (!bms_is_subset(cur_em->em_relids, join_relids))
01082 continue;
01083
01084 if (bms_is_subset(cur_em->em_relids, outer_relids))
01085 outer_members = lappend(outer_members, cur_em);
01086 else if (bms_is_subset(cur_em->em_relids, inner_relids))
01087 inner_members = lappend(inner_members, cur_em);
01088 else
01089 new_members = lappend(new_members, cur_em);
01090 }
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101 if (outer_members && inner_members)
01102 {
01103 EquivalenceMember *best_outer_em = NULL;
01104 EquivalenceMember *best_inner_em = NULL;
01105 Oid best_eq_op = InvalidOid;
01106 int best_score = -1;
01107 RestrictInfo *rinfo;
01108
01109 foreach(lc1, outer_members)
01110 {
01111 EquivalenceMember *outer_em = (EquivalenceMember *) lfirst(lc1);
01112 ListCell *lc2;
01113
01114 foreach(lc2, inner_members)
01115 {
01116 EquivalenceMember *inner_em = (EquivalenceMember *) lfirst(lc2);
01117 Oid eq_op;
01118 int score;
01119
01120 eq_op = select_equality_operator(ec,
01121 outer_em->em_datatype,
01122 inner_em->em_datatype);
01123 if (!OidIsValid(eq_op))
01124 continue;
01125 score = 0;
01126 if (IsA(outer_em->em_expr, Var) ||
01127 (IsA(outer_em->em_expr, RelabelType) &&
01128 IsA(((RelabelType *) outer_em->em_expr)->arg, Var)))
01129 score++;
01130 if (IsA(inner_em->em_expr, Var) ||
01131 (IsA(inner_em->em_expr, RelabelType) &&
01132 IsA(((RelabelType *) inner_em->em_expr)->arg, Var)))
01133 score++;
01134 if (op_hashjoinable(eq_op,
01135 exprType((Node *) outer_em->em_expr)))
01136 score++;
01137 if (score > best_score)
01138 {
01139 best_outer_em = outer_em;
01140 best_inner_em = inner_em;
01141 best_eq_op = eq_op;
01142 best_score = score;
01143 if (best_score == 3)
01144 break;
01145 }
01146 }
01147 if (best_score == 3)
01148 break;
01149 }
01150 if (best_score < 0)
01151 {
01152
01153 ec->ec_broken = true;
01154 return NIL;
01155 }
01156
01157
01158
01159
01160
01161 rinfo = create_join_clause(root, ec, best_eq_op,
01162 best_outer_em, best_inner_em,
01163 ec);
01164
01165 result = lappend(result, rinfo);
01166 }
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177 if (new_members)
01178 {
01179 List *old_members = list_concat(outer_members, inner_members);
01180 EquivalenceMember *prev_em = NULL;
01181 RestrictInfo *rinfo;
01182
01183
01184 if (old_members)
01185 new_members = lappend(new_members, linitial(old_members));
01186
01187 foreach(lc1, new_members)
01188 {
01189 EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc1);
01190
01191 if (prev_em != NULL)
01192 {
01193 Oid eq_op;
01194
01195 eq_op = select_equality_operator(ec,
01196 prev_em->em_datatype,
01197 cur_em->em_datatype);
01198 if (!OidIsValid(eq_op))
01199 {
01200
01201 ec->ec_broken = true;
01202 return NIL;
01203 }
01204
01205 rinfo = create_join_clause(root, ec, eq_op,
01206 prev_em, cur_em,
01207 NULL);
01208
01209 result = lappend(result, rinfo);
01210 }
01211 prev_em = cur_em;
01212 }
01213 }
01214
01215 return result;
01216 }
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226 static List *
01227 generate_join_implied_equalities_broken(PlannerInfo *root,
01228 EquivalenceClass *ec,
01229 Relids nominal_join_relids,
01230 Relids outer_relids,
01231 Relids nominal_inner_relids,
01232 AppendRelInfo *inner_appinfo)
01233 {
01234 List *result = NIL;
01235 ListCell *lc;
01236
01237 foreach(lc, ec->ec_sources)
01238 {
01239 RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(lc);
01240 Relids clause_relids = restrictinfo->required_relids;
01241
01242 if (bms_is_subset(clause_relids, nominal_join_relids) &&
01243 !bms_is_subset(clause_relids, outer_relids) &&
01244 !bms_is_subset(clause_relids, nominal_inner_relids))
01245 result = lappend(result, restrictinfo);
01246 }
01247
01248
01249
01250
01251
01252
01253
01254
01255 if (inner_appinfo)
01256 result = (List *) adjust_appendrel_attrs(root, (Node *) result,
01257 inner_appinfo);
01258
01259 return result;
01260 }
01261
01262
01263
01264
01265
01266
01267
01268
01269 static Oid
01270 select_equality_operator(EquivalenceClass *ec, Oid lefttype, Oid righttype)
01271 {
01272 ListCell *lc;
01273
01274 foreach(lc, ec->ec_opfamilies)
01275 {
01276 Oid opfamily = lfirst_oid(lc);
01277 Oid opno;
01278
01279 opno = get_opfamily_member(opfamily, lefttype, righttype,
01280 BTEqualStrategyNumber);
01281 if (OidIsValid(opno))
01282 return opno;
01283 }
01284 return InvalidOid;
01285 }
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298 static RestrictInfo *
01299 create_join_clause(PlannerInfo *root,
01300 EquivalenceClass *ec, Oid opno,
01301 EquivalenceMember *leftem,
01302 EquivalenceMember *rightem,
01303 EquivalenceClass *parent_ec)
01304 {
01305 RestrictInfo *rinfo;
01306 ListCell *lc;
01307 MemoryContext oldcontext;
01308
01309
01310
01311
01312
01313
01314
01315 foreach(lc, ec->ec_sources)
01316 {
01317 rinfo = (RestrictInfo *) lfirst(lc);
01318 if (rinfo->left_em == leftem &&
01319 rinfo->right_em == rightem &&
01320 rinfo->parent_ec == parent_ec &&
01321 opno == ((OpExpr *) rinfo->clause)->opno)
01322 return rinfo;
01323 }
01324
01325 foreach(lc, ec->ec_derives)
01326 {
01327 rinfo = (RestrictInfo *) lfirst(lc);
01328 if (rinfo->left_em == leftem &&
01329 rinfo->right_em == rightem &&
01330 rinfo->parent_ec == parent_ec &&
01331 opno == ((OpExpr *) rinfo->clause)->opno)
01332 return rinfo;
01333 }
01334
01335
01336
01337
01338
01339 oldcontext = MemoryContextSwitchTo(root->planner_cxt);
01340
01341 rinfo = build_implied_join_equality(opno,
01342 ec->ec_collation,
01343 leftem->em_expr,
01344 rightem->em_expr,
01345 bms_union(leftem->em_relids,
01346 rightem->em_relids),
01347 bms_union(leftem->em_nullable_relids,
01348 rightem->em_nullable_relids));
01349
01350
01351 rinfo->parent_ec = parent_ec;
01352
01353
01354
01355
01356
01357 rinfo->left_ec = ec;
01358 rinfo->right_ec = ec;
01359
01360
01361 rinfo->left_em = leftem;
01362 rinfo->right_em = rightem;
01363
01364 ec->ec_derives = lappend(ec->ec_derives, rinfo);
01365
01366 MemoryContextSwitchTo(oldcontext);
01367
01368 return rinfo;
01369 }
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450 void
01451 reconsider_outer_join_clauses(PlannerInfo *root)
01452 {
01453 bool found;
01454 ListCell *cell;
01455 ListCell *prev;
01456 ListCell *next;
01457
01458
01459 do
01460 {
01461 found = false;
01462
01463
01464 prev = NULL;
01465 for (cell = list_head(root->left_join_clauses); cell; cell = next)
01466 {
01467 RestrictInfo *rinfo = (RestrictInfo *) lfirst(cell);
01468
01469 next = lnext(cell);
01470 if (reconsider_outer_join_clause(root, rinfo, true))
01471 {
01472 found = true;
01473
01474 root->left_join_clauses =
01475 list_delete_cell(root->left_join_clauses, cell, prev);
01476
01477
01478 rinfo->norm_selec = 2.0;
01479 rinfo->outer_selec = 1.0;
01480 distribute_restrictinfo_to_rels(root, rinfo);
01481 }
01482 else
01483 prev = cell;
01484 }
01485
01486
01487 prev = NULL;
01488 for (cell = list_head(root->right_join_clauses); cell; cell = next)
01489 {
01490 RestrictInfo *rinfo = (RestrictInfo *) lfirst(cell);
01491
01492 next = lnext(cell);
01493 if (reconsider_outer_join_clause(root, rinfo, false))
01494 {
01495 found = true;
01496
01497 root->right_join_clauses =
01498 list_delete_cell(root->right_join_clauses, cell, prev);
01499
01500
01501 rinfo->norm_selec = 2.0;
01502 rinfo->outer_selec = 1.0;
01503 distribute_restrictinfo_to_rels(root, rinfo);
01504 }
01505 else
01506 prev = cell;
01507 }
01508
01509
01510 prev = NULL;
01511 for (cell = list_head(root->full_join_clauses); cell; cell = next)
01512 {
01513 RestrictInfo *rinfo = (RestrictInfo *) lfirst(cell);
01514
01515 next = lnext(cell);
01516 if (reconsider_full_join_clause(root, rinfo))
01517 {
01518 found = true;
01519
01520 root->full_join_clauses =
01521 list_delete_cell(root->full_join_clauses, cell, prev);
01522
01523
01524 rinfo->norm_selec = 2.0;
01525 rinfo->outer_selec = 1.0;
01526 distribute_restrictinfo_to_rels(root, rinfo);
01527 }
01528 else
01529 prev = cell;
01530 }
01531 } while (found);
01532
01533
01534 foreach(cell, root->left_join_clauses)
01535 {
01536 RestrictInfo *rinfo = (RestrictInfo *) lfirst(cell);
01537
01538 distribute_restrictinfo_to_rels(root, rinfo);
01539 }
01540 foreach(cell, root->right_join_clauses)
01541 {
01542 RestrictInfo *rinfo = (RestrictInfo *) lfirst(cell);
01543
01544 distribute_restrictinfo_to_rels(root, rinfo);
01545 }
01546 foreach(cell, root->full_join_clauses)
01547 {
01548 RestrictInfo *rinfo = (RestrictInfo *) lfirst(cell);
01549
01550 distribute_restrictinfo_to_rels(root, rinfo);
01551 }
01552 }
01553
01554
01555
01556
01557
01558
01559 static bool
01560 reconsider_outer_join_clause(PlannerInfo *root, RestrictInfo *rinfo,
01561 bool outer_on_left)
01562 {
01563 Expr *outervar,
01564 *innervar;
01565 Oid opno,
01566 collation,
01567 left_type,
01568 right_type,
01569 inner_datatype;
01570 Relids inner_relids,
01571 inner_nullable_relids;
01572 ListCell *lc1;
01573
01574 Assert(is_opclause(rinfo->clause));
01575 opno = ((OpExpr *) rinfo->clause)->opno;
01576 collation = ((OpExpr *) rinfo->clause)->inputcollid;
01577
01578
01579 if (rinfo->outerjoin_delayed && !op_strict(opno))
01580 return false;
01581
01582
01583 op_input_types(opno, &left_type, &right_type);
01584 if (outer_on_left)
01585 {
01586 outervar = (Expr *) get_leftop(rinfo->clause);
01587 innervar = (Expr *) get_rightop(rinfo->clause);
01588 inner_datatype = right_type;
01589 inner_relids = rinfo->right_relids;
01590 }
01591 else
01592 {
01593 outervar = (Expr *) get_rightop(rinfo->clause);
01594 innervar = (Expr *) get_leftop(rinfo->clause);
01595 inner_datatype = left_type;
01596 inner_relids = rinfo->left_relids;
01597 }
01598 inner_nullable_relids = bms_intersect(inner_relids,
01599 rinfo->nullable_relids);
01600
01601
01602 foreach(lc1, root->eq_classes)
01603 {
01604 EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc1);
01605 bool match;
01606 ListCell *lc2;
01607
01608
01609 if (!cur_ec->ec_has_const)
01610 continue;
01611
01612 if (cur_ec->ec_has_volatile)
01613 continue;
01614
01615 if (collation != cur_ec->ec_collation)
01616 continue;
01617 if (!equal(rinfo->mergeopfamilies, cur_ec->ec_opfamilies))
01618 continue;
01619
01620 match = false;
01621 foreach(lc2, cur_ec->ec_members)
01622 {
01623 EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2);
01624
01625 Assert(!cur_em->em_is_child);
01626 if (equal(outervar, cur_em->em_expr))
01627 {
01628 match = true;
01629 break;
01630 }
01631 }
01632 if (!match)
01633 continue;
01634
01635
01636
01637
01638
01639
01640 match = false;
01641 foreach(lc2, cur_ec->ec_members)
01642 {
01643 EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2);
01644 Oid eq_op;
01645 RestrictInfo *newrinfo;
01646
01647 if (!cur_em->em_is_const)
01648 continue;
01649 eq_op = select_equality_operator(cur_ec,
01650 inner_datatype,
01651 cur_em->em_datatype);
01652 if (!OidIsValid(eq_op))
01653 continue;
01654 newrinfo = build_implied_join_equality(eq_op,
01655 cur_ec->ec_collation,
01656 innervar,
01657 cur_em->em_expr,
01658 bms_copy(inner_relids),
01659 bms_copy(inner_nullable_relids));
01660 if (process_equivalence(root, newrinfo, true))
01661 match = true;
01662 }
01663
01664
01665
01666
01667
01668
01669 if (match)
01670 return true;
01671 else
01672 break;
01673 }
01674
01675 return false;
01676 }
01677
01678
01679
01680
01681
01682
01683 static bool
01684 reconsider_full_join_clause(PlannerInfo *root, RestrictInfo *rinfo)
01685 {
01686 Expr *leftvar;
01687 Expr *rightvar;
01688 Oid opno,
01689 collation,
01690 left_type,
01691 right_type;
01692 Relids left_relids,
01693 right_relids,
01694 left_nullable_relids,
01695 right_nullable_relids;
01696 ListCell *lc1;
01697
01698
01699 if (rinfo->outerjoin_delayed)
01700 return false;
01701
01702
01703 Assert(is_opclause(rinfo->clause));
01704 opno = ((OpExpr *) rinfo->clause)->opno;
01705 collation = ((OpExpr *) rinfo->clause)->inputcollid;
01706 op_input_types(opno, &left_type, &right_type);
01707 leftvar = (Expr *) get_leftop(rinfo->clause);
01708 rightvar = (Expr *) get_rightop(rinfo->clause);
01709 left_relids = rinfo->left_relids;
01710 right_relids = rinfo->right_relids;
01711 left_nullable_relids = bms_intersect(left_relids,
01712 rinfo->nullable_relids);
01713 right_nullable_relids = bms_intersect(right_relids,
01714 rinfo->nullable_relids);
01715
01716 foreach(lc1, root->eq_classes)
01717 {
01718 EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc1);
01719 EquivalenceMember *coal_em = NULL;
01720 bool match;
01721 bool matchleft;
01722 bool matchright;
01723 ListCell *lc2;
01724
01725
01726 if (!cur_ec->ec_has_const)
01727 continue;
01728
01729 if (cur_ec->ec_has_volatile)
01730 continue;
01731
01732 if (collation != cur_ec->ec_collation)
01733 continue;
01734 if (!equal(rinfo->mergeopfamilies, cur_ec->ec_opfamilies))
01735 continue;
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750 match = false;
01751 foreach(lc2, cur_ec->ec_members)
01752 {
01753 coal_em = (EquivalenceMember *) lfirst(lc2);
01754 Assert(!coal_em->em_is_child);
01755 if (IsA(coal_em->em_expr, CoalesceExpr))
01756 {
01757 CoalesceExpr *cexpr = (CoalesceExpr *) coal_em->em_expr;
01758 Node *cfirst;
01759 Node *csecond;
01760
01761 if (list_length(cexpr->args) != 2)
01762 continue;
01763 cfirst = (Node *) linitial(cexpr->args);
01764 csecond = (Node *) lsecond(cexpr->args);
01765
01766 if (equal(leftvar, cfirst) && equal(rightvar, csecond))
01767 {
01768 match = true;
01769 break;
01770 }
01771 }
01772 }
01773 if (!match)
01774 continue;
01775
01776
01777
01778
01779
01780
01781
01782 matchleft = matchright = false;
01783 foreach(lc2, cur_ec->ec_members)
01784 {
01785 EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2);
01786 Oid eq_op;
01787 RestrictInfo *newrinfo;
01788
01789 if (!cur_em->em_is_const)
01790 continue;
01791 eq_op = select_equality_operator(cur_ec,
01792 left_type,
01793 cur_em->em_datatype);
01794 if (OidIsValid(eq_op))
01795 {
01796 newrinfo = build_implied_join_equality(eq_op,
01797 cur_ec->ec_collation,
01798 leftvar,
01799 cur_em->em_expr,
01800 bms_copy(left_relids),
01801 bms_copy(left_nullable_relids));
01802 if (process_equivalence(root, newrinfo, true))
01803 matchleft = true;
01804 }
01805 eq_op = select_equality_operator(cur_ec,
01806 right_type,
01807 cur_em->em_datatype);
01808 if (OidIsValid(eq_op))
01809 {
01810 newrinfo = build_implied_join_equality(eq_op,
01811 cur_ec->ec_collation,
01812 rightvar,
01813 cur_em->em_expr,
01814 bms_copy(right_relids),
01815 bms_copy(right_nullable_relids));
01816 if (process_equivalence(root, newrinfo, true))
01817 matchright = true;
01818 }
01819 }
01820
01821
01822
01823
01824
01825
01826
01827
01828 if (matchleft && matchright)
01829 {
01830 cur_ec->ec_members = list_delete_ptr(cur_ec->ec_members, coal_em);
01831 return true;
01832 }
01833
01834
01835
01836
01837
01838
01839 break;
01840 }
01841
01842 return false;
01843 }
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858 bool
01859 exprs_known_equal(PlannerInfo *root, Node *item1, Node *item2)
01860 {
01861 ListCell *lc1;
01862
01863 foreach(lc1, root->eq_classes)
01864 {
01865 EquivalenceClass *ec = (EquivalenceClass *) lfirst(lc1);
01866 bool item1member = false;
01867 bool item2member = false;
01868 ListCell *lc2;
01869
01870
01871 if (ec->ec_has_volatile)
01872 continue;
01873
01874 foreach(lc2, ec->ec_members)
01875 {
01876 EquivalenceMember *em = (EquivalenceMember *) lfirst(lc2);
01877
01878 if (em->em_is_child)
01879 continue;
01880 if (equal(item1, em->em_expr))
01881 item1member = true;
01882 else if (equal(item2, em->em_expr))
01883 item2member = true;
01884
01885 if (item1member && item2member)
01886 return true;
01887 }
01888 }
01889 return false;
01890 }
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904 void
01905 add_child_rel_equivalences(PlannerInfo *root,
01906 AppendRelInfo *appinfo,
01907 RelOptInfo *parent_rel,
01908 RelOptInfo *child_rel)
01909 {
01910 ListCell *lc1;
01911
01912 foreach(lc1, root->eq_classes)
01913 {
01914 EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc1);
01915 ListCell *lc2;
01916
01917
01918
01919
01920
01921
01922 if (cur_ec->ec_has_volatile)
01923 continue;
01924
01925
01926 if (!bms_is_subset(parent_rel->relids, cur_ec->ec_relids))
01927 continue;
01928
01929 foreach(lc2, cur_ec->ec_members)
01930 {
01931 EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2);
01932
01933 if (cur_em->em_is_const || cur_em->em_is_child)
01934 continue;
01935
01936
01937 if (bms_overlap(cur_em->em_relids, parent_rel->relids))
01938 {
01939
01940 Expr *child_expr;
01941 Relids new_relids;
01942 Relids new_nullable_relids;
01943
01944 child_expr = (Expr *)
01945 adjust_appendrel_attrs(root,
01946 (Node *) cur_em->em_expr,
01947 appinfo);
01948
01949
01950
01951
01952
01953
01954
01955 new_relids = bms_difference(cur_em->em_relids,
01956 parent_rel->relids);
01957 new_relids = bms_add_members(new_relids, child_rel->relids);
01958
01959
01960
01961
01962
01963 new_nullable_relids = cur_em->em_nullable_relids;
01964 if (bms_overlap(new_nullable_relids, parent_rel->relids))
01965 {
01966 new_nullable_relids = bms_difference(new_nullable_relids,
01967 parent_rel->relids);
01968 new_nullable_relids = bms_add_members(new_nullable_relids,
01969 child_rel->relids);
01970 }
01971
01972 (void) add_eq_member(cur_ec, child_expr,
01973 new_relids, new_nullable_relids,
01974 true, cur_em->em_datatype);
01975 }
01976 }
01977 }
01978 }
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996 void
01997 mutate_eclass_expressions(PlannerInfo *root,
01998 Node *(*mutator) (),
01999 void *context,
02000 bool include_child_exprs)
02001 {
02002 ListCell *lc1;
02003
02004 foreach(lc1, root->eq_classes)
02005 {
02006 EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc1);
02007 ListCell *lc2;
02008
02009 foreach(lc2, cur_ec->ec_members)
02010 {
02011 EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2);
02012
02013 if (cur_em->em_is_child && !include_child_exprs)
02014 continue;
02015
02016 cur_em->em_expr = (Expr *)
02017 mutator((Node *) cur_em->em_expr, context);
02018 }
02019 }
02020 }
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046 List *
02047 generate_implied_equalities_for_column(PlannerInfo *root,
02048 RelOptInfo *rel,
02049 ec_matches_callback_type callback,
02050 void *callback_arg,
02051 Relids prohibited_rels)
02052 {
02053 List *result = NIL;
02054 bool is_child_rel = (rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
02055 Index parent_relid;
02056 ListCell *lc1;
02057
02058
02059 if (is_child_rel)
02060 parent_relid = find_childrel_appendrelinfo(root, rel)->parent_relid;
02061 else
02062 parent_relid = 0;
02063
02064 foreach(lc1, root->eq_classes)
02065 {
02066 EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc1);
02067 EquivalenceMember *cur_em;
02068 ListCell *lc2;
02069
02070
02071
02072
02073
02074 if (cur_ec->ec_has_const || list_length(cur_ec->ec_members) <= 1)
02075 continue;
02076
02077
02078
02079
02080
02081 if (!is_child_rel &&
02082 !bms_is_subset(rel->relids, cur_ec->ec_relids))
02083 continue;
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095 cur_em = NULL;
02096 foreach(lc2, cur_ec->ec_members)
02097 {
02098 cur_em = (EquivalenceMember *) lfirst(lc2);
02099 if (bms_equal(cur_em->em_relids, rel->relids) &&
02100 callback(root, rel, cur_ec, cur_em, callback_arg))
02101 break;
02102 cur_em = NULL;
02103 }
02104
02105 if (!cur_em)
02106 continue;
02107
02108
02109
02110
02111
02112 foreach(lc2, cur_ec->ec_members)
02113 {
02114 EquivalenceMember *other_em = (EquivalenceMember *) lfirst(lc2);
02115 Oid eq_op;
02116 RestrictInfo *rinfo;
02117
02118 if (other_em->em_is_child)
02119 continue;
02120
02121
02122 if (other_em == cur_em ||
02123 bms_overlap(other_em->em_relids, rel->relids))
02124 continue;
02125
02126
02127 if (bms_overlap(other_em->em_relids, prohibited_rels))
02128 continue;
02129
02130
02131
02132
02133
02134 if (is_child_rel &&
02135 bms_is_member(parent_relid, other_em->em_relids))
02136 continue;
02137
02138 eq_op = select_equality_operator(cur_ec,
02139 cur_em->em_datatype,
02140 other_em->em_datatype);
02141 if (!OidIsValid(eq_op))
02142 continue;
02143
02144
02145 rinfo = create_join_clause(root, cur_ec, eq_op,
02146 cur_em, other_em,
02147 cur_ec);
02148
02149 result = lappend(result, rinfo);
02150 }
02151
02152
02153
02154
02155
02156
02157 if (result)
02158 break;
02159 }
02160
02161 return result;
02162 }
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174 bool
02175 have_relevant_eclass_joinclause(PlannerInfo *root,
02176 RelOptInfo *rel1, RelOptInfo *rel2)
02177 {
02178 ListCell *lc1;
02179
02180 foreach(lc1, root->eq_classes)
02181 {
02182 EquivalenceClass *ec = (EquivalenceClass *) lfirst(lc1);
02183
02184
02185
02186
02187
02188 if (list_length(ec->ec_members) <= 1)
02189 continue;
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211 if (bms_overlap(rel1->relids, ec->ec_relids) &&
02212 bms_overlap(rel2->relids, ec->ec_relids))
02213 return true;
02214 }
02215
02216 return false;
02217 }
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228 bool
02229 has_relevant_eclass_joinclause(PlannerInfo *root, RelOptInfo *rel1)
02230 {
02231 ListCell *lc1;
02232
02233 foreach(lc1, root->eq_classes)
02234 {
02235 EquivalenceClass *ec = (EquivalenceClass *) lfirst(lc1);
02236
02237
02238
02239
02240
02241 if (list_length(ec->ec_members) <= 1)
02242 continue;
02243
02244
02245
02246
02247
02248 if (bms_overlap(rel1->relids, ec->ec_relids) &&
02249 !bms_is_subset(ec->ec_relids, rel1->relids))
02250 return true;
02251 }
02252
02253 return false;
02254 }
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267 bool
02268 eclass_useful_for_merging(EquivalenceClass *eclass,
02269 RelOptInfo *rel)
02270 {
02271 ListCell *lc;
02272
02273 Assert(!eclass->ec_merged);
02274
02275
02276
02277
02278
02279 if (eclass->ec_has_const || list_length(eclass->ec_members) <= 1)
02280 return false;
02281
02282
02283
02284
02285
02286
02287
02288
02289 if (bms_is_subset(eclass->ec_relids, rel->relids))
02290 return false;
02291
02292
02293 foreach(lc, eclass->ec_members)
02294 {
02295 EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc);
02296
02297 if (cur_em->em_is_child)
02298 continue;
02299
02300 if (!bms_overlap(cur_em->em_relids, rel->relids))
02301 return true;
02302 }
02303
02304 return false;
02305 }
02306
02307
02308
02309
02310
02311
02312
02313
02314 bool
02315 is_redundant_derived_clause(RestrictInfo *rinfo, List *clauselist)
02316 {
02317 EquivalenceClass *parent_ec = rinfo->parent_ec;
02318 ListCell *lc;
02319
02320
02321 if (parent_ec == NULL)
02322 return false;
02323
02324 foreach(lc, clauselist)
02325 {
02326 RestrictInfo *otherrinfo = (RestrictInfo *) lfirst(lc);
02327
02328 if (otherrinfo->parent_ec == parent_ec)
02329 return true;
02330 }
02331
02332 return false;
02333 }