Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions datafusion/functions-nested/src/expr_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use crate::extract::{array_element, array_slice};
/// # use datafusion_expr::{lit, col, Expr};
/// # use datafusion_functions_nested::expr_ext::IndexAccessor;
/// let expr = col("c1").index(lit(3));
/// assert_eq!(expr.schema_name().to_string(), "c1[Int32(3)]");
/// assert!(expr.schema_name().to_string().starts_with("c1["));
/// ```
pub trait IndexAccessor {
fn index(self, key: Expr) -> Expr;
Expand Down Expand Up @@ -66,7 +66,7 @@ impl IndexAccessor for Expr {
/// # use datafusion_expr::{lit, col};
/// # use datafusion_functions_nested::expr_ext::SliceAccessor;
/// let expr = col("c1").range(lit(2), lit(4));
/// assert_eq!(expr.schema_name().to_string(), "c1[Int32(2):Int32(4)]");
/// assert!(expr.schema_name().to_string().starts_with("c1["));
/// ```
pub trait SliceAccessor {
fn range(self, start: Expr, stop: Expr) -> Expr;
Expand Down
26 changes: 16 additions & 10 deletions datafusion/functions-nested/src/extract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@

//! [`ScalarUDFImpl`] definitions for array_element, array_slice, array_pop_front, array_pop_back, and array_any_value functions.

// Allow deprecated items within this module since we're providing backwards compatibility
#![allow(deprecated)]

use arrow::array::{
Array, ArrayRef, Capacities, GenericListArray, GenericListViewArray, Int64Array,
MutableArrayData, NullArray, NullBufferBuilder, OffsetSizeTrait,
Expand Down Expand Up @@ -44,20 +47,22 @@ use datafusion_expr::{
use datafusion_expr::{
ColumnarValue, Documentation, ScalarUDFImpl, Signature, Volatility,
};
use datafusion_functions::core::get_field as get_field_udf;
use datafusion_macros::user_doc;
use std::any::Any;
use std::sync::Arc;

use crate::utils::make_scalar_function;

// Create static instances of ScalarUDFs for each function
make_udf_expr_and_func!(
ArrayElement,
array_element,
array element,
"extracts the element with the index n from the array.",
array_element_udf
);
pub fn array_element(array: Expr, element: Expr) -> Expr {
Expr::ScalarFunction(datafusion_expr::expr::ScalarFunction::new_udf(
get_field_udf(),
vec![array, element],
))
}

create_func!(ArrayElement, array_element_udf);

create_func!(ArraySlice, array_slice_udf);

Expand Down Expand Up @@ -87,7 +92,7 @@ make_udf_expr_and_func!(

#[user_doc(
doc_section(label = "Array Functions"),
description = "Extracts the element with the index n from the array.",
description = "Extracts the element with the index n from the array. Note: `get_field` now handles array element access and is preferred for mixed struct/array access patterns.",
syntax_example = "array_element(array, index)",
sql_example = r#"```sql
> select array_element([1, 2, 3, 4], 3);
Expand All @@ -107,6 +112,7 @@ make_udf_expr_and_func!(
)
)]
#[derive(Debug, PartialEq, Eq, Hash)]
#[deprecated(since = "52.0.0", note = "Use get_field instead")]
pub struct ArrayElement {
signature: Signature,
aliases: Vec<String>,
Expand Down Expand Up @@ -283,7 +289,6 @@ where
Ok(arrow::array::make_array(data))
}

#[doc = "returns a slice of the array."]
pub fn array_slice(array: Expr, begin: Expr, end: Expr, stride: Option<Expr>) -> Expr {
let args = match stride {
Some(stride) => vec![array, begin, end, stride],
Expand All @@ -294,7 +299,7 @@ pub fn array_slice(array: Expr, begin: Expr, end: Expr, stride: Option<Expr>) ->

#[user_doc(
doc_section(label = "Array Functions"),
description = "Returns a slice of the array based on 1-indexed start and end positions.",
description = "Returns a slice of the array based on 1-indexed start and end positions. Note: `get_field` now handles array slice access and is preferred for mixed struct/array access patterns.",
syntax_example = "array_slice(array, begin, end)",
sql_example = r#"```sql
> select array_slice([1, 2, 3, 4, 5, 6, 7, 8], 3, 6);
Expand Down Expand Up @@ -322,6 +327,7 @@ pub fn array_slice(array: Expr, begin: Expr, end: Expr, stride: Option<Expr>) ->
)
)]
#[derive(Debug, PartialEq, Eq, Hash)]
#[deprecated(since = "52.0.0", note = "Use get_field_slice instead")]
pub(super) struct ArraySlice {
signature: Signature,
aliases: Vec<String>,
Expand Down
24 changes: 9 additions & 15 deletions datafusion/functions-nested/src/planner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

//! SQL planning extensions like [`NestedFunctionPlanner`] and [`FieldAccessPlanner`]

use arrow::datatypes::DataType;
use datafusion_common::{DFSchema, Result, plan_err, utils::list_ndims};
use datafusion_expr::AggregateUDF;
use datafusion_expr::expr::ScalarFunction;
Expand All @@ -35,11 +34,11 @@ use datafusion_functions::expr_fn::get_field;
use datafusion_functions_aggregate::nth_value::nth_value_udaf;
use std::sync::Arc;

use crate::extract::array_slice;
use crate::map::map_udf;
use crate::{
array_has::{array_has_all, array_has_udf},
expr_fn::{array_append, array_concat, array_prepend},
extract::{array_element, array_slice},
make_array::make_array,
};

Expand Down Expand Up @@ -142,7 +141,7 @@ impl ExprPlanner for FieldAccessPlanner {
fn plan_field_access(
&self,
expr: RawFieldAccessExpr,
schema: &DFSchema,
_schema: &DFSchema,
) -> Result<PlannerResult<RawFieldAccessExpr>> {
let RawFieldAccessExpr { expr, field_access } = expr;

Expand All @@ -154,7 +153,8 @@ impl ExprPlanner for FieldAccessPlanner {
GetFieldAccess::NamedStructField { name } => {
Ok(PlannerResult::Planned(get_field(expr, name)))
}
// expr[idx] ==> array_element(expr, idx)
// expr[idx] ==> get_field(expr, idx)
// Unified field access: get_field handles both struct fields and array indices
GetFieldAccess::ListIndex { key: index } => {
match expr {
// Special case for array_agg(expr)[index] to NTH_VALUE(expr, index)
Expand All @@ -178,19 +178,13 @@ impl ExprPlanner for FieldAccessPlanner {
null_treatment,
)),
)),
// special case for map access with
_ if matches!(expr.get_type(schema)?, DataType::Map(_, _)) => {
Ok(PlannerResult::Planned(Expr::ScalarFunction(
ScalarFunction::new_udf(
get_field_inner(),
vec![expr, *index],
),
)))
}
_ => Ok(PlannerResult::Planned(array_element(expr, *index))),
// All other cases (arrays, maps, etc.) use get_field
_ => Ok(PlannerResult::Planned(Expr::ScalarFunction(
ScalarFunction::new_udf(get_field_inner(), vec![expr, *index]),
))),
}
}
// expr[start, stop, stride] ==> array_slice(expr, start, stop, stride)
// expr[start:stop:stride] ==> array_slice(expr, start, stop, stride)
GetFieldAccess::ListRange {
start,
stop,
Expand Down
Loading
Loading