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