// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. use std::fmt::{self, Display, Formatter}; use datafusion_expr::{logical_plan::Explain, LogicalPlan}; use pyo3::prelude::*; use crate::{common::df_schema::PyDFSchema, errors::py_type_err, sql::logical::PyLogicalPlan}; use super::logical_node::LogicalNode; #[pyclass(name = "Explain", module = "datafusion.expr", subclass)] #[derive(Clone)] pub struct PyExplain { explain: Explain, } impl From for Explain { fn from(explain: PyExplain) -> Self { explain.explain } } impl From for PyExplain { fn from(explain: Explain) -> PyExplain { PyExplain { explain } } } impl Display for PyExplain { fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!( f, "Explain verbose: {:?} plan: {:?} stringified_plans: {:?} schema: {:?} logical_optimization_succeeded: {:?}", &self.explain.verbose, &self.explain.plan, &self.explain.stringified_plans, &self.explain.schema, &self.explain.logical_optimization_succeeded ) } } #[pymethods] impl PyExplain { fn explain_string(&self) -> PyResult> { let mut string_plans: Vec = Vec::new(); for stringified_plan in &self.explain.stringified_plans { string_plans.push((*stringified_plan.plan).clone()); } Ok(string_plans) } fn verbose(&self) -> bool { self.explain.verbose } fn plan(&self) -> PyResult { Ok(PyLogicalPlan::from((*self.explain.plan).clone())) } fn schema(&self) -> PyDFSchema { (*self.explain.schema).clone().into() } fn logical_optimization_succceeded(&self) -> bool { self.explain.logical_optimization_succeeded } } impl TryFrom for PyExplain { type Error = PyErr; fn try_from(logical_plan: LogicalPlan) -> Result { match logical_plan { LogicalPlan::Explain(explain) => Ok(PyExplain { explain }), _ => Err(py_type_err("unexpected plan")), } } } impl LogicalNode for PyExplain { fn inputs(&self) -> Vec { vec![] } fn to_variant(&self, py: Python) -> PyResult { Ok(self.clone().into_py(py)) } }