This is an automated email from the ASF dual-hosted git repository.
dheres pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow-datafusion.git
The following commit(s) were added to refs/heads/master by this push:
new 231027274 feat: Support simple Arrays with Literals (#2194)
231027274 is described below
commit 231027274b13e92fbbfb6011f149fec414d55ab8
Author: Dmitry Patsura <[email protected]>
AuthorDate: Wed Apr 13 13:17:36 2022 +0300
feat: Support simple Arrays with Literals (#2194)
* feat: Support simple Arrays (literals only)
* Update datafusion/core/src/sql/planner.rs
Co-authored-by: Andrew Lamb <[email protected]>
Co-authored-by: Andrew Lamb <[email protected]>
---
datafusion/core/src/sql/planner.rs | 72 +++++++++++++++++++++++++++++++++++++-
datafusion/core/tests/sql/expr.rs | 19 ++++++++++
2 files changed, 90 insertions(+), 1 deletion(-)
diff --git a/datafusion/core/src/sql/planner.rs
b/datafusion/core/src/sql/planner.rs
index 84ddace9a..12bae6ba0 100644
--- a/datafusion/core/src/sql/planner.rs
+++ b/datafusion/core/src/sql/planner.rs
@@ -49,6 +49,7 @@ use crate::{
};
use arrow::datatypes::*;
use hashbrown::HashMap;
+
use sqlparser::ast::{
BinaryOperator, DataType as SQLDataType, DateTimeField, Expr as SQLExpr,
FunctionArg,
FunctionArgExpr, Ident, Join, JoinConstraint, JoinOperator, ObjectName,
Query,
@@ -1437,6 +1438,8 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
fractional_seconds_precision,
),
+ SQLExpr::Array(arr) => self.sql_array_literal(arr.elem, schema),
+
SQLExpr::Identifier(id) => {
if id.value.starts_with('@') {
// TODO: figure out if ScalarVariables should be
insensitive.
@@ -2117,6 +2120,51 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
.get_table_provider(tables_reference)
.is_some()
}
+
+ fn sql_array_literal(
+ &self,
+ elements: Vec<SQLExpr>,
+ schema: &DFSchema,
+ ) -> Result<Expr> {
+ let mut values = Vec::with_capacity(elements.len());
+
+ for element in elements {
+ let value = self.sql_expr_to_logical_expr(element, schema)?;
+ match value {
+ Expr::Literal(scalar) => {
+ values.push(scalar);
+ }
+ _ => {
+ return Err(DataFusionError::NotImplemented(format!(
+ "Arrays with elements other than literal are not
supported: {}",
+ value
+ )));
+ }
+ }
+ }
+
+ let data_types: HashSet<DataType> =
+ values.iter().map(|e| e.get_datatype()).collect();
+
+ if data_types.is_empty() {
+ Ok(Expr::Literal(ScalarValue::List(
+ None,
+ Box::new(DataType::Utf8),
+ )))
+ } else if data_types.len() > 1 {
+ Err(DataFusionError::NotImplemented(format!(
+ "Arrays with different types are not supported: {:?}",
+ data_types,
+ )))
+ } else {
+ let data_type = values[0].get_datatype();
+
+ Ok(Expr::Literal(ScalarValue::List(
+ Some(Box::new(values)),
+ Box::new(data_type),
+ )))
+ }
+ }
}
/// Remove join expressions from a filter expression
@@ -2260,7 +2308,7 @@ fn parse_sql_number(n: &str) -> Result<Expr> {
mod tests {
use crate::datasource::empty::EmptyTable;
use crate::physical_plan::functions::Volatility;
- use crate::{logical_plan::create_udf, sql::parser::DFParser};
+ use crate::{assert_contains, logical_plan::create_udf,
sql::parser::DFParser};
use datafusion_expr::ScalarFunctionImplementation;
use super::*;
@@ -2968,6 +3016,28 @@ mod tests {
);
}
+ #[test]
+ fn select_array_no_common_type() {
+ let sql = "SELECT [1, true, null]";
+ let err = logical_plan(sql).expect_err("query should have failed");
+
+ // HashSet doesn't guarantee order
+ assert_contains!(
+ err.to_string(),
+ r#"Arrays with different types are not supported: "#
+ );
+ }
+
+ #[test]
+ fn select_array_non_literal_type() {
+ let sql = "SELECT [now()]";
+ let err = logical_plan(sql).expect_err("query should have failed");
+ assert_eq!(
+ r#"NotImplemented("Arrays with elements other than literal are not
supported: now()")"#,
+ format!("{:?}", err)
+ );
+ }
+
#[test]
fn
select_simple_aggregate_with_groupby_and_column_is_in_aggregate_and_groupby() {
quick_test(
diff --git a/datafusion/core/tests/sql/expr.rs
b/datafusion/core/tests/sql/expr.rs
index 565af3203..de71764ba 100644
--- a/datafusion/core/tests/sql/expr.rs
+++ b/datafusion/core/tests/sql/expr.rs
@@ -457,6 +457,25 @@ async fn test_crypto_expressions() -> Result<()> {
Ok(())
}
+#[tokio::test]
+async fn test_array_literals() -> Result<()> {
+ // Named, just another syntax
+ test_expression!("ARRAY[1,2,3,4,5]", "[1, 2, 3, 4, 5]");
+ // Unnamed variant
+ test_expression!("[1,2,3,4,5]", "[1, 2, 3, 4, 5]");
+ test_expression!("[true, false]", "[true, false]");
+ test_expression!("['str1', 'str2']", "[str1, str2]");
+ test_expression!("[[1,2], [3,4]]", "[[1, 2], [3, 4]]");
+
+ // TODO: Not supported in parser, uncomment when it will be available
+ // test_expression!(
+ // "[]",
+ // "[]"
+ // );
+
+ Ok(())
+}
+
#[tokio::test]
async fn test_interval_expressions() -> Result<()> {
// day nano intervals