Skip to content
Draft
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
33 changes: 30 additions & 3 deletions datafusion/sql/src/expr/identifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
use arrow::datatypes::FieldRef;
use datafusion_common::datatype::DataTypeExt;
use datafusion_common::{
Column, DFSchema, Result, Span, TableReference, assert_or_internal_err,
Column, DFSchema, Result, ScalarValue, Span, TableReference, assert_or_internal_err,
exec_datafusion_err, internal_err, not_impl_err, plan_datafusion_err, plan_err,
};
use datafusion_expr::expr::LambdaVariable;
use datafusion_expr::planner::PlannerResult;
use datafusion_expr::{Case, Expr};
use datafusion_expr::planner::{PlannerResult, RawFieldAccessExpr};
use datafusion_expr::{Case, Expr, GetFieldAccess};
use sqlparser::ast::{CaseWhen, Expr as SQLExpr, Ident};
use std::sync::Arc;

Expand Down Expand Up @@ -144,6 +144,33 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
})?;
Ok(Expr::ScalarVariable(field, var_names))
} else {
let root_name = self.ident_normalizer.normalize(ids[0].clone());
if planner_context.lambda_parameters().contains_key(&root_name) {
let mut expr =
self.sql_identifier_to_expr(ids[0].clone(), schema, planner_context)?;
'fields: for id in ids.into_iter().skip(1) {
let field_access = GetFieldAccess::NamedStructField {
name: ScalarValue::from(self.ident_normalizer.normalize(id)),
};
let mut field_access_expr = RawFieldAccessExpr { expr, field_access };
for planner in self.context_provider.get_expr_planners() {
match planner.plan_field_access(field_access_expr, schema)? {
PlannerResult::Planned(planned) => {
expr = planned;
continue 'fields;
}
PlannerResult::Original(original) => {
field_access_expr = original;
}
}
}
return not_impl_err!(
"GetFieldAccess not supported by ExprPlanner: {field_access_expr:?}"
);
}
return Ok(expr);
}

let ids = ids
.into_iter()
.map(|id| self.ident_normalizer.normalize(id))
Expand Down
27 changes: 27 additions & 0 deletions datafusion/sqllogictest/test_files/array/array_transform.slt
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,33 @@ SELECT array_transform([[10, 20]], v -> v[1]);
----
[10]

# dotted field access on a struct-valued lambda parameter
query ?
SELECT array_transform(
make_array(named_struct('rule_number', 1, 'rule_action', 'allow')),
e -> e.rule_action
);
----
[allow]

# dotted field access followed by a list subscript
query ?
SELECT array_transform(
make_array(named_struct('items', make_array(10, 20))),
e -> e.items[1]
);
----
[10]

# chained dotted field access on nested structs
query ?
SELECT array_transform(
make_array(named_struct('metadata', named_struct('rule_action', 'deny'))),
e -> e.metadata.rule_action
);
----
[deny]


# expr simplifier inside lambda body
query TT
Expand Down
Loading