Partitions `self` into two instances, one of which can be eagerly applied. The `available` argument indicates which input columns are available (keys) and in which positions (values). This information may allow some maps and filters to execute. The `input_arity` argument reports the total number of input columns (which may include some not present in `available`) This method partitions `self` in
(self, available: BTreeMap<usize, usize>, input_arity: usize)
| 721 | /// // optimize the representation. |
| 722 | /// ``` |
| 723 | pub fn partition(self, available: BTreeMap<usize, usize>, input_arity: usize) -> (Self, Self) { |
| 724 | // Map expressions, filter predicates, and projections for `before` and `after`. |
| 725 | let mut before_expr = Vec::new(); |
| 726 | let mut before_pred = Vec::new(); |
| 727 | let mut before_proj = Vec::new(); |
| 728 | let mut after_expr = Vec::new(); |
| 729 | let mut after_pred = Vec::new(); |
| 730 | let mut after_proj = Vec::new(); |
| 731 | |
| 732 | // Track which output columns must be preserved in the output of `before`. |
| 733 | let mut demanded = BTreeSet::new(); |
| 734 | demanded.extend(0..self.input_arity); |
| 735 | demanded.extend(self.projection.iter()); |
| 736 | |
| 737 | // Determine which map expressions can be computed from the available subset. |
| 738 | // Some expressions may depend on other expressions, but by evaluating them |
| 739 | // in forward order we should accurately determine the available expressions. |
| 740 | let mut available_expr = vec![false; self.input_arity]; |
| 741 | // Initialize available columns from `available`, which is then not used again. |
| 742 | for index in available.keys() { |
| 743 | available_expr[*index] = true; |
| 744 | } |
| 745 | for expr in self.expressions.into_iter() { |
| 746 | // We treat an expression as available if its supporting columns are available, |
| 747 | // and if it is not a literal (we want to avoid pushing down literals). This |
| 748 | // choice is ad-hoc, but the intent is that we partition the operators so |
| 749 | // that we can reduce the row representation size and total computation. |
| 750 | // Pushing down literals harms the former and does nothing for the latter. |
| 751 | // In the future, we'll want to have a harder think about this trade-off, as |
| 752 | // we are certainly making sub-optimal decisions by pushing down all available |
| 753 | // work. |
| 754 | // TODO(mcsherry): establish better principles about what work to push down. |
| 755 | let is_available = expr.support().into_iter().all(|i| available_expr[i]) |
| 756 | && !OptimizableExpr::is_literal(&expr); |
| 757 | if is_available { |
| 758 | before_expr.push(expr); |
| 759 | } else { |
| 760 | demanded.extend(expr.support()); |
| 761 | after_expr.push(expr); |
| 762 | } |
| 763 | available_expr.push(is_available); |
| 764 | } |
| 765 | |
| 766 | // Determine which predicates can be computed from the available subset. |
| 767 | for (_when, pred) in self.predicates.into_iter() { |
| 768 | let is_available = pred.support().into_iter().all(|i| available_expr[i]); |
| 769 | if is_available { |
| 770 | before_pred.push(pred); |
| 771 | } else { |
| 772 | demanded.extend(pred.support()); |
| 773 | after_pred.push(pred); |
| 774 | } |
| 775 | } |
| 776 | |
| 777 | // Map from prior output location to location in un-projected `before`. |
| 778 | // This map is used to correct references in `before` but it should be |
| 779 | // adjusted to reflect `before`s projection prior to use in `after`. |
| 780 | let mut before_map = available; |