(
catalog: &TestCatalog,
input: &str,
args: &std::collections::HashMap<String, Vec<String>>,
)
| 41 | |
| 42 | #[allow(clippy::disallowed_types)] |
| 43 | fn handle_explain( |
| 44 | catalog: &TestCatalog, |
| 45 | input: &str, |
| 46 | args: &std::collections::HashMap<String, Vec<String>>, |
| 47 | ) -> String { |
| 48 | let with = match args.get("with") { |
| 49 | Some(with) => with.iter().cloned().collect::<BTreeSet<String>>(), |
| 50 | None => return "missing required `with` argument for `explain` directive".to_string(), |
| 51 | }; |
| 52 | |
| 53 | // Create the ExplainConfig from the given `with` set of strings. |
| 54 | let config = match parse_explain_config(with) { |
| 55 | Ok(config) => config, |
| 56 | Err(e) => return format!("ExplainConfig::try_from error\n{}\n", e.to_string().trim()), |
| 57 | }; |
| 58 | |
| 59 | // Create OptimizerFeatures and override from the config overrides layer. |
| 60 | let features = OptimizerFeatures::default().override_from(&config.features); |
| 61 | |
| 62 | let context = ExplainContext { |
| 63 | config: &config, |
| 64 | features: &features, |
| 65 | humanizer: catalog, |
| 66 | cardinality_stats: Default::default(), // empty stats |
| 67 | used_indexes: Default::default(), |
| 68 | finishing: Default::default(), |
| 69 | duration: Default::default(), |
| 70 | target_cluster: Default::default(), |
| 71 | optimizer_notices: Default::default(), |
| 72 | }; |
| 73 | |
| 74 | // Parse the relation, returning early on parse error. |
| 75 | let mut relation = match try_parse_mir(catalog, input) { |
| 76 | Ok(relation) => relation, |
| 77 | Err(e) => return format!("try_parse_mir error:\n{}\n", e.to_string().trim()), |
| 78 | }; |
| 79 | |
| 80 | // normalize the representation as linear chains |
| 81 | // (this implies !context.config.raw_plans by construction) |
| 82 | if context.config.linear_chains { |
| 83 | match enforce_linear_chains(&mut relation) { |
| 84 | Ok(_) => {} |
| 85 | Err(e) => return format!("enforce_linear_chains error:\n{}\n", e.to_string().trim()), |
| 86 | }; |
| 87 | }; |
| 88 | |
| 89 | // We deliberately don't interpret the `raw_plans` config option here, |
| 90 | // because we might want to test the output of things that are reset when it |
| 91 | // is set. For test purposes we never want to implicitly normalize the plan |
| 92 | // as part this statement. |
| 93 | |
| 94 | let annotated_plan = match annotate_plan(&relation, &context) { |
| 95 | Ok(annotated_plan) => annotated_plan, |
| 96 | Err(e) => return format!("annotate_plan error:\n{}\n", e.to_string().trim()), |
| 97 | }; |
| 98 | |
| 99 | text_string_at(annotated_plan.plan, || PlanRenderingContext { |
| 100 | indent: Indent::default(), |
no test coverage detected