* cdb_pull_up_eclass * * Given an argument EquivalenceClass, finds an EquivalenceClass whose * expr can be projected thru a given targetlist. If found, builds the * transformed key expr and returns an equivalence class containing it. * * Returns NULL if the given EC does not have any member that can be * rewritten in terms of the projected output columns. * * Note that this function doe
| 1546 | * expr in determining whether an EC member expr matches a targetlist expr. |
| 1547 | */ |
| 1548 | EquivalenceClass * |
| 1549 | cdb_pull_up_eclass(PlannerInfo *root, |
| 1550 | EquivalenceClass *eclass, |
| 1551 | Relids relids, |
| 1552 | List *targetlist, |
| 1553 | List *newvarlist, |
| 1554 | Index newrelid, |
| 1555 | bool ignore_relabel) |
| 1556 | { |
| 1557 | Expr *sub_distkeyexpr; |
| 1558 | EquivalenceClass *outer_ec; |
| 1559 | Expr *newexpr = NULL; |
| 1560 | Index sortref = 0; |
| 1561 | bool relabel_stripped = false; |
| 1562 | |
| 1563 | Assert(eclass); |
| 1564 | Assert(!newvarlist || |
| 1565 | list_length(newvarlist) == list_length(targetlist)); |
| 1566 | |
| 1567 | /* Find an expr that we can rewrite to use the projected columns. */ |
| 1568 | sub_distkeyexpr = cdbpullup_findEclassInTargetList(eclass, targetlist, InvalidOid, &relabel_stripped); |
| 1569 | |
| 1570 | /* Replace expr's Var nodes with new ones referencing the targetlist. */ |
| 1571 | if (sub_distkeyexpr) |
| 1572 | { |
| 1573 | if (ignore_relabel && relabel_stripped) |
| 1574 | return eclass; |
| 1575 | |
| 1576 | newexpr = cdbpullup_expr(sub_distkeyexpr, |
| 1577 | targetlist, |
| 1578 | newvarlist, |
| 1579 | newrelid); |
| 1580 | } |
| 1581 | /* If not found, see if the equiv class contains a constant expr. */ |
| 1582 | else if (CdbEquivClassIsConstant(eclass)) |
| 1583 | { |
| 1584 | ListCell *lc; |
| 1585 | |
| 1586 | foreach(lc, eclass->ec_members) |
| 1587 | { |
| 1588 | EquivalenceMember *em = lfirst(lc); |
| 1589 | |
| 1590 | if (em->em_is_const) |
| 1591 | { |
| 1592 | newexpr = (Expr *) copyObject(em->em_expr); |
| 1593 | break; |
| 1594 | } |
| 1595 | } |
| 1596 | } |
| 1597 | /* Fail if no usable expr. */ |
| 1598 | else |
| 1599 | return NULL; |
| 1600 | |
| 1601 | if (!newexpr) |
| 1602 | elog(ERROR, "could not pull up equivalence class using projected target list"); |
| 1603 | |
| 1604 | /* |
| 1605 | * See https://github.com/apache/cloudberry/issues/593 |
no test coverage detected