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