datafusion_python/expr/
explain.rs1use std::fmt::{self, Display, Formatter};
19
20use datafusion::logical_expr::logical_plan::Explain;
21use datafusion::logical_expr::LogicalPlan;
22use pyo3::prelude::*;
23use pyo3::IntoPyObjectExt;
24
25use super::logical_node::LogicalNode;
26use crate::common::df_schema::PyDFSchema;
27use crate::errors::py_type_err;
28use crate::sql::logical::PyLogicalPlan;
29
30#[pyclass(frozen, name = "Explain", module = "datafusion.expr", subclass)]
31#[derive(Clone)]
32pub struct PyExplain {
33 explain: Explain,
34}
35
36impl From<PyExplain> for Explain {
37 fn from(explain: PyExplain) -> Self {
38 explain.explain
39 }
40}
41
42impl From<Explain> for PyExplain {
43 fn from(explain: Explain) -> PyExplain {
44 PyExplain { explain }
45 }
46}
47
48impl Display for PyExplain {
49 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
50 write!(
51 f,
52 "Explain
53 verbose: {:?}
54 plan: {:?}
55 stringified_plans: {:?}
56 schema: {:?}
57 logical_optimization_succeeded: {:?}",
58 &self.explain.verbose,
59 &self.explain.plan,
60 &self.explain.stringified_plans,
61 &self.explain.schema,
62 &self.explain.logical_optimization_succeeded
63 )
64 }
65}
66
67#[pymethods]
68impl PyExplain {
69 fn explain_string(&self) -> PyResult<Vec<String>> {
70 let mut string_plans: Vec<String> = Vec::new();
71 for stringified_plan in &self.explain.stringified_plans {
72 string_plans.push((*stringified_plan.plan).clone());
73 }
74 Ok(string_plans)
75 }
76
77 fn verbose(&self) -> bool {
78 self.explain.verbose
79 }
80
81 fn plan(&self) -> PyResult<PyLogicalPlan> {
82 Ok(PyLogicalPlan::from((*self.explain.plan).clone()))
83 }
84
85 fn schema(&self) -> PyDFSchema {
86 (*self.explain.schema).clone().into()
87 }
88
89 fn logical_optimization_succceeded(&self) -> bool {
90 self.explain.logical_optimization_succeeded
91 }
92}
93
94impl TryFrom<LogicalPlan> for PyExplain {
95 type Error = PyErr;
96
97 fn try_from(logical_plan: LogicalPlan) -> Result<Self, Self::Error> {
98 match logical_plan {
99 LogicalPlan::Explain(explain) => Ok(PyExplain { explain }),
100 _ => Err(py_type_err("unexpected plan")),
101 }
102 }
103}
104
105impl LogicalNode for PyExplain {
106 fn inputs(&self) -> Vec<PyLogicalPlan> {
107 vec![]
108 }
109
110 fn to_variant<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
111 self.clone().into_bound_py_any(py)
112 }
113}