* get_eclass_for_sort_expr * Given an expression and opfamily/collation info, find an existing * equivalence class it is a member of; if none, optionally build a new * single-member EquivalenceClass for it. * * expr is the expression, and nullable_relids is the set of base relids * that are potentially nullable below it. We actually only care about * the set of such relids that are u
| 618 | * generating poor (but not incorrect) plans. |
| 619 | */ |
| 620 | EquivalenceClass * |
| 621 | get_eclass_for_sort_expr(PlannerInfo *root, |
| 622 | Expr *expr, |
| 623 | Relids nullable_relids, |
| 624 | List *opfamilies, |
| 625 | Oid opcintype, |
| 626 | Oid collation, |
| 627 | Index sortref, |
| 628 | Relids rel, |
| 629 | bool create_it) |
| 630 | { |
| 631 | Relids expr_relids; |
| 632 | EquivalenceClass *newec; |
| 633 | EquivalenceMember *newem; |
| 634 | ListCell *lc1; |
| 635 | MemoryContext oldcontext; |
| 636 | |
| 637 | /* |
| 638 | * Ensure the expression exposes the correct type and collation. |
| 639 | */ |
| 640 | expr = canonicalize_ec_expression(expr, opcintype, collation); |
| 641 | |
| 642 | /* |
| 643 | * Scan through the existing EquivalenceClasses for a match |
| 644 | */ |
| 645 | foreach(lc1, root->eq_classes) |
| 646 | { |
| 647 | EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc1); |
| 648 | ListCell *lc2; |
| 649 | |
| 650 | /* |
| 651 | * Never match to a volatile EC, except when we are looking at another |
| 652 | * reference to the same volatile SortGroupClause. |
| 653 | */ |
| 654 | if (cur_ec->ec_has_volatile && |
| 655 | (sortref == 0 || sortref != cur_ec->ec_sortref)) |
| 656 | continue; |
| 657 | |
| 658 | if (collation != cur_ec->ec_collation) |
| 659 | continue; |
| 660 | if (!equal(opfamilies, cur_ec->ec_opfamilies)) |
| 661 | continue; |
| 662 | |
| 663 | foreach(lc2, cur_ec->ec_members) |
| 664 | { |
| 665 | EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2); |
| 666 | |
| 667 | /* |
| 668 | * Ignore child members unless they match the request. |
| 669 | */ |
| 670 | if (cur_em->em_is_child && |
| 671 | !bms_equal(cur_em->em_relids, rel)) |
| 672 | continue; |
| 673 | |
| 674 | /* |
| 675 | * If below an outer join, don't match constants: they're not as |
| 676 | * constant as they look. |
| 677 | */ |
no test coverage detected