Skip to content

Commit

Permalink
Support to unparse ScalarValue::IntervalMonthDayNano to String (#10956
Browse files Browse the repository at this point in the history
)

* support to unparse ScalarValue::IntervalMonthDayNano to String

* use array formatter to format the interval string
  • Loading branch information
goldmedal committed Jun 18, 2024
1 parent 500b73f commit 41a7882
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 5 deletions.
8 changes: 7 additions & 1 deletion datafusion/expr/src/expr_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ use crate::{
Signature, Volatility,
};
use crate::{AggregateUDFImpl, ColumnarValue, ScalarUDFImpl, WindowUDF, WindowUDFImpl};
use arrow::compute::kernels::cast_utils::parse_interval_month_day_nano;
use arrow::datatypes::{DataType, Field};
use datafusion_common::{Column, Result};
use datafusion_common::{Column, Result, ScalarValue};
use std::any::Any;
use std::fmt::Debug;
use std::ops::Not;
Expand Down Expand Up @@ -670,6 +671,11 @@ impl WindowUDFImpl for SimpleWindowUDF {
}
}

pub fn interval_month_day_nano_lit(value: &str) -> Expr {
let interval = parse_interval_month_day_nano(value).ok();
Expr::Literal(ScalarValue::IntervalMonthDayNano(interval))
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
49 changes: 45 additions & 4 deletions datafusion/sql/src/unparser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@
// specific language governing permissions and limitations
// under the License.

use arrow::util::display::array_value_to_string;
use core::fmt;
use std::{fmt::Display, vec};

use arrow_array::{Date32Array, Date64Array};
use arrow_schema::DataType;
use sqlparser::ast::Value::SingleQuotedString;
use sqlparser::ast::{
self, Expr as AstExpr, Function, FunctionArg, Ident, UnaryOperator,
self, Expr as AstExpr, Function, FunctionArg, Ident, Interval, UnaryOperator,
};

use datafusion_common::{
Expand Down Expand Up @@ -834,7 +836,22 @@ impl Unparser<'_> {
}
ScalarValue::IntervalDayTime(None) => Ok(ast::Expr::Value(ast::Value::Null)),
ScalarValue::IntervalMonthDayNano(Some(_i)) => {
not_impl_err!("Unsupported scalar: {v:?}")
let wrap_array = v.to_array()?;
let Some(result) = array_value_to_string(&wrap_array, 0).ok() else {
return internal_err!(
"Unable to convert IntervalMonthDayNano to string"
);
};
let interval = Interval {
value: Box::new(ast::Expr::Value(SingleQuotedString(
result.to_uppercase(),
))),
leading_field: None,
leading_precision: None,
last_field: None,
fractional_seconds_precision: None,
};
Ok(ast::Expr::Interval(interval))
}
ScalarValue::IntervalMonthDayNano(None) => {
Ok(ast::Expr::Value(ast::Value::Null))
Expand Down Expand Up @@ -962,19 +979,19 @@ impl Unparser<'_> {

#[cfg(test)]
mod tests {
use std::ops::{Add, Sub};
use std::{any::Any, sync::Arc, vec};

use arrow::datatypes::{Field, Schema};
use arrow_schema::DataType::Int8;

use datafusion_common::TableReference;
use datafusion_expr::AggregateExt;
use datafusion_expr::{
case, col, cube, exists, grouping_set, lit, not, not_exists, out_ref_col,
placeholder, rollup, table_scan, try_cast, when, wildcard, ColumnarValue,
ScalarUDF, ScalarUDFImpl, Signature, Volatility, WindowFrame,
WindowFunctionDefinition,
};
use datafusion_expr::{interval_month_day_nano_lit, AggregateExt};
use datafusion_functions_aggregate::count::count_udaf;
use datafusion_functions_aggregate::expr_fn::sum;

Expand Down Expand Up @@ -1264,6 +1281,30 @@ mod tests {
),
(col("need-quoted").eq(lit(1)), r#"("need-quoted" = 1)"#),
(col("need quoted").eq(lit(1)), r#"("need quoted" = 1)"#),
(
interval_month_day_nano_lit(
"1 YEAR 1 MONTH 1 DAY 3 HOUR 10 MINUTE 20 SECOND",
),
r#"INTERVAL '0 YEARS 13 MONS 1 DAYS 3 HOURS 10 MINS 20.000000000 SECS'"#,
),
(
interval_month_day_nano_lit("1.5 MONTH"),
r#"INTERVAL '0 YEARS 1 MONS 15 DAYS 0 HOURS 0 MINS 0.000000000 SECS'"#,
),
(
interval_month_day_nano_lit("-3 MONTH"),
r#"INTERVAL '0 YEARS -3 MONS 0 DAYS 0 HOURS 0 MINS 0.000000000 SECS'"#,
),
(
interval_month_day_nano_lit("1 MONTH")
.add(interval_month_day_nano_lit("1 DAY")),
r#"(INTERVAL '0 YEARS 1 MONS 0 DAYS 0 HOURS 0 MINS 0.000000000 SECS' + INTERVAL '0 YEARS 0 MONS 1 DAYS 0 HOURS 0 MINS 0.000000000 SECS')"#,
),
(
interval_month_day_nano_lit("1 MONTH")
.sub(interval_month_day_nano_lit("1 DAY")),
r#"(INTERVAL '0 YEARS 1 MONS 0 DAYS 0 HOURS 0 MINS 0.000000000 SECS' - INTERVAL '0 YEARS 0 MONS 1 DAYS 0 HOURS 0 MINS 0.000000000 SECS')"#,
),
];

for (expr, expected) in tests {
Expand Down

0 comments on commit 41a7882

Please sign in to comment.