Skip to content

Commit 6ae2007

Browse files
re-implement PyExpr::column_name
The previous implementation relied on `DFField` which was removed upstream. Ref: apache/datafusion#9595
1 parent cc0b4b2 commit 6ae2007

File tree

1 file changed

+37
-2
lines changed

1 file changed

+37
-2
lines changed

src/expr.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18+
use datafusion_expr::utils::exprlist_to_fields;
19+
use datafusion_expr::LogicalPlan;
1820
use pyo3::{basic::CompareOp, prelude::*};
1921
use std::convert::{From, Into};
22+
use std::sync::Arc;
2023

21-
use datafusion::arrow::datatypes::DataType;
24+
use datafusion::arrow::datatypes::{DataType, Field};
2225
use datafusion::arrow::pyarrow::PyArrowType;
2326
use datafusion::scalar::ScalarValue;
2427
use datafusion_expr::{
@@ -29,11 +32,12 @@ use datafusion_expr::{
2932
};
3033

3134
use crate::common::data_type::{DataTypeMap, RexType};
32-
use crate::errors::{py_datafusion_err, py_runtime_err, py_type_err};
35+
use crate::errors::{py_datafusion_err, py_runtime_err, py_type_err, DataFusionError};
3336
use crate::expr::aggregate_expr::PyAggregateFunction;
3437
use crate::expr::binary_expr::PyBinaryExpr;
3538
use crate::expr::column::PyColumn;
3639
use crate::expr::literal::PyLiteral;
40+
use crate::sql::logical::PyLogicalPlan;
3741

3842
use self::alias::PyAlias;
3943
use self::bool_expr::{
@@ -553,9 +557,40 @@ impl PyExpr {
553557
}
554558
})
555559
}
560+
561+
pub fn column_name(&self, plan: PyLogicalPlan) -> PyResult<String> {
562+
self._column_name(&plan.plan()).map_err(py_runtime_err)
563+
}
556564
}
557565

558566
impl PyExpr {
567+
pub fn _column_name(&self, plan: &LogicalPlan) -> Result<String, DataFusionError> {
568+
let field = Self::expr_to_field(&self.expr, plan)?;
569+
Ok(field.name().to_owned())
570+
}
571+
572+
/// Create a [Field] representing an [Expr], given an input [LogicalPlan] to resolve against
573+
pub fn expr_to_field(
574+
expr: &Expr,
575+
input_plan: &LogicalPlan,
576+
) -> Result<Arc<Field>, DataFusionError> {
577+
match expr {
578+
Expr::Sort(Sort { expr, .. }) => {
579+
// DataFusion does not support create_name for sort expressions (since they never
580+
// appear in projections) so we just delegate to the contained expression instead
581+
Self::expr_to_field(expr, input_plan)
582+
}
583+
Expr::Wildcard { .. } => {
584+
// Since * could be any of the valid column names just return the first one
585+
Ok(Arc::new(input_plan.schema().field(0).clone()))
586+
}
587+
_ => {
588+
let fields =
589+
exprlist_to_fields(&[expr.clone()], input_plan).map_err(PyErr::from)?;
590+
Ok(fields[0].1.clone())
591+
}
592+
}
593+
}
559594
fn _types(expr: &Expr) -> PyResult<DataTypeMap> {
560595
match expr {
561596
Expr::BinaryExpr(BinaryExpr {

0 commit comments

Comments
 (0)