datafusion_python/expr/
projection.rs1use std::fmt::{self, Display, Formatter};
19
20use datafusion::logical_expr::logical_plan::Projection;
21use datafusion::logical_expr::Expr;
22use pyo3::prelude::*;
23use pyo3::IntoPyObjectExt;
24
25use crate::common::df_schema::PyDFSchema;
26use crate::expr::logical_node::LogicalNode;
27use crate::expr::PyExpr;
28use crate::sql::logical::PyLogicalPlan;
29
30#[pyclass(frozen, name = "Projection", module = "datafusion.expr", subclass)]
31#[derive(Clone)]
32pub struct PyProjection {
33 pub projection: Projection,
34}
35
36impl PyProjection {
37 pub fn new(projection: Projection) -> Self {
38 Self { projection }
39 }
40}
41
42impl From<Projection> for PyProjection {
43 fn from(projection: Projection) -> PyProjection {
44 PyProjection { projection }
45 }
46}
47
48impl From<PyProjection> for Projection {
49 fn from(proj: PyProjection) -> Self {
50 proj.projection
51 }
52}
53
54impl Display for PyProjection {
55 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
56 write!(
57 f,
58 "Projection
59 \nExpr(s): {:?}
60 \nInput: {:?}
61 \nProjected Schema: {:?}",
62 &self.projection.expr, &self.projection.input, &self.projection.schema,
63 )
64 }
65}
66
67#[pymethods]
68impl PyProjection {
69 fn projections(&self) -> PyResult<Vec<PyExpr>> {
71 Ok(self
72 .projection
73 .expr
74 .iter()
75 .map(|e| PyExpr::from(e.clone()))
76 .collect())
77 }
78
79 fn input(&self) -> PyResult<Vec<PyLogicalPlan>> {
81 Ok(Self::inputs(self))
82 }
83
84 fn schema(&self) -> PyResult<PyDFSchema> {
86 Ok((*self.projection.schema).clone().into())
87 }
88
89 fn __repr__(&self) -> PyResult<String> {
90 Ok(format!("Projection({self})"))
91 }
92
93 fn __name__(&self) -> PyResult<String> {
94 Ok("Projection".to_string())
95 }
96}
97
98impl PyProjection {
99 pub fn projected_expressions(local_expr: &PyExpr) -> Vec<PyExpr> {
101 let mut projs: Vec<PyExpr> = Vec::new();
102 match &local_expr.expr {
103 Expr::Alias(alias) => {
104 let py_expr: PyExpr = PyExpr::from(*alias.expr.clone());
105 projs.extend_from_slice(Self::projected_expressions(&py_expr).as_slice());
106 }
107 _ => projs.push(local_expr.clone()),
108 }
109 projs
110 }
111}
112
113impl LogicalNode for PyProjection {
114 fn inputs(&self) -> Vec<PyLogicalPlan> {
115 vec![PyLogicalPlan::from((*self.projection.input).clone())]
116 }
117
118 fn to_variant<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
119 self.clone().into_bound_py_any(py)
120 }
121}