Skip to content

Commit 1b97b41

Browse files
committed
Replace case builter with keeping the expressions and then applying as required
1 parent 8a52e23 commit 1b97b41

File tree

2 files changed

+45
-36
lines changed

2 files changed

+45
-36
lines changed

src/expr/conditional_expr.rs

Lines changed: 43 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -16,56 +16,65 @@
1616
// under the License.
1717

1818
use crate::{errors::PyDataFusionResult, expr::PyExpr};
19-
use datafusion::common::{exec_err, DataFusionError};
2019
use datafusion::logical_expr::conditional_expressions::CaseBuilder;
2120
use datafusion::prelude::Expr;
2221
use pyo3::prelude::*;
2322

23+
// TODO(tsaucer) replace this all with CaseBuilder after it implements Clone
24+
#[derive(Clone, Debug)]
2425
#[pyclass(name = "CaseBuilder", module = "datafusion.expr", subclass, frozen)]
2526
pub struct PyCaseBuilder {
26-
case_builder: CaseBuilder,
27+
expr: Option<Expr>,
28+
when: Vec<Expr>,
29+
then: Vec<Expr>,
2730
}
2831

29-
impl From<CaseBuilder> for PyCaseBuilder {
30-
fn from(case_builder: CaseBuilder) -> PyCaseBuilder {
31-
PyCaseBuilder { case_builder }
32+
#[pymethods]
33+
impl PyCaseBuilder {
34+
#[new]
35+
pub fn new(expr: Option<PyExpr>) -> Self {
36+
Self {
37+
expr: expr.map(Into::into),
38+
when: vec![],
39+
then: vec![],
40+
}
3241
}
33-
}
34-
35-
// TODO(tsaucer) upstream make CaseBuilder impl Clone
36-
fn builder_clone(case_builder: &CaseBuilder) -> Result<CaseBuilder, DataFusionError> {
37-
let Expr::Case(case) = case_builder.end()? else {
38-
return exec_err!("CaseBuilder returned an invalid expression");
39-
};
4042

41-
let (when_expr, then_expr) = case
42-
.when_then_expr
43-
.iter()
44-
.map(|(w, t)| (w.as_ref().to_owned(), t.as_ref().to_owned()))
45-
.unzip();
43+
pub fn when(&self, when: PyExpr, then: PyExpr) -> PyCaseBuilder {
44+
println!("when called {self:?}");
45+
let mut case_builder = self.clone();
46+
case_builder.when.push(when.into());
47+
case_builder.then.push(then.into());
4648

47-
Ok(CaseBuilder::new(
48-
case.expr,
49-
when_expr,
50-
then_expr,
51-
case.else_expr,
52-
))
53-
}
54-
55-
#[pymethods]
56-
impl PyCaseBuilder {
57-
fn when(&self, when: PyExpr, then: PyExpr) -> PyDataFusionResult<PyCaseBuilder> {
58-
let case_builder = builder_clone(&self.case_builder)?.when(when.expr, then.expr);
59-
Ok(PyCaseBuilder { case_builder })
49+
case_builder
6050
}
6151

6252
fn otherwise(&self, else_expr: PyExpr) -> PyDataFusionResult<PyExpr> {
63-
Ok(builder_clone(&self.case_builder)?
64-
.otherwise(else_expr.expr)?
65-
.into())
53+
println!("otherwise called {self:?}");
54+
let case_builder = CaseBuilder::new(
55+
self.expr.clone().map(Box::new),
56+
self.when.clone(),
57+
self.then.clone(),
58+
Some(Box::new(else_expr.into())),
59+
);
60+
61+
let expr = case_builder.end()?;
62+
63+
Ok(expr.into())
6664
}
6765

6866
fn end(&self) -> PyDataFusionResult<PyExpr> {
69-
Ok(builder_clone(&self.case_builder)?.end()?.into())
67+
println!("end called {self:?}");
68+
69+
let case_builder = CaseBuilder::new(
70+
self.expr.clone().map(Box::new),
71+
self.when.clone(),
72+
self.then.clone(),
73+
None,
74+
);
75+
76+
let expr = case_builder.end()?;
77+
78+
Ok(expr.into())
7079
}
7180
}

src/functions.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,13 +230,13 @@ fn col(name: &str) -> PyResult<PyExpr> {
230230
/// Create a CASE WHEN statement with literal WHEN expressions for comparison to the base expression.
231231
#[pyfunction]
232232
fn case(expr: PyExpr) -> PyResult<PyCaseBuilder> {
233-
Ok(datafusion::logical_expr::case(expr.expr).into())
233+
Ok(PyCaseBuilder::new(Some(expr)))
234234
}
235235

236236
/// Create a CASE WHEN statement with literal WHEN expressions for comparison to the base expression.
237237
#[pyfunction]
238238
fn when(when: PyExpr, then: PyExpr) -> PyResult<PyCaseBuilder> {
239-
Ok(datafusion::logical_expr::when(when.expr, then.expr).into())
239+
Ok(PyCaseBuilder::new(None).when(when, then))
240240
}
241241

242242
/// Helper function to find the appropriate window function.

0 commit comments

Comments
 (0)