This is an automated email from the ASF dual-hosted git repository.

alamb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion.git


The following commit(s) were added to refs/heads/main by this push:
     new f39b467d10 implement nested identifier access (#12614)
f39b467d10 is described below

commit f39b467d10efa9fd356207ed707b5d3fd3196e82
Author: Lordworms <[email protected]>
AuthorDate: Fri Sep 27 16:17:03 2024 -0700

    implement nested identifier access (#12614)
    
    * adding struct_extract function
    
    * changing logics
    
    * Revert "adding struct_extract function"
    
    This reverts commit 00a12bc03ea924dec14f48f29b6b4f77bc735e67.
    
    * fix clippy
    
    * optimize
---
 datafusion/functions/src/core/planner.rs      | 27 ++++----
 datafusion/sql/src/expr/identifier.rs         | 15 +----
 datafusion/sqllogictest/test_files/struct.slt | 91 +++++++++++++++++++++++++++
 3 files changed, 108 insertions(+), 25 deletions(-)

diff --git a/datafusion/functions/src/core/planner.rs 
b/datafusion/functions/src/core/planner.rs
index 889f191d59..12fcb4a263 100644
--- a/datafusion/functions/src/core/planner.rs
+++ b/datafusion/functions/src/core/planner.rs
@@ -17,7 +17,7 @@
 
 use arrow::datatypes::Field;
 use datafusion_common::Result;
-use datafusion_common::{not_impl_err, Column, DFSchema, ScalarValue, 
TableReference};
+use datafusion_common::{Column, DFSchema, ScalarValue, TableReference};
 use datafusion_expr::expr::ScalarFunction;
 use datafusion_expr::planner::{ExprPlanner, PlannerResult, RawDictionaryExpr};
 use datafusion_expr::{lit, Expr};
@@ -70,19 +70,20 @@ impl ExprPlanner for CoreFunctionPlanner {
         qualifier: Option<&TableReference>,
         nested_names: &[String],
     ) -> Result<PlannerResult<Vec<Expr>>> {
-        // TODO: remove when can support multiple nested identifiers
-        if nested_names.len() > 1 {
-            return not_impl_err!(
-                "Nested identifiers not yet supported for column {}",
-                Column::from((qualifier, field)).quoted_flat_name()
-            );
+        let col = Expr::Column(Column::from((qualifier, field)));
+
+        // Start with the base column expression
+        let mut expr = col;
+
+        // Iterate over nested_names and create nested get_field expressions
+        for nested_name in nested_names {
+            let get_field_args = vec![expr, 
lit(ScalarValue::from(nested_name.clone()))];
+            expr = Expr::ScalarFunction(ScalarFunction::new_udf(
+                crate::core::get_field(),
+                get_field_args,
+            ));
         }
-        let nested_name = nested_names[0].to_string();
 
-        let col = Expr::Column(Column::from((qualifier, field)));
-        let get_field_args = vec![col, lit(ScalarValue::from(nested_name))];
-        Ok(PlannerResult::Planned(Expr::ScalarFunction(
-            ScalarFunction::new_udf(crate::core::get_field(), get_field_args),
-        )))
+        Ok(PlannerResult::Planned(expr))
     }
 }
diff --git a/datafusion/sql/src/expr/identifier.rs 
b/datafusion/sql/src/expr/identifier.rs
index 36776c6902..b2c8312709 100644
--- a/datafusion/sql/src/expr/identifier.rs
+++ b/datafusion/sql/src/expr/identifier.rs
@@ -19,8 +19,8 @@ use arrow_schema::Field;
 use sqlparser::ast::{Expr as SQLExpr, Ident};
 
 use datafusion_common::{
-    internal_err, not_impl_err, plan_datafusion_err, Column, DFSchema, 
DataFusionError,
-    Result, TableReference,
+    internal_err, not_impl_err, plan_datafusion_err, plan_err, Column, 
DFSchema,
+    DataFusionError, Result, TableReference,
 };
 use datafusion_expr::planner::PlannerResult;
 use datafusion_expr::{Case, Expr};
@@ -113,13 +113,6 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
                 .map(|id| self.ident_normalizer.normalize(id))
                 .collect::<Vec<_>>();
 
-            // Currently not supporting more than one nested level
-            // Though ideally once that support is in place, this code should 
work with it
-            // TODO: remove when can support multiple nested identifiers
-            if ids.len() > 5 {
-                return not_impl_err!("Compound identifier: {ids:?}");
-            }
-
             let search_result = search_dfschema(&ids, schema);
             match search_result {
                 // found matching field with spare identifier(s) for nested 
field(s) in structure
@@ -142,9 +135,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
                             }
                         }
                     }
-                    not_impl_err!(
-                        "Compound identifiers not supported by ExprPlanner: 
{ids:?}"
-                    )
+                    plan_err!("could not parse compound identifier from 
{ids:?}")
                 }
                 // found matching field with no spare identifier(s)
                 Some((field, qualifier, _nested_names)) => {
diff --git a/datafusion/sqllogictest/test_files/struct.slt 
b/datafusion/sqllogictest/test_files/struct.slt
index f3ac6549ad..d2e7160d00 100644
--- a/datafusion/sqllogictest/test_files/struct.slt
+++ b/datafusion/sqllogictest/test_files/struct.slt
@@ -282,3 +282,94 @@ drop table values;
 
 statement ok
 drop table struct_values;
+
+statement ok
+CREATE OR REPLACE VIEW complex_view AS 
+SELECT {
+    'user': {
+        'info': {
+            'personal': {
+                'name': 'John Doe',
+                'age': 30,
+                'email': '[email protected]'
+            },
+            'address': {
+                'street': '123 Main St',
+                'city': 'Anytown',
+                'country': 'Countryland',
+                'coordinates': [40.7128, -74.0060]
+            }
+        },
+        'preferences': {
+            'theme': 'dark',
+            'notifications': true,
+            'languages': ['en', 'es', 'fr']
+        },
+        'stats': {
+            'logins': 42,
+            'last_active': '2023-09-15',
+            'scores': [85, 92, 78, 95],
+            'achievements': {
+                'badges': ['early_bird', 'top_contributor'],
+                'levels': {
+                    'beginner': true,
+                    'intermediate': true,
+                    'advanced': false
+                }
+            }
+        }
+    },
+    'metadata': {
+        'version': '1.0',
+        'created_at': '2023-09-01T12:00:00Z'
+    },
+    'deep_nested': {
+        'level1': {
+            'level2': {
+                'level3': {
+                    'level4': {
+                        'level5': {
+                            'level6': {
+                                'level7': {
+                                    'level8': {
+                                        'level9': {
+                                            'level10': 'You reached the 
bottom!'
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+} AS complex_data;
+
+query T
+SELECT complex_data.user.info.personal.name FROM complex_view;
+----
+John Doe
+
+query I
+SELECT complex_data.user.info.personal.age FROM complex_view;
+----
+30
+
+query T
+SELECT complex_data.user.info.address.city FROM complex_view;
+----
+Anytown
+
+query T
+SELECT complex_data.user.preferences.languages[2] FROM complex_view;
+----
+es
+
+query T
+SELECT 
complex_data.deep_nested.level1.level2.level3.level4.level5.level6.level7.level8.level9.level10
 FROM complex_view;
+----
+You reached the bottom!
+
+statement ok
+drop view complex_view;


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to