1use arrow::array::{Array, ArrayRef, ArrowPrimitiveType, AsArray, PrimitiveArray};
19use arrow::compute::try_binary;
20use arrow::datatypes::{DataType, DecimalType};
21use arrow::error::ArrowError;
22use datafusion_common::{DataFusionError, Result, ScalarValue};
23use datafusion_expr::ColumnarValue;
24use datafusion_expr::function::Hint;
25use std::sync::Arc;
26
27macro_rules! get_optimal_return_type {
37 ($FUNC:ident, $largeUtf8Type:expr, $utf8Type:expr) => {
38 pub(crate) fn $FUNC(arg_type: &DataType, name: &str) -> Result<DataType> {
39 Ok(match arg_type {
40 DataType::LargeUtf8 | DataType::LargeBinary => $largeUtf8Type,
42 DataType::Utf8 | DataType::Binary => $utf8Type,
44 DataType::Utf8View | DataType::BinaryView => $utf8Type,
46 DataType::Null => DataType::Null,
47 DataType::Dictionary(_, value_type) => match **value_type {
48 DataType::LargeUtf8 | DataType::LargeBinary => $largeUtf8Type,
49 DataType::Utf8 | DataType::Binary => $utf8Type,
50 DataType::Null => DataType::Null,
51 _ => {
52 return datafusion_common::exec_err!(
53 "The {} function can only accept strings, but got {:?}.",
54 name.to_uppercase(),
55 **value_type
56 );
57 }
58 },
59 data_type => {
60 return datafusion_common::exec_err!(
61 "The {} function can only accept strings, but got {:?}.",
62 name.to_uppercase(),
63 data_type
64 );
65 }
66 })
67 }
68 };
69}
70
71get_optimal_return_type!(utf8_to_str_type, DataType::LargeUtf8, DataType::Utf8);
73
74get_optimal_return_type!(utf8_to_int_type, DataType::Int64, DataType::Int32);
76
77pub(crate) fn transform_leaf_type_preserving_encoding<F>(
82 arg_type: &DataType,
83 transform: &F,
84) -> Result<DataType>
85where
86 F: Fn(&DataType) -> Result<DataType>,
87{
88 match arg_type {
89 DataType::Dictionary(key_type, value_type) => Ok(DataType::Dictionary(
90 key_type.clone(),
91 Box::new(transform_leaf_type_preserving_encoding(
92 value_type, transform,
93 )?),
94 )),
95 _ => transform(arg_type),
96 }
97}
98
99pub fn make_scalar_function<F>(
103 inner: F,
104 hints: Vec<Hint>,
105) -> impl Fn(&[ColumnarValue]) -> Result<ColumnarValue>
106where
107 F: Fn(&[ArrayRef]) -> Result<ArrayRef>,
108{
109 move |args: &[ColumnarValue]| {
110 let len = args
113 .iter()
114 .fold(Option::<usize>::None, |acc, arg| match arg {
115 ColumnarValue::Scalar(_) => acc,
116 ColumnarValue::Array(a) => Some(a.len()),
117 });
118
119 let is_scalar = len.is_none();
120
121 let inferred_length = len.unwrap_or(1);
122 let args = args
123 .iter()
124 .zip(hints.iter().chain(std::iter::repeat(&Hint::Pad)))
125 .map(|(arg, hint)| {
126 let expansion_len = match hint {
129 Hint::AcceptsSingular => 1,
130 Hint::Pad => inferred_length,
131 };
132 arg.to_array(expansion_len)
133 })
134 .collect::<Result<Vec<_>>>()?;
135
136 let result = (inner)(&args);
137 if is_scalar {
138 let result = result.and_then(|arr| ScalarValue::try_from_array(&arr, 0));
140 result.map(ColumnarValue::Scalar)
141 } else {
142 result.map(ColumnarValue::Array)
143 }
144 }
145}
146
147pub fn calculate_binary_math<L, R, O, F>(
154 left: &dyn Array,
155 right: &ColumnarValue,
156 fun: F,
157) -> Result<Arc<PrimitiveArray<O>>>
158where
159 L: ArrowPrimitiveType,
160 R: ArrowPrimitiveType,
161 O: ArrowPrimitiveType,
162 F: Fn(L::Native, R::Native) -> Result<O::Native, ArrowError>,
163 R::Native: TryFrom<ScalarValue>,
164{
165 calculate_binary_math_cast::<L, R, O, F>(left, right, fun, &R::DATA_TYPE)
166}
167
168#[deprecated(
176 since = "55.0.0",
177 note = "Use `calculate_binary_decimal_math_cast` instead"
178)]
179pub fn calculate_binary_decimal_math<L, R, O, F>(
180 left: &dyn Array,
181 right: &ColumnarValue,
182 fun: F,
183 precision: u8,
184 scale: i8,
185) -> Result<Arc<PrimitiveArray<O>>>
186where
187 L: DecimalType,
188 R: ArrowPrimitiveType,
189 O: DecimalType,
190 F: Fn(L::Native, R::Native) -> Result<O::Native, ArrowError>,
191 R::Native: TryFrom<ScalarValue>,
192{
193 calculate_binary_decimal_math_cast::<L, R, O, F>(
194 left,
195 right,
196 fun,
197 precision,
198 scale,
199 &R::DATA_TYPE,
200 )
201}
202
203fn calculate_binary_math_cast<L, R, O, F>(
219 left: &dyn Array,
220 right: &ColumnarValue,
221 fun: F,
222 cast_target: &DataType,
223) -> Result<Arc<PrimitiveArray<O>>>
224where
225 L: ArrowPrimitiveType,
226 R: ArrowPrimitiveType,
227 O: ArrowPrimitiveType,
228 F: Fn(L::Native, R::Native) -> Result<O::Native, ArrowError>,
229 R::Native: TryFrom<ScalarValue>,
230{
231 let left = left.as_primitive::<L>();
232 let right = right.cast_to(cast_target, None)?;
233 let result = match right {
234 ColumnarValue::Scalar(scalar) => {
235 if scalar.is_null() {
236 PrimitiveArray::<O>::new_null(left.len())
239 } else {
240 let right = R::Native::try_from(scalar.clone()).map_err(|_| {
241 DataFusionError::NotImplemented(format!(
242 "Cannot convert scalar value {scalar} to {cast_target}"
243 ))
244 })?;
245 left.try_unary::<_, O, _>(|lvalue| fun(lvalue, right))?
246 }
247 }
248 ColumnarValue::Array(right) => {
249 let right = right.as_primitive::<R>();
250 try_binary::<_, _, _, O>(left, right, &fun)?
251 }
252 };
253 Ok(Arc::new(result) as _)
254}
255
256pub fn calculate_binary_decimal_math_cast<L, R, O, F>(
275 left: &dyn Array,
276 right: &ColumnarValue,
277 fun: F,
278 precision: u8,
279 scale: i8,
280 cast_target: &DataType,
281) -> Result<Arc<PrimitiveArray<O>>>
282where
283 L: DecimalType,
284 R: ArrowPrimitiveType,
285 O: DecimalType,
286 F: Fn(L::Native, R::Native) -> Result<O::Native, ArrowError>,
287 R::Native: TryFrom<ScalarValue>,
288{
289 let result_array =
290 calculate_binary_math_cast::<L, R, O, F>(left, right, fun, cast_target)?;
291 Ok(Arc::new(
292 result_array
293 .as_ref()
294 .clone()
295 .with_precision_and_scale(precision, scale)?,
296 ))
297}
298
299pub fn decimal128_to_i128(value: i128, scale: i8) -> Result<i128, ArrowError> {
301 if scale < 0 {
302 Err(ArrowError::ComputeError(
303 "Negative scale is not supported".into(),
304 ))
305 } else if scale == 0 {
306 Ok(value)
307 } else {
308 match i128::from(10).checked_pow(scale as u32) {
309 Some(divisor) => Ok(value / divisor),
310 None => Err(ArrowError::ComputeError(format!(
311 "Cannot get a power of {scale}"
312 ))),
313 }
314 }
315}
316
317pub fn decimal32_to_i32(value: i32, scale: i8) -> Result<i32, ArrowError> {
318 if scale < 0 {
319 Err(ArrowError::ComputeError(
320 "Negative scale is not supported".into(),
321 ))
322 } else if scale == 0 {
323 Ok(value)
324 } else {
325 match 10_i32.checked_pow(scale as u32) {
326 Some(divisor) => Ok(value / divisor),
327 None => Err(ArrowError::ComputeError(format!(
328 "Cannot get a power of {scale}"
329 ))),
330 }
331 }
332}
333
334pub fn decimal64_to_i64(value: i64, scale: i8) -> Result<i64, ArrowError> {
335 if scale < 0 {
336 Err(ArrowError::ComputeError(
337 "Negative scale is not supported".into(),
338 ))
339 } else if scale == 0 {
340 Ok(value)
341 } else {
342 match i64::from(10).checked_pow(scale as u32) {
343 Some(divisor) => Ok(value / divisor),
344 None => Err(ArrowError::ComputeError(format!(
345 "Cannot get a power of {scale}"
346 ))),
347 }
348 }
349}
350
351#[cfg(test)]
352pub mod test {
353 macro_rules! test_function {
361 ($FUNC:expr, $ARGS:expr, $EXPECTED:expr, $EXPECTED_TYPE:ty, $EXPECTED_DATA_TYPE:expr, $ARRAY_TYPE:ident, $CONFIG_OPTIONS:expr) => {
362 let expected: Result<Option<$EXPECTED_TYPE>> = $EXPECTED;
363 let func = $FUNC;
364
365 let data_array = $ARGS.iter().map(|arg| arg.data_type()).collect::<Vec<_>>();
366 let cardinality = $ARGS
367 .iter()
368 .fold(Option::<usize>::None, |acc, arg| match arg {
369 ColumnarValue::Scalar(_) => acc,
370 ColumnarValue::Array(a) => Some(a.len()),
371 })
372 .unwrap_or(1);
373
374 let scalar_arguments = $ARGS.iter().map(|arg| match arg {
375 ColumnarValue::Scalar(scalar) => Some(scalar.clone()),
376 ColumnarValue::Array(_) => None,
377 }).collect::<Vec<_>>();
378 let scalar_arguments_refs = scalar_arguments.iter().map(|arg| arg.as_ref()).collect::<Vec<_>>();
379
380 let nullables = $ARGS.iter().map(|arg| match arg {
381 ColumnarValue::Scalar(scalar) => scalar.is_null(),
382 ColumnarValue::Array(a) => a.null_count() > 0,
383 }).collect::<Vec<_>>();
384
385 let field_array = data_array.into_iter().zip(nullables).enumerate()
386 .map(|(idx, (data_type, nullable))| arrow::datatypes::Field::new(format!("field_{idx}"), data_type, nullable))
387 .map(std::sync::Arc::new)
388 .collect::<Vec<_>>();
389
390 let return_field = func.return_field_from_args(datafusion_expr::ReturnFieldArgs {
391 arg_fields: &field_array,
392 scalar_arguments: &scalar_arguments_refs,
393 });
394 let arg_fields = $ARGS.iter()
395 .enumerate()
396 .map(|(idx, arg)| arrow::datatypes::Field::new(format!("f_{idx}"), arg.data_type(), true).into())
397 .collect::<Vec<_>>();
398
399 match expected {
400 Ok(expected) => {
401 assert_eq!(return_field.is_ok(), true);
402 let return_field = return_field.unwrap();
403 let return_type = return_field.data_type();
404 assert_eq!(return_type, &$EXPECTED_DATA_TYPE);
405
406 let result = func.invoke_with_args(datafusion_expr::ScalarFunctionArgs{
407 args: $ARGS,
408 arg_fields,
409 number_rows: cardinality,
410 return_field,
411 config_options: $CONFIG_OPTIONS
412 });
413 assert_eq!(result.is_ok(), true, "function returned an error: {}", result.unwrap_err());
414
415 let result = result.unwrap().to_array(cardinality).expect("Failed to convert to array");
416 let result = result.as_any().downcast_ref::<$ARRAY_TYPE>().expect("Failed to convert to type");
417 assert_eq!(result.data_type(), &$EXPECTED_DATA_TYPE);
418
419 match expected {
421 Some(v) => assert_eq!(result.value(0), v),
422 None => assert!(result.is_null(0)),
423 };
424 }
425 Err(expected_error) => {
426 if let Ok(return_field) = return_field {
427 match func.invoke_with_args(datafusion_expr::ScalarFunctionArgs {
429 args: $ARGS,
430 arg_fields,
431 number_rows: cardinality,
432 return_field,
433 config_options: $CONFIG_OPTIONS,
434 }) {
435 Ok(_) => assert!(false, "expected error"),
436 Err(error) => {
437 assert!(expected_error
438 .strip_backtrace()
439 .starts_with(&error.strip_backtrace()));
440 }
441 }
442 } else if let Err(error) = return_field {
443 datafusion_common::assert_contains!(
444 expected_error.strip_backtrace(),
445 error.strip_backtrace()
446 );
447 }
448 }
449 };
450 };
451
452 ($FUNC:expr, $ARGS:expr, $EXPECTED:expr, $EXPECTED_TYPE:ty, $EXPECTED_DATA_TYPE:expr, $ARRAY_TYPE:ident) => {
453 test_function!(
454 $FUNC,
455 $ARGS,
456 $EXPECTED,
457 $EXPECTED_TYPE,
458 $EXPECTED_DATA_TYPE,
459 $ARRAY_TYPE,
460 std::sync::Arc::new(datafusion_common::config::ConfigOptions::default())
461 )
462 };
463 }
464
465 use arrow::{
466 array::Int32Array,
467 datatypes::{DataType, Int32Type},
468 };
469 use itertools::Either;
470 pub(crate) use test_function;
471
472 use super::*;
473
474 #[test]
475 fn test_calculate_binary_math_scalar_null() {
476 let left = Int32Array::from(vec![1, 2]);
477 let right = ColumnarValue::Scalar(ScalarValue::Int32(None));
478 let result = calculate_binary_math::<Int32Type, Int32Type, Int32Type, _>(
479 &left,
480 &right,
481 |x, y| Ok(x + y),
482 )
483 .unwrap();
484
485 assert_eq!(result.len(), 2);
486 assert_eq!(result.null_count(), 2);
487 }
488
489 #[test]
490 fn string_to_int_type() {
491 let v = utf8_to_int_type(&DataType::Utf8, "test").unwrap();
492 assert_eq!(v, DataType::Int32);
493
494 let v = utf8_to_int_type(&DataType::Utf8View, "test").unwrap();
495 assert_eq!(v, DataType::Int32);
496
497 let v = utf8_to_int_type(&DataType::LargeUtf8, "test").unwrap();
498 assert_eq!(v, DataType::Int64);
499 }
500
501 #[test]
502 fn test_decimal128_to_i128() {
503 let cases = [
504 (123, 0, Some(123)),
505 (1230, 1, Some(123)),
506 (123000, 3, Some(123)),
507 (1, 0, Some(1)),
508 (123, -3, None),
509 (123, i8::MAX, None),
510 (i128::MAX, 0, Some(i128::MAX)),
511 (i128::MAX, 3, Some(i128::MAX / 1000)),
512 ];
513
514 for (value, scale, expected) in cases {
515 match decimal128_to_i128(value, scale) {
516 Ok(actual) => {
517 assert_eq!(
518 actual,
519 expected.expect("Got value but expected none"),
520 "{value} and {scale} vs {expected:?}"
521 );
522 }
523 Err(_) => assert!(expected.is_none()),
524 }
525 }
526 }
527
528 #[test]
529 fn test_decimal32_to_i32() {
530 let cases: [(i32, i8, Either<i32, String>); _] = [
531 (123, 0, Either::Left(123)),
532 (1230, 1, Either::Left(123)),
533 (123000, 3, Either::Left(123)),
534 (1234567, 2, Either::Left(12345)),
535 (-1234567, 2, Either::Left(-12345)),
536 (1, 0, Either::Left(1)),
537 (
538 123,
539 -3,
540 Either::Right("Negative scale is not supported".into()),
541 ),
542 (
543 123,
544 i8::MAX,
545 Either::Right("Cannot get a power of 127".into()),
546 ),
547 (999999999, 0, Either::Left(999999999)),
548 (999999999, 3, Either::Left(999999)),
549 ];
550
551 for (value, scale, expected) in cases {
552 match decimal32_to_i32(value, scale) {
553 Ok(actual) => {
554 let expected_value =
555 expected.left().expect("Got value but expected none");
556 assert_eq!(
557 actual, expected_value,
558 "{value} and {scale} vs {expected_value:?}"
559 );
560 }
561 Err(ArrowError::ComputeError(msg)) => {
562 assert_eq!(
563 msg,
564 expected.right().expect("Got error but expected value")
565 );
566 }
567 Err(_) => {
568 assert!(expected.is_right())
569 }
570 }
571 }
572 }
573
574 #[test]
575 fn test_decimal64_to_i64() {
576 let cases: [(i64, i8, Either<i64, String>); _] = [
577 (123, 0, Either::Left(123)),
578 (1234567890, 2, Either::Left(12345678)),
579 (-1234567890, 2, Either::Left(-12345678)),
580 (
581 123,
582 -3,
583 Either::Right("Negative scale is not supported".into()),
584 ),
585 (
586 123,
587 i8::MAX,
588 Either::Right("Cannot get a power of 127".into()),
589 ),
590 (
591 999999999999999999i64,
592 0,
593 Either::Left(999999999999999999i64),
594 ),
595 (
596 999999999999999999i64,
597 3,
598 Either::Left(999999999999999999i64 / 1000),
599 ),
600 (
601 -999999999999999999i64,
602 3,
603 Either::Left(-999999999999999999i64 / 1000),
604 ),
605 ];
606
607 for (value, scale, expected) in cases {
608 match decimal64_to_i64(value, scale) {
609 Ok(actual) => {
610 let expected_value =
611 expected.left().expect("Got value but expected none");
612 assert_eq!(
613 actual, expected_value,
614 "{value} and {scale} vs {expected_value:?}"
615 );
616 }
617 Err(ArrowError::ComputeError(msg)) => {
618 assert_eq!(
619 msg,
620 expected.right().expect("Got error but expected value")
621 );
622 }
623 Err(_) => {
624 assert!(expected.is_right())
625 }
626 }
627 }
628 }
629}