From 74b1fdb0f89b7388bea8d232b824b70f5d00e526 Mon Sep 17 00:00:00 2001 From: Jeremy Dyer Date: Wed, 22 Feb 2023 18:11:03 -0500 Subject: [PATCH 1/3] Bindings for LIKE type expressions --- datafusion/__init__.py | 6 + datafusion/tests/test_imports.py | 6 + src/expr.rs | 8 +- src/expr/like.rs | 196 +++++++++++++++++++++++++++++++ 4 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 src/expr/like.rs diff --git a/datafusion/__init__.py b/datafusion/__init__.py index 46206f06..2d39d8df 100644 --- a/datafusion/__init__.py +++ b/datafusion/__init__.py @@ -45,7 +45,10 @@ Expr, Filter, Limit, + Like, + ILike, Projection, + SimilarTo, Sort, TableScan, ) @@ -71,6 +74,9 @@ "Sort", "Limit", "Filter", + "Like", + "ILike", + "SimilarTo", ] diff --git a/datafusion/tests/test_imports.py b/datafusion/tests/test_imports.py index 7eb8b7cf..074f9d7f 100644 --- a/datafusion/tests/test_imports.py +++ b/datafusion/tests/test_imports.py @@ -44,6 +44,9 @@ Aggregate, Sort, Analyze, + Like, + ILike, + SimilarTo, ) @@ -77,6 +80,9 @@ def test_class_module_is_datafusion(): Limit, Filter, Analyze, + Like, + ILike, + SimilarTo, ]: assert klass.__module__ == "datafusion.expr" diff --git a/src/expr.rs b/src/expr.rs index 90ce6bf0..6e2364d5 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -29,12 +29,15 @@ use crate::expr::column::PyColumn; use crate::expr::literal::PyLiteral; use datafusion::scalar::ScalarValue; +use self::like::{PyILike, PyLike, PySimilarTo}; + pub mod aggregate; pub mod aggregate_expr; pub mod analyze; pub mod binary_expr; pub mod column; pub mod filter; +pub mod like; pub mod limit; pub mod literal; pub mod logical_node; @@ -45,7 +48,7 @@ pub mod table_scan; /// A PyExpr that can be used on a DataFrame #[pyclass(name = "Expr", module = "datafusion.expr", subclass)] #[derive(Debug, Clone)] -pub(crate) struct PyExpr { +pub struct PyExpr { pub(crate) expr: Expr, } @@ -177,6 +180,9 @@ pub(crate) fn init_module(m: &PyModule) -> PyResult<()> { m.add_class::()?; m.add_class::()?; m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; // operators m.add_class::()?; m.add_class::()?; diff --git a/src/expr/like.rs b/src/expr/like.rs new file mode 100644 index 00000000..6ed3c246 --- /dev/null +++ b/src/expr/like.rs @@ -0,0 +1,196 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +use datafusion_expr::expr::Like; +use pyo3::prelude::*; +use std::fmt::{self, Display, Formatter}; + +use crate::expr::PyExpr; + +#[pyclass(name = "Like", module = "datafusion.expr", subclass)] +#[derive(Clone)] +pub struct PyLike { + like: Like, +} + +impl From for PyLike { + fn from(like: Like) -> PyLike { + PyLike { like } + } +} + +impl From for Like { + fn from(like: PyLike) -> Self { + like.like + } +} + +impl Display for PyLike { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!( + f, + "Like + Negated: {:?} + Expr: {:?} + Pattern: {:?} + Escape_Char: {:?}", + &self.negated(), + &self.expr(), + &self.pattern(), + &self.escape_char() + ) + } +} + +#[pymethods] +impl PyLike { + fn negated(&self) -> PyResult { + Ok(self.like.negated) + } + + fn expr(&self) -> PyResult { + Ok((*self.like.expr).clone().into()) + } + + fn pattern(&self) -> PyResult { + Ok((*self.like.pattern).clone().into()) + } + + fn escape_char(&self) -> PyResult> { + Ok(self.like.escape_char) + } + + fn __repr__(&self) -> String { + format!("Like({})", self) + } +} + +#[pyclass(name = "ILike", module = "datafusion.expr", subclass)] +#[derive(Clone)] +pub struct PyILike { + like: Like, +} + +impl From for PyILike { + fn from(like: Like) -> PyILike { + PyILike { like } + } +} + +impl From for Like { + fn from(like: PyILike) -> Self { + like.like + } +} + +impl Display for PyILike { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!( + f, + "ILike + Negated: {:?} + Expr: {:?} + Pattern: {:?} + Escape_Char: {:?}", + &self.negated(), + &self.expr(), + &self.pattern(), + &self.escape_char() + ) + } +} + +#[pymethods] +impl PyILike { + fn negated(&self) -> PyResult { + Ok(self.like.negated) + } + + fn expr(&self) -> PyResult { + Ok((*self.like.expr).clone().into()) + } + + fn pattern(&self) -> PyResult { + Ok((*self.like.pattern).clone().into()) + } + + fn escape_char(&self) -> PyResult> { + Ok(self.like.escape_char) + } + + fn __repr__(&self) -> String { + format!("Like({})", self) + } +} + +#[pyclass(name = "SimilarTo", module = "datafusion.expr", subclass)] +#[derive(Clone)] +pub struct PySimilarTo { + like: Like, +} + +impl From for PySimilarTo { + fn from(like: Like) -> PySimilarTo { + PySimilarTo { like } + } +} + +impl From for Like { + fn from(like: PySimilarTo) -> Self { + like.like + } +} + +impl Display for PySimilarTo { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!( + f, + "SimilarTo + Negated: {:?} + Expr: {:?} + Pattern: {:?} + Escape_Char: {:?}", + &self.negated(), + &self.expr(), + &self.pattern(), + &self.escape_char() + ) + } +} + +#[pymethods] +impl PySimilarTo { + fn negated(&self) -> PyResult { + Ok(self.like.negated) + } + + fn expr(&self) -> PyResult { + Ok((*self.like.expr).clone().into()) + } + + fn pattern(&self) -> PyResult { + Ok((*self.like.pattern).clone().into()) + } + + fn escape_char(&self) -> PyResult> { + Ok(self.like.escape_char) + } + + fn __repr__(&self) -> String { + format!("Like({})", self) + } +} From 0dfaff16ba0f383b32f56298134fb051c0d57877 Mon Sep 17 00:00:00 2001 From: Jeremy Dyer Date: Wed, 22 Feb 2023 19:09:17 -0500 Subject: [PATCH 2/3] cargo fmt --- src/expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/expr.rs b/src/expr.rs index 913f38b8..5e7604e4 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -29,8 +29,8 @@ use crate::expr::column::PyColumn; use crate::expr::literal::PyLiteral; use datafusion::scalar::ScalarValue; -use self::like::{PyILike, PyLike, PySimilarTo}; use self::alias::PyAlias; +use self::like::{PyILike, PyLike, PySimilarTo}; pub mod aggregate; pub mod aggregate_expr; From 07b42c85eb0b4fb6d4721297059f75543d626c4f Mon Sep 17 00:00:00 2001 From: Jeremy Dyer Date: Wed, 22 Feb 2023 20:35:51 -0500 Subject: [PATCH 3/3] remove conflict expression --- src/expr.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/expr.rs b/src/expr.rs index 0a371bd2..cdc81e7a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -30,11 +30,8 @@ use crate::expr::literal::PyLiteral; use datafusion::scalar::ScalarValue; use self::alias::PyAlias; -<<<<<<< HEAD use self::like::{PyILike, PyLike, PySimilarTo}; -======= use self::scalar_variable::PyScalarVariable; ->>>>>>> upstream/main pub mod aggregate; pub mod aggregate_expr;