From f06ad3c972752713641ec1fee1e6cd4da2db0d64 Mon Sep 17 00:00:00 2001 From: Andrew Lamb Date: Mon, 30 Jan 2023 16:20:38 -0500 Subject: [PATCH] Add support --- .../expr/src/type_coercion/functions.rs | 11 +++++-- datafusion/optimizer/src/type_coercion.rs | 31 ++++++++++++++++--- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/datafusion/expr/src/type_coercion/functions.rs b/datafusion/expr/src/type_coercion/functions.rs index f58050eb9415d..d95596413b83d 100644 --- a/datafusion/expr/src/type_coercion/functions.rs +++ b/datafusion/expr/src/type_coercion/functions.rs @@ -22,8 +22,10 @@ use arrow::{ }; use datafusion_common::{DataFusionError, Result}; -/// Performs type coercion for functions Returns the data types that -/// each argument must be coerced to match `signature`. +/// Performs type coercion for function arguments. +/// +/// Returns the data types to which each argument must be coerced to +/// match `signature`. /// /// For more details on coercion in general, please see the /// [`type_coercion`](crate::type_coercion) module. @@ -175,7 +177,10 @@ pub fn can_coerce_from(type_into: &DataType, type_from: &DataType) -> bool { | Decimal128(_, _) ), Timestamp(TimeUnit::Nanosecond, None) => { - matches!(type_from, Null | Timestamp(_, None)) + matches!(type_from, Null | Timestamp(_, None) | Utf8 | LargeUtf8) + } + Interval(_) => { + matches!(type_from, Utf8 | LargeUtf8) } Utf8 | LargeUtf8 => true, Null => can_cast_types(type_from, type_into), diff --git a/datafusion/optimizer/src/type_coercion.rs b/datafusion/optimizer/src/type_coercion.rs index e335c9ff5f851..5a73559532a8f 100644 --- a/datafusion/optimizer/src/type_coercion.rs +++ b/datafusion/optimizer/src/type_coercion.rs @@ -42,6 +42,7 @@ use datafusion_expr::{ WindowFrame, WindowFrameBound, WindowFrameUnits, }; use datafusion_expr::{ExprSchemable, Signature}; +use log::debug; use crate::utils::rewrite_preserving_name; use crate::{OptimizerConfig, OptimizerRule}; @@ -550,13 +551,35 @@ fn coerce_arguments_for_signature( let new_types = data_types(¤t_types, signature)?; - expressions - .iter() + debug!("AAL current types: {current_types:?}"); + debug!("AAL new types: {new_types:?}"); + + + let exprs = expressions + .into_iter() .enumerate() - .map(|(i, expr)| expr.clone().cast_to(&new_types[i], schema)) - .collect::>>() + .map(|(i, expr)| cast_expr(expr, &new_types[i], schema)) + .collect::>>(); + + debug!("AAL new exprs: {new_types:?}"); + + exprs } +/// Cast expr to the specified type, if possible +fn cast_expr(expr: &Expr, to_type: &DataType, schema: &DFSchema) -> Result { + // Special case until Interval coercion is handled in arrow-rs + match (expr, to_type) { + (Expr::Literal(ScalarValue::Utf8(Some(s))), DataType::Interval(_)) => { + parse_interval("millisecond", s.as_str()).map(Expr::Literal) + }, + _ => expr.clone().cast_to(to_type, schema), + } +} + + + + /// Returns the coerced exprs for each `input_exprs`. /// Get the coerced data type from `aggregate_rule::coerce_types` and add `try_cast` if the /// data type of `input_exprs` need to be coerced.