Applies a `TableFunc` to every row, followed by an `mfp`.
(
&self,
input_key: Option<Vec<MirScalarExpr>>,
input: CollectionBundle<'scope, T>,
exprs: Vec<MirScalarExpr>,
func: TableFunc,
mfp: MapFilterProject,
| 27 | impl<'scope, T: crate::render::RenderTimestamp> Context<'scope, T> { |
| 28 | /// Applies a `TableFunc` to every row, followed by an `mfp`. |
| 29 | pub fn render_flat_map( |
| 30 | &self, |
| 31 | input_key: Option<Vec<MirScalarExpr>>, |
| 32 | input: CollectionBundle<'scope, T>, |
| 33 | exprs: Vec<MirScalarExpr>, |
| 34 | func: TableFunc, |
| 35 | mfp: MapFilterProject, |
| 36 | ) -> CollectionBundle<'scope, T> { |
| 37 | let until = self.until.clone(); |
| 38 | let mfp_plan = mfp.into_plan().expect("MapFilterProject planning failed"); |
| 39 | let (ok_collection, err_collection) = |
| 40 | input.as_specific_collection(input_key.as_deref(), &self.config_set); |
| 41 | let stream = ok_collection.inner; |
| 42 | let scope = input.scope(); |
| 43 | |
| 44 | // Budget to limit the number of rows processed in a single invocation. |
| 45 | // |
| 46 | // The current implementation can only yield between input batches, but not from within |
| 47 | // a batch. A `generate_series` can still cause unavailability if it generates many rows. |
| 48 | let budget = COMPUTE_FLAT_MAP_FUEL.get(&self.config_set); |
| 49 | |
| 50 | let (oks, errs) = stream.unary_fallible(Pipeline, "FlatMapStage", move |_, info| { |
| 51 | let activator = scope.activator_for(info.address); |
| 52 | let mut queue = VecDeque::new(); |
| 53 | Box::new(move |input, ok_output, err_output| { |
| 54 | let mut datums = DatumVec::new(); |
| 55 | let mut datums_mfp = DatumVec::new(); |
| 56 | |
| 57 | // Buffer for extensions to `input_row`. |
| 58 | let mut table_func_output = Vec::new(); |
| 59 | |
| 60 | let mut budget = budget; |
| 61 | |
| 62 | input.for_each(|cap, data| { |
| 63 | queue.push_back((cap.retain(0), cap.retain(1), std::mem::take(data))) |
| 64 | }); |
| 65 | |
| 66 | while let Some((ok_cap, err_cap, data)) = queue.pop_front() { |
| 67 | let mut ok_session = ok_output.session_with_builder(&ok_cap); |
| 68 | let mut err_session = err_output.session_with_builder(&err_cap); |
| 69 | |
| 70 | 'input: for (input_row, time, diff) in data { |
| 71 | let temp_storage = RowArena::new(); |
| 72 | |
| 73 | // Unpack datums for expression evaluation. |
| 74 | let datums_local = datums.borrow_with(&input_row); |
| 75 | let args = exprs |
| 76 | .iter() |
| 77 | .map(|e| e.eval(&datums_local, &temp_storage)) |
| 78 | .collect::<Result<Vec<_>, _>>(); |
| 79 | let args = match args { |
| 80 | Ok(args) => args, |
| 81 | Err(e) => { |
| 82 | err_session.give((e.into(), time, diff)); |
| 83 | continue 'input; |
| 84 | } |
| 85 | }; |
| 86 | let mut extensions = match func.eval(&args, &temp_storage) { |
no test coverage detected