(dataflow: &mut DataflowDesc)
| 116 | fields(path.segment = "inline_views") |
| 117 | )] |
| 118 | fn inline_views(dataflow: &mut DataflowDesc) -> Result<(), TransformError> { |
| 119 | // We cannot inline anything whose `BuildDesc::id` appears in either the |
| 120 | // `index_exports` or `sink_exports` of `dataflow`, because we lose our |
| 121 | // ability to name it. |
| 122 | |
| 123 | // A view can / should be in-lined in another view if it is only used by |
| 124 | // one subsequent view. If there are two distinct views that have not |
| 125 | // themselves been merged, then too bad and it doesn't get inlined. |
| 126 | |
| 127 | // Starting from the *last* object to build, walk backwards and inline |
| 128 | // any view that is neither referenced by a `index_exports` nor |
| 129 | // `sink_exports` nor more than two remaining objects to build. |
| 130 | |
| 131 | for index in (0..dataflow.objects_to_build.len()).rev() { |
| 132 | // Capture the name used by others to reference this view. |
| 133 | let global_id = dataflow.objects_to_build[index].id; |
| 134 | // Determine if any exports directly reference this view. |
| 135 | let mut occurs_in_export = false; |
| 136 | for (_gid, sink_desc) in dataflow.sink_exports.iter() { |
| 137 | if sink_desc.from == global_id { |
| 138 | occurs_in_export = true; |
| 139 | } |
| 140 | } |
| 141 | for (_, (index_desc, _)) in dataflow.index_exports.iter() { |
| 142 | if index_desc.on_id == global_id { |
| 143 | occurs_in_export = true; |
| 144 | } |
| 145 | } |
| 146 | // Count the number of subsequent views that reference this view. |
| 147 | let mut occurrences_in_later_views = Vec::new(); |
| 148 | for other in (index + 1)..dataflow.objects_to_build.len() { |
| 149 | if dataflow.objects_to_build[other] |
| 150 | .plan |
| 151 | .depends_on() |
| 152 | .contains(&global_id) |
| 153 | { |
| 154 | occurrences_in_later_views.push(other); |
| 155 | } |
| 156 | } |
| 157 | // Inline if the view is referenced in one view and no exports. |
| 158 | if !occurs_in_export && occurrences_in_later_views.len() == 1 { |
| 159 | let other = occurrences_in_later_views[0]; |
| 160 | // We can remove this view and insert it in the later view, |
| 161 | // but are not able to relocate the later view `other`. |
| 162 | |
| 163 | // When splicing in the `index` view, we need to create disjoint |
| 164 | // identifiers for the Let's `body` and `value`, as well as a new |
| 165 | // identifier for the binding itself. Following `NormalizeLets`, we |
| 166 | // go with the binding first, then the value, then the body. |
| 167 | let mut id_gen = crate::IdGen::default(); |
| 168 | let new_local = LocalId::new(id_gen.allocate_id()); |
| 169 | // Use the same `id_gen` to assign new identifiers to `index`. |
| 170 | crate::normalize_lets::renumber_bindings( |
| 171 | dataflow.objects_to_build[index].plan.as_inner_mut(), |
| 172 | &mut id_gen, |
| 173 | )?; |
| 174 | // Assign new identifiers to the other relation. |
| 175 | crate::normalize_lets::renumber_bindings( |
no test coverage detected