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 e7d9504fd9 Unparse struct to sql (#13493)
e7d9504fd9 is described below
commit e7d9504fd9d12cc8242b0b5d4b92c3fad4fb0e97
Author: delamarch3 <[email protected]>
AuthorDate: Thu Nov 21 14:02:33 2024 +0000
Unparse struct to sql (#13493)
* unparse struct to sql
* add roundtrip statement test for named_struct
* quote keys if needed
* add roundtrip statement test for get_field
* improve error messages
* fmt
* fmt
* match string literals only
Co-authored-by: Jax Liu <[email protected]>
---------
Co-authored-by: Jax Liu <[email protected]>
---
datafusion/sql/src/unparser/expr.rs | 61 ++++++++++++++++++++++++++++++-
datafusion/sql/tests/cases/plan_to_sql.rs | 4 +-
2 files changed, 63 insertions(+), 2 deletions(-)
diff --git a/datafusion/sql/src/unparser/expr.rs
b/datafusion/sql/src/unparser/expr.rs
index f1f28258f9..ae2607de00 100644
--- a/datafusion/sql/src/unparser/expr.rs
+++ b/datafusion/sql/src/unparser/expr.rs
@@ -462,7 +462,9 @@ impl Unparser<'_> {
match func_name {
"make_array" => self.make_array_to_sql(args),
"array_element" => self.array_element_to_sql(args),
- // TODO: support for the construct and access functions of the
`map` and `struct` types
+ "named_struct" => self.named_struct_to_sql(args),
+ "get_field" => self.get_field_to_sql(args),
+ // TODO: support for the construct and access functions of the
`map` type
_ => self.scalar_function_to_sql_internal(func_name, args),
}
}
@@ -514,6 +516,57 @@ impl Unparser<'_> {
})
}
+ fn named_struct_to_sql(&self, args: &[Expr]) -> Result<ast::Expr> {
+ if args.len() % 2 != 0 {
+ return internal_err!("named_struct must have an even number of
arguments");
+ }
+
+ let args = args
+ .chunks_exact(2)
+ .map(|chunk| {
+ let key = match &chunk[0] {
+ Expr::Literal(ScalarValue::Utf8(Some(s))) =>
self.new_ident_quoted_if_needs(s.to_string()),
+ _ => return internal_err!("named_struct expects even
arguments to be strings, but received: {:?}", &chunk[0])
+ };
+
+ Ok(ast::DictionaryField {
+ key,
+ value: Box::new(self.expr_to_sql(&chunk[1])?),
+ })
+ })
+ .collect::<Result<Vec<_>>>()?;
+
+ Ok(ast::Expr::Dictionary(args))
+ }
+
+ fn get_field_to_sql(&self, args: &[Expr]) -> Result<ast::Expr> {
+ if args.len() != 2 {
+ return internal_err!("get_field must have exactly 2 arguments");
+ }
+
+ let mut id = match &args[0] {
+ Expr::Column(col) => match self.col_to_sql(col)? {
+ ast::Expr::Identifier(ident) => vec![ident],
+ ast::Expr::CompoundIdentifier(idents) => idents,
+ other => return internal_err!("expected col_to_sql to return
an Identifier or CompoundIdentifier, but received: {:?}", other),
+ },
+ _ => return internal_err!("get_field expects first argument to be
column, but received: {:?}", &args[0]),
+ };
+
+ let field = match &args[1] {
+ Expr::Literal(lit) =>
self.new_ident_quoted_if_needs(lit.to_string()),
+ _ => {
+ return internal_err!(
+ "get_field expects second argument to be a string, but
received: {:?}",
+ &args[0]
+ )
+ }
+ };
+ id.push(field);
+
+ Ok(ast::Expr::CompoundIdentifier(id))
+ }
+
pub fn sort_to_sql(&self, sort: &Sort) -> Result<ast::OrderByExpr> {
let Sort {
expr,
@@ -1524,6 +1577,7 @@ mod tests {
Signature, Volatility, WindowFrame, WindowFunctionDefinition,
};
use datafusion_expr::{interval_month_day_nano_lit, ExprFunctionExt};
+ use datafusion_functions::expr_fn::{get_field, named_struct};
use datafusion_functions_aggregate::count::count_udaf;
use datafusion_functions_aggregate::expr_fn::sum;
use datafusion_functions_nested::expr_fn::{array_element, make_array};
@@ -1937,6 +1991,11 @@ mod tests {
array_element(make_array(vec![lit(1), lit(2), lit(3)]),
lit(1)),
"[1, 2, 3][1]",
),
+ (
+ named_struct(vec![lit("a"), lit("1"), lit("b"), lit(2)]),
+ "{a: '1', b: 2}",
+ ),
+ (get_field(col("a.b"), "c"), "a.b.c"),
];
for (expr, expected) in tests {
diff --git a/datafusion/sql/tests/cases/plan_to_sql.rs
b/datafusion/sql/tests/cases/plan_to_sql.rs
index f9d97cdc74..58d99549de 100644
--- a/datafusion/sql/tests/cases/plan_to_sql.rs
+++ b/datafusion/sql/tests/cases/plan_to_sql.rs
@@ -188,7 +188,9 @@ fn roundtrip_statement() -> Result<()> {
"SELECT ARRAY[1, 2, 3][1]",
"SELECT [1, 2, 3]",
"SELECT [1, 2, 3][1]",
- "SELECT left[1] FROM array"
+ "SELECT left[1] FROM array",
+ "SELECT {a:1, b:2}",
+ "SELECT s.a FROM (SELECT {a:1, b:2} AS s)"
];
// For each test sql string, we transform as follows:
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]