Prepare to apply `inner` to `outer`. Note that `inner` is a correlated (SQL) expression, while `outer` is a non-correlated (dataflow) expression. `inner` will, in effect, be executed once for every distinct row in `outer`, and the results will be joined with `outer`. Note that columns in `outer` that are not depended upon by `inner` are thrown away before the distinct, so that we don't perform nee
(
id_gen: &mut mz_ore::id_gen::IdGen,
outer: MirRelationExpr,
col_map: &ColumnMap,
cte_map: &mut CteMap,
inner: HirRelationExpr,
apply_requires_distinct_outer: bool,
contex
| 1766 | /// The caller must supply the `apply` function that applies the rewritten |
| 1767 | /// `inner` to `outer`. |
| 1768 | fn branch<F>( |
| 1769 | id_gen: &mut mz_ore::id_gen::IdGen, |
| 1770 | outer: MirRelationExpr, |
| 1771 | col_map: &ColumnMap, |
| 1772 | cte_map: &mut CteMap, |
| 1773 | inner: HirRelationExpr, |
| 1774 | apply_requires_distinct_outer: bool, |
| 1775 | context: &Context, |
| 1776 | apply: F, |
| 1777 | ) -> Result<MirRelationExpr, PlanError> |
| 1778 | where |
| 1779 | F: FnOnce( |
| 1780 | &mut mz_ore::id_gen::IdGen, |
| 1781 | HirRelationExpr, |
| 1782 | MirRelationExpr, |
| 1783 | &ColumnMap, |
| 1784 | &mut CteMap, |
| 1785 | &Context, |
| 1786 | ) -> Result<MirRelationExpr, PlanError>, |
| 1787 | { |
| 1788 | // TODO: It would be nice to have a version of this code w/o optimizations, |
| 1789 | // at the least for purposes of understanding. It was difficult for one reader |
| 1790 | // to understand the required properties of `outer` and `col_map`. |
| 1791 | |
| 1792 | // If the inner expression is sufficiently simple, it is safe to apply it |
| 1793 | // *directly* to outer, rather than applying it to the distinctified key |
| 1794 | // (see below). |
| 1795 | // |
| 1796 | // As an example, consider the following two queries: |
| 1797 | // |
| 1798 | // CREATE TABLE t (a int, b int); |
| 1799 | // SELECT a, series FROM t, generate_series(1, t.b) series; |
| 1800 | // |
| 1801 | // The "simple" path for the `SELECT` yields |
| 1802 | // |
| 1803 | // %0 = |
| 1804 | // | Get t |
| 1805 | // | FlatMap generate_series(1, #1) |
| 1806 | // |
| 1807 | // while the non-simple path yields: |
| 1808 | // |
| 1809 | // %0 = |
| 1810 | // | Get t |
| 1811 | // |
| 1812 | // %1 = |
| 1813 | // | Get t |
| 1814 | // | Distinct group=(#1) |
| 1815 | // | FlatMap generate_series(1, #0) |
| 1816 | // |
| 1817 | // %2 = |
| 1818 | // | LeftJoin %1 %2 (= #1 #2) |
| 1819 | // |
| 1820 | // There is a tradeoff here: the simple plan is stateless, but the non- |
| 1821 | // simple plan may do (much) less computation if there are only a few |
| 1822 | // distinct values of `t.b`. |
| 1823 | // |
| 1824 | // We apply a very simple heuristic here and take the simple path if `inner` |
| 1825 | // contains only maps, filters, projections, and calls to table functions. |
no test coverage detected