1use std::any::Any;
21use std::sync::Arc;
22
23use super::power::PowerFunc;
24
25use crate::utils::{calculate_binary_math, decimal128_to_i128};
26use arrow::array::{Array, ArrayRef};
27use arrow::datatypes::{
28 DataType, Decimal128Type, Decimal256Type, Float32Type, Float64Type, Int32Type,
29 Int64Type, DECIMAL128_MAX_PRECISION, DECIMAL256_MAX_PRECISION,
30};
31use arrow::error::ArrowError;
32use arrow_buffer::i256;
33use datafusion_common::{
34 exec_err, internal_err, plan_datafusion_err, plan_err, Result, ScalarValue,
35};
36use datafusion_expr::expr::ScalarFunction;
37use datafusion_expr::simplify::{ExprSimplifyResult, SimplifyInfo};
38use datafusion_expr::sort_properties::{ExprProperties, SortProperties};
39use datafusion_expr::{
40 lit, ColumnarValue, Documentation, Expr, ScalarFunctionArgs, ScalarUDF,
41 TypeSignature::*,
42};
43use datafusion_expr::{ScalarUDFImpl, Signature, Volatility};
44use datafusion_macros::user_doc;
45
46#[user_doc(
47 doc_section(label = "Math Functions"),
48 description = "Returns the base-x logarithm of a number. Can either provide a specified base, or if omitted then takes the base-10 of a number.",
49 syntax_example = r#"log(base, numeric_expression)
50log(numeric_expression)"#,
51 sql_example = r#"```sql
52> SELECT log(10);
53+---------+
54| log(10) |
55+---------+
56| 1.0 |
57+---------+
58```"#,
59 standard_argument(name = "base", prefix = "Base numeric"),
60 standard_argument(name = "numeric_expression", prefix = "Numeric")
61)]
62#[derive(Debug, PartialEq, Eq, Hash)]
63pub struct LogFunc {
64 signature: Signature,
65}
66
67impl Default for LogFunc {
68 fn default() -> Self {
69 Self::new()
70 }
71}
72
73impl LogFunc {
74 pub fn new() -> Self {
75 Self {
76 signature: Signature::one_of(
77 vec![
78 Numeric(1),
79 Numeric(2),
80 Exact(vec![DataType::Float32, DataType::Float32]),
81 Exact(vec![DataType::Float64, DataType::Float64]),
82 Exact(vec![
83 DataType::Int64,
84 DataType::Decimal128(DECIMAL128_MAX_PRECISION, 0),
85 ]),
86 Exact(vec![
87 DataType::Float32,
88 DataType::Decimal128(DECIMAL128_MAX_PRECISION, 0),
89 ]),
90 Exact(vec![
91 DataType::Float64,
92 DataType::Decimal128(DECIMAL128_MAX_PRECISION, 0),
93 ]),
94 Exact(vec![
95 DataType::Int64,
96 DataType::Decimal256(DECIMAL256_MAX_PRECISION, 0),
97 ]),
98 Exact(vec![
99 DataType::Float32,
100 DataType::Decimal256(DECIMAL256_MAX_PRECISION, 0),
101 ]),
102 Exact(vec![
103 DataType::Float64,
104 DataType::Decimal256(DECIMAL256_MAX_PRECISION, 0),
105 ]),
106 ],
107 Volatility::Immutable,
108 ),
109 }
110 }
111}
112
113fn log_decimal128(value: i128, scale: i8, base: f64) -> Result<f64, ArrowError> {
116 if !base.is_finite() || base.trunc() != base {
117 return Err(ArrowError::ComputeError(format!(
118 "Log cannot use non-integer base: {base}"
119 )));
120 }
121 if (base as u32) < 2 {
122 return Err(ArrowError::ComputeError(format!(
123 "Log base must be greater than 1: {base}"
124 )));
125 }
126
127 let unscaled_value = decimal128_to_i128(value, scale)?;
128 if unscaled_value > 0 {
129 let log_value: u32 = unscaled_value.ilog(base as i128);
130 Ok(log_value as f64)
131 } else {
132 Ok(f64::NAN)
134 }
135}
136
137fn log_decimal256(value: i256, scale: i8, base: f64) -> Result<f64, ArrowError> {
140 match value.to_i128() {
141 Some(value) => log_decimal128(value, scale, base),
142 None => Err(ArrowError::NotYetImplemented(format!(
143 "Log of Decimal256 larger than Decimal128 is not yet supported: {value}"
144 ))),
145 }
146}
147
148impl ScalarUDFImpl for LogFunc {
149 fn as_any(&self) -> &dyn Any {
150 self
151 }
152 fn name(&self) -> &str {
153 "log"
154 }
155
156 fn signature(&self) -> &Signature {
157 &self.signature
158 }
159
160 fn return_type(&self, arg_types: &[DataType]) -> Result<DataType> {
161 match &arg_types.last().ok_or(plan_datafusion_err!("No args"))? {
163 DataType::Float32 => Ok(DataType::Float32),
164 _ => Ok(DataType::Float64),
165 }
166 }
167
168 fn output_ordering(&self, input: &[ExprProperties]) -> Result<SortProperties> {
169 let (base_sort_properties, num_sort_properties) = if input.len() == 1 {
170 (SortProperties::Singleton, input[0].sort_properties)
172 } else {
173 (input[0].sort_properties, input[1].sort_properties)
174 };
175 match (num_sort_properties, base_sort_properties) {
176 (first @ SortProperties::Ordered(num), SortProperties::Ordered(base))
177 if num.descending != base.descending
178 && num.nulls_first == base.nulls_first =>
179 {
180 Ok(first)
181 }
182 (
183 first @ (SortProperties::Ordered(_) | SortProperties::Singleton),
184 SortProperties::Singleton,
185 ) => Ok(first),
186 (SortProperties::Singleton, second @ SortProperties::Ordered(_)) => {
187 Ok(-second)
188 }
189 _ => Ok(SortProperties::Unordered),
190 }
191 }
192
193 fn invoke_with_args(&self, args: ScalarFunctionArgs) -> Result<ColumnarValue> {
195 let args = ColumnarValue::values_to_arrays(&args.args)?;
196
197 let (base, value) = if args.len() == 2 {
198 (ColumnarValue::Array(Arc::clone(&args[0])), &args[1])
200 } else {
201 let ret_type = if args[0].data_type().is_null() {
203 &DataType::Float64
204 } else {
205 args[0].data_type()
206 };
207 (
208 ColumnarValue::Array(
209 ScalarValue::new_ten(ret_type)?.to_array_of_size(args[0].len())?,
210 ),
211 &args[0],
212 )
213 };
214
215 let arr: ArrayRef = match value.data_type() {
219 DataType::Float32 => calculate_binary_math::<
220 Float32Type,
221 Float32Type,
222 Float32Type,
223 _,
224 >(value, &base, |x, b| Ok(f32::log(x, b)))?,
225 DataType::Float64 => calculate_binary_math::<
226 Float64Type,
227 Float64Type,
228 Float64Type,
229 _,
230 >(value, &base, |x, b| Ok(f64::log(x, b)))?,
231 DataType::Int32 => {
232 calculate_binary_math::<Int32Type, Float64Type, Float64Type, _>(
233 value,
234 &base,
235 |x, b| Ok(f64::log(x as f64, b)),
236 )?
237 }
238 DataType::Int64 => {
239 calculate_binary_math::<Int64Type, Float64Type, Float64Type, _>(
240 value,
241 &base,
242 |x, b| Ok(f64::log(x as f64, b)),
243 )?
244 }
245 DataType::Decimal128(_precision, scale) => {
246 calculate_binary_math::<Decimal128Type, Float64Type, Float64Type, _>(
247 value,
248 &base,
249 |x, b| log_decimal128(x, *scale, b),
250 )?
251 }
252 DataType::Decimal256(_precision, scale) => {
253 calculate_binary_math::<Decimal256Type, Float64Type, Float64Type, _>(
254 value,
255 &base,
256 |x, b| log_decimal256(x, *scale, b),
257 )?
258 }
259 other => {
260 return exec_err!("Unsupported data type {other:?} for function log")
261 }
262 };
263
264 Ok(ColumnarValue::Array(arr))
265 }
266
267 fn documentation(&self) -> Option<&Documentation> {
268 self.doc()
269 }
270
271 fn simplify(
276 &self,
277 mut args: Vec<Expr>,
278 info: &dyn SimplifyInfo,
279 ) -> Result<ExprSimplifyResult> {
280 let num_args = args.len();
284 if num_args > 2 {
285 return plan_err!("Expected log to have 1 or 2 arguments, got {num_args}");
286 }
287 let number = args.pop().ok_or_else(|| {
288 plan_datafusion_err!("Expected log to have 1 or 2 arguments, got 0")
289 })?;
290 let number_datatype = info.get_data_type(&number)?;
291 let base = if let Some(base) = args.pop() {
293 base
294 } else {
295 lit(ScalarValue::new_ten(&number_datatype)?)
296 };
297
298 match number {
299 Expr::Literal(value, _)
300 if value == ScalarValue::new_one(&number_datatype)? =>
301 {
302 Ok(ExprSimplifyResult::Simplified(lit(ScalarValue::new_zero(
303 &info.get_data_type(&base)?,
304 )?)))
305 }
306 Expr::ScalarFunction(ScalarFunction { func, mut args })
307 if is_pow(&func) && args.len() == 2 && base == args[0] =>
308 {
309 let b = args.pop().unwrap(); Ok(ExprSimplifyResult::Simplified(b))
311 }
312 number => {
313 if number == base {
314 Ok(ExprSimplifyResult::Simplified(lit(ScalarValue::new_one(
315 &number_datatype,
316 )?)))
317 } else {
318 let args = match num_args {
319 1 => vec![number],
320 2 => vec![base, number],
321 _ => {
322 return internal_err!(
323 "Unexpected number of arguments in log::simplify"
324 )
325 }
326 };
327 Ok(ExprSimplifyResult::Original(args))
328 }
329 }
330 }
331 }
332}
333
334fn is_pow(func: &ScalarUDF) -> bool {
336 func.inner().as_any().downcast_ref::<PowerFunc>().is_some()
337}
338
339#[cfg(test)]
340mod tests {
341 use std::collections::HashMap;
342
343 use super::*;
344
345 use arrow::array::{
346 Date32Array, Decimal128Array, Decimal256Array, Float32Array, Float64Array,
347 };
348 use arrow::compute::SortOptions;
349 use arrow::datatypes::{Field, DECIMAL256_MAX_PRECISION};
350 use datafusion_common::cast::{as_float32_array, as_float64_array};
351 use datafusion_common::config::ConfigOptions;
352 use datafusion_common::DFSchema;
353 use datafusion_expr::execution_props::ExecutionProps;
354 use datafusion_expr::simplify::SimplifyContext;
355
356 #[test]
357 fn test_log_invalid_base_type() {
358 let arg_fields = vec![
359 Field::new("b", DataType::Date32, false).into(),
360 Field::new("n", DataType::Float64, false).into(),
361 ];
362 let args = ScalarFunctionArgs {
363 args: vec![
364 ColumnarValue::Array(Arc::new(Date32Array::from(vec![5, 10, 15, 20]))), ColumnarValue::Array(Arc::new(Float64Array::from(vec![
366 10.0, 100.0, 1000.0, 10000.0,
367 ]))), ],
369 arg_fields,
370 number_rows: 4,
371 return_field: Field::new("f", DataType::Float64, true).into(),
372 config_options: Arc::new(ConfigOptions::default()),
373 lambdas: None,
374 };
375 let result = LogFunc::new().invoke_with_args(args);
376 assert!(result.is_err());
377 assert_eq!(
378 result.unwrap_err().to_string().lines().next().unwrap(),
379 "Arrow error: Cast error: Casting from Date32 to Float64 not supported"
380 );
381 }
382
383 #[test]
384 fn test_log_invalid_value() {
385 let arg_field = Field::new("a", DataType::Date32, false).into();
386 let args = ScalarFunctionArgs {
387 args: vec![
388 ColumnarValue::Array(Arc::new(Date32Array::from(vec![10]))), ],
390 arg_fields: vec![arg_field],
391 number_rows: 1,
392 return_field: Field::new("f", DataType::Float64, true).into(),
393 config_options: Arc::new(ConfigOptions::default()),
394 lambdas: None,
395 };
396
397 let result = LogFunc::new().invoke_with_args(args);
398 result.expect_err("expected error");
399 }
400
401 #[test]
402 fn test_log_scalar_f32_unary() {
403 let arg_field = Field::new("a", DataType::Float32, false).into();
404 let args = ScalarFunctionArgs {
405 args: vec![
406 ColumnarValue::Scalar(ScalarValue::Float32(Some(10.0))), ],
408 arg_fields: vec![arg_field],
409 number_rows: 1,
410 return_field: Field::new("f", DataType::Float32, true).into(),
411 config_options: Arc::new(ConfigOptions::default()),
412 lambdas: None,
413 };
414 let result = LogFunc::new()
415 .invoke_with_args(args)
416 .expect("failed to initialize function log");
417
418 match result {
419 ColumnarValue::Array(arr) => {
420 let floats = as_float32_array(&arr)
421 .expect("failed to convert result to a Float32Array");
422
423 assert_eq!(floats.len(), 1);
424 assert!((floats.value(0) - 1.0).abs() < 1e-10);
425 }
426 ColumnarValue::Scalar(_) => {
427 panic!("Expected an array value")
428 }
429 }
430 }
431
432 #[test]
433 fn test_log_scalar_f64_unary() {
434 let arg_field = Field::new("a", DataType::Float64, false).into();
435 let args = ScalarFunctionArgs {
436 args: vec![
437 ColumnarValue::Scalar(ScalarValue::Float64(Some(10.0))), ],
439 arg_fields: vec![arg_field],
440 number_rows: 1,
441 return_field: Field::new("f", DataType::Float64, true).into(),
442 config_options: Arc::new(ConfigOptions::default()),
443 lambdas: None,
444 };
445 let result = LogFunc::new()
446 .invoke_with_args(args)
447 .expect("failed to initialize function log");
448
449 match result {
450 ColumnarValue::Array(arr) => {
451 let floats = as_float64_array(&arr)
452 .expect("failed to convert result to a Float64Array");
453
454 assert_eq!(floats.len(), 1);
455 assert!((floats.value(0) - 1.0).abs() < 1e-10);
456 }
457 ColumnarValue::Scalar(_) => {
458 panic!("Expected an array value")
459 }
460 }
461 }
462
463 #[test]
464 fn test_log_scalar_f32() {
465 let arg_fields = vec![
466 Field::new("a", DataType::Float32, false).into(),
467 Field::new("a", DataType::Float32, false).into(),
468 ];
469 let args = ScalarFunctionArgs {
470 args: vec![
471 ColumnarValue::Scalar(ScalarValue::Float32(Some(2.0))), ColumnarValue::Scalar(ScalarValue::Float32(Some(32.0))), ],
474 arg_fields,
475 number_rows: 1,
476 return_field: Field::new("f", DataType::Float32, true).into(),
477 config_options: Arc::new(ConfigOptions::default()),
478 lambdas: None,
479 };
480 let result = LogFunc::new()
481 .invoke_with_args(args)
482 .expect("failed to initialize function log");
483
484 match result {
485 ColumnarValue::Array(arr) => {
486 let floats = as_float32_array(&arr)
487 .expect("failed to convert result to a Float32Array");
488
489 assert_eq!(floats.len(), 1);
490 assert!((floats.value(0) - 5.0).abs() < 1e-10);
491 }
492 ColumnarValue::Scalar(_) => {
493 panic!("Expected an array value")
494 }
495 }
496 }
497
498 #[test]
499 fn test_log_scalar_f64() {
500 let arg_fields = vec![
501 Field::new("a", DataType::Float64, false).into(),
502 Field::new("a", DataType::Float64, false).into(),
503 ];
504 let args = ScalarFunctionArgs {
505 args: vec![
506 ColumnarValue::Scalar(ScalarValue::Float64(Some(2.0))), ColumnarValue::Scalar(ScalarValue::Float64(Some(64.0))), ],
509 arg_fields,
510 number_rows: 1,
511 return_field: Field::new("f", DataType::Float64, true).into(),
512 config_options: Arc::new(ConfigOptions::default()),
513 lambdas: None,
514 };
515 let result = LogFunc::new()
516 .invoke_with_args(args)
517 .expect("failed to initialize function log");
518
519 match result {
520 ColumnarValue::Array(arr) => {
521 let floats = as_float64_array(&arr)
522 .expect("failed to convert result to a Float64Array");
523
524 assert_eq!(floats.len(), 1);
525 assert!((floats.value(0) - 6.0).abs() < 1e-10);
526 }
527 ColumnarValue::Scalar(_) => {
528 panic!("Expected an array value")
529 }
530 }
531 }
532
533 #[test]
534 fn test_log_f64_unary() {
535 let arg_field = Field::new("a", DataType::Float64, false).into();
536 let args = ScalarFunctionArgs {
537 args: vec![
538 ColumnarValue::Array(Arc::new(Float64Array::from(vec![
539 10.0, 100.0, 1000.0, 10000.0,
540 ]))), ],
542 arg_fields: vec![arg_field],
543 number_rows: 4,
544 return_field: Field::new("f", DataType::Float64, true).into(),
545 config_options: Arc::new(ConfigOptions::default()),
546 lambdas: None,
547 };
548 let result = LogFunc::new()
549 .invoke_with_args(args)
550 .expect("failed to initialize function log");
551
552 match result {
553 ColumnarValue::Array(arr) => {
554 let floats = as_float64_array(&arr)
555 .expect("failed to convert result to a Float64Array");
556
557 assert_eq!(floats.len(), 4);
558 assert!((floats.value(0) - 1.0).abs() < 1e-10);
559 assert!((floats.value(1) - 2.0).abs() < 1e-10);
560 assert!((floats.value(2) - 3.0).abs() < 1e-10);
561 assert!((floats.value(3) - 4.0).abs() < 1e-10);
562 }
563 ColumnarValue::Scalar(_) => {
564 panic!("Expected an array value")
565 }
566 }
567 }
568
569 #[test]
570 fn test_log_f32_unary() {
571 let arg_field = Field::new("a", DataType::Float32, false).into();
572 let args = ScalarFunctionArgs {
573 args: vec![
574 ColumnarValue::Array(Arc::new(Float32Array::from(vec![
575 10.0, 100.0, 1000.0, 10000.0,
576 ]))), ],
578 arg_fields: vec![arg_field],
579 number_rows: 4,
580 return_field: Field::new("f", DataType::Float32, true).into(),
581 config_options: Arc::new(ConfigOptions::default()),
582 lambdas: None,
583 };
584 let result = LogFunc::new()
585 .invoke_with_args(args)
586 .expect("failed to initialize function log");
587
588 match result {
589 ColumnarValue::Array(arr) => {
590 let floats = as_float32_array(&arr)
591 .expect("failed to convert result to a Float64Array");
592
593 assert_eq!(floats.len(), 4);
594 assert!((floats.value(0) - 1.0).abs() < 1e-10);
595 assert!((floats.value(1) - 2.0).abs() < 1e-10);
596 assert!((floats.value(2) - 3.0).abs() < 1e-10);
597 assert!((floats.value(3) - 4.0).abs() < 1e-10);
598 }
599 ColumnarValue::Scalar(_) => {
600 panic!("Expected an array value")
601 }
602 }
603 }
604
605 #[test]
606 fn test_log_f64() {
607 let arg_fields = vec![
608 Field::new("a", DataType::Float64, false).into(),
609 Field::new("a", DataType::Float64, false).into(),
610 ];
611 let args = ScalarFunctionArgs {
612 args: vec![
613 ColumnarValue::Array(Arc::new(Float64Array::from(vec![
614 2.0, 2.0, 3.0, 5.0, 5.0,
615 ]))), ColumnarValue::Array(Arc::new(Float64Array::from(vec![
617 8.0, 4.0, 81.0, 625.0, -123.0,
618 ]))), ],
620 arg_fields,
621 number_rows: 5,
622 return_field: Field::new("f", DataType::Float64, true).into(),
623 config_options: Arc::new(ConfigOptions::default()),
624 lambdas: None,
625 };
626 let result = LogFunc::new()
627 .invoke_with_args(args)
628 .expect("failed to initialize function log");
629
630 match result {
631 ColumnarValue::Array(arr) => {
632 let floats = as_float64_array(&arr)
633 .expect("failed to convert result to a Float64Array");
634
635 assert_eq!(floats.len(), 5);
636 assert!((floats.value(0) - 3.0).abs() < 1e-10);
637 assert!((floats.value(1) - 2.0).abs() < 1e-10);
638 assert!((floats.value(2) - 4.0).abs() < 1e-10);
639 assert!((floats.value(3) - 4.0).abs() < 1e-10);
640 assert!(floats.value(4).is_nan());
641 }
642 ColumnarValue::Scalar(_) => {
643 panic!("Expected an array value")
644 }
645 }
646 }
647
648 #[test]
649 fn test_log_f32() {
650 let arg_fields = vec![
651 Field::new("a", DataType::Float32, false).into(),
652 Field::new("a", DataType::Float32, false).into(),
653 ];
654 let args = ScalarFunctionArgs {
655 args: vec![
656 ColumnarValue::Array(Arc::new(Float32Array::from(vec![
657 2.0, 2.0, 3.0, 5.0,
658 ]))), ColumnarValue::Array(Arc::new(Float32Array::from(vec![
660 8.0, 4.0, 81.0, 625.0,
661 ]))), ],
663 arg_fields,
664 number_rows: 4,
665 return_field: Field::new("f", DataType::Float32, true).into(),
666 config_options: Arc::new(ConfigOptions::default()),
667 lambdas: None,
668 };
669 let result = LogFunc::new()
670 .invoke_with_args(args)
671 .expect("failed to initialize function log");
672
673 match result {
674 ColumnarValue::Array(arr) => {
675 let floats = as_float32_array(&arr)
676 .expect("failed to convert result to a Float32Array");
677
678 assert_eq!(floats.len(), 4);
679 assert!((floats.value(0) - 3.0).abs() < f32::EPSILON);
680 assert!((floats.value(1) - 2.0).abs() < f32::EPSILON);
681 assert!((floats.value(2) - 4.0).abs() < f32::EPSILON);
682 assert!((floats.value(3) - 4.0).abs() < f32::EPSILON);
683 }
684 ColumnarValue::Scalar(_) => {
685 panic!("Expected an array value")
686 }
687 }
688 }
689 #[test]
690 fn test_log_simplify_errors() {
692 let props = ExecutionProps::new();
693 let schema =
694 Arc::new(DFSchema::new_with_metadata(vec![], HashMap::new()).unwrap());
695 let context = SimplifyContext::new(&props).with_schema(schema);
696 let _ = LogFunc::new().simplify(vec![], &context).unwrap_err();
698 let _ = LogFunc::new()
700 .simplify(vec![lit(1), lit(2), lit(3)], &context)
701 .unwrap_err();
702 }
703
704 #[test]
705 fn test_log_simplify_original() {
707 let props = ExecutionProps::new();
708 let schema =
709 Arc::new(DFSchema::new_with_metadata(vec![], HashMap::new()).unwrap());
710 let context = SimplifyContext::new(&props).with_schema(schema);
711 let result = LogFunc::new().simplify(vec![lit(2)], &context).unwrap();
713 let ExprSimplifyResult::Original(args) = result else {
714 panic!("Expected ExprSimplifyResult::Original")
715 };
716 assert_eq!(args.len(), 1);
717 assert_eq!(args[0], lit(2));
718 let result = LogFunc::new()
720 .simplify(vec![lit(2), lit(3)], &context)
721 .unwrap();
722 let ExprSimplifyResult::Original(args) = result else {
723 panic!("Expected ExprSimplifyResult::Original")
724 };
725 assert_eq!(args.len(), 2);
726 assert_eq!(args[0], lit(2));
727 assert_eq!(args[1], lit(3));
728 }
729
730 #[test]
731 fn test_log_output_ordering() {
732 let orders = [
734 ExprProperties::new_unknown(),
735 ExprProperties::new_unknown().with_order(SortProperties::Ordered(
736 SortOptions {
737 descending: false,
738 nulls_first: true,
739 },
740 )),
741 ExprProperties::new_unknown().with_order(SortProperties::Ordered(
742 SortOptions {
743 descending: true,
744 nulls_first: true,
745 },
746 )),
747 ExprProperties::new_unknown().with_order(SortProperties::Singleton),
748 ];
749
750 let log = LogFunc::new();
751
752 for order in orders.iter().cloned() {
754 let result = log.output_ordering(std::slice::from_ref(&order)).unwrap();
755 assert_eq!(result, order.sort_properties);
756 }
757
758 let mut results = Vec::with_capacity(orders.len() * orders.len());
760 for base_order in orders.iter() {
761 for num_order in orders.iter().cloned() {
762 let result = log
763 .output_ordering(&[base_order.clone(), num_order])
764 .unwrap();
765 results.push(result);
766 }
767 }
768 let expected = [
769 SortProperties::Unordered,
771 SortProperties::Unordered,
772 SortProperties::Unordered,
773 SortProperties::Unordered,
774 SortProperties::Unordered,
776 SortProperties::Unordered,
778 SortProperties::Ordered(SortOptions {
780 descending: true,
781 nulls_first: true,
782 }),
783 SortProperties::Ordered(SortOptions {
785 descending: true,
786 nulls_first: true,
787 }),
788 SortProperties::Unordered,
790 SortProperties::Ordered(SortOptions {
792 descending: false,
793 nulls_first: true,
794 }),
795 SortProperties::Unordered,
797 SortProperties::Ordered(SortOptions {
799 descending: false,
800 nulls_first: true,
801 }),
802 SortProperties::Unordered,
804 SortProperties::Ordered(SortOptions {
806 descending: false,
807 nulls_first: true,
808 }),
809 SortProperties::Ordered(SortOptions {
811 descending: true,
812 nulls_first: true,
813 }),
814 SortProperties::Singleton,
816 ];
817 assert_eq!(results, expected);
818
819 let base_order = ExprProperties::new_unknown().with_order(
821 SortProperties::Ordered(SortOptions {
822 descending: true,
823 nulls_first: true,
824 }),
825 );
826 let num_order = ExprProperties::new_unknown().with_order(
827 SortProperties::Ordered(SortOptions {
828 descending: false,
829 nulls_first: false,
830 }),
831 );
832 assert_eq!(
833 log.output_ordering(&[base_order, num_order]).unwrap(),
834 SortProperties::Unordered
835 );
836 }
837
838 #[test]
839 fn test_log_scalar_decimal128_unary() {
840 let arg_field = Field::new("a", DataType::Decimal128(38, 0), false).into();
841 let args = ScalarFunctionArgs {
842 args: vec![
843 ColumnarValue::Scalar(ScalarValue::Decimal128(Some(10), 38, 0)), ],
845 arg_fields: vec![arg_field],
846 number_rows: 1,
847 return_field: Field::new("f", DataType::Decimal128(38, 0), true).into(),
848 config_options: Arc::new(ConfigOptions::default()),
849 lambdas: None,
850 };
851 let result = LogFunc::new()
852 .invoke_with_args(args)
853 .expect("failed to initialize function log");
854
855 match result {
856 ColumnarValue::Array(arr) => {
857 let floats = as_float64_array(&arr)
858 .expect("failed to convert result to a Decimal128Array");
859 assert_eq!(floats.len(), 1);
860 assert!((floats.value(0) - 1.0).abs() < 1e-10);
861 }
862 ColumnarValue::Scalar(_) => {
863 panic!("Expected an array value")
864 }
865 }
866 }
867
868 #[test]
869 fn test_log_scalar_decimal128() {
870 let arg_fields = vec![
871 Field::new("b", DataType::Float64, false).into(),
872 Field::new("x", DataType::Decimal128(38, 0), false).into(),
873 ];
874 let args = ScalarFunctionArgs {
875 args: vec![
876 ColumnarValue::Scalar(ScalarValue::Float64(Some(2.0))), ColumnarValue::Scalar(ScalarValue::Decimal128(Some(64), 38, 0)), ],
879 arg_fields,
880 number_rows: 1,
881 return_field: Field::new("f", DataType::Float64, true).into(),
882 config_options: Arc::new(ConfigOptions::default()),
883 lambdas: None,
884 };
885 let result = LogFunc::new()
886 .invoke_with_args(args)
887 .expect("failed to initialize function log");
888
889 match result {
890 ColumnarValue::Array(arr) => {
891 let floats = as_float64_array(&arr)
892 .expect("failed to convert result to a Float64Array");
893
894 assert_eq!(floats.len(), 1);
895 assert!((floats.value(0) - 6.0).abs() < 1e-10);
896 }
897 ColumnarValue::Scalar(_) => {
898 panic!("Expected an array value")
899 }
900 }
901 }
902
903 #[test]
904 fn test_log_decimal128_unary() {
905 let arg_field = Field::new("a", DataType::Decimal128(38, 0), false).into();
906 let args = ScalarFunctionArgs {
907 args: vec![
908 ColumnarValue::Array(Arc::new(
909 Decimal128Array::from(vec![10, 100, 1000, 10000, 12600, -123])
910 .with_precision_and_scale(38, 0)
911 .unwrap(),
912 )), ],
914 arg_fields: vec![arg_field],
915 number_rows: 6,
916 return_field: Field::new("f", DataType::Float64, true).into(),
917 config_options: Arc::new(ConfigOptions::default()),
918 lambdas: None,
919 };
920 let result = LogFunc::new()
921 .invoke_with_args(args)
922 .expect("failed to initialize function log");
923
924 match result {
925 ColumnarValue::Array(arr) => {
926 let floats = as_float64_array(&arr)
927 .expect("failed to convert result to a Float64Array");
928
929 assert_eq!(floats.len(), 6);
930 assert!((floats.value(0) - 1.0).abs() < 1e-10);
931 assert!((floats.value(1) - 2.0).abs() < 1e-10);
932 assert!((floats.value(2) - 3.0).abs() < 1e-10);
933 assert!((floats.value(3) - 4.0).abs() < 1e-10);
934 assert!((floats.value(4) - 4.0).abs() < 1e-10); assert!(floats.value(5).is_nan());
936 }
937 ColumnarValue::Scalar(_) => {
938 panic!("Expected an array value")
939 }
940 }
941 }
942
943 #[test]
944 fn test_log_decimal128_base_decimal() {
945 for base in [
947 ScalarValue::Decimal128(Some(i128::from(2)), 38, 0),
948 ScalarValue::Decimal128(Some(i128::from(2000)), 38, 3),
949 ] {
950 let arg_fields = vec![
951 Field::new("b", DataType::Decimal128(38, 0), false).into(),
952 Field::new("x", DataType::Decimal128(38, 0), false).into(),
953 ];
954 let args = ScalarFunctionArgs {
955 args: vec![
956 ColumnarValue::Scalar(base), ColumnarValue::Scalar(ScalarValue::Decimal128(Some(64), 38, 0)), ],
959 arg_fields,
960 number_rows: 1,
961 return_field: Field::new("f", DataType::Float64, true).into(),
962 config_options: Arc::new(ConfigOptions::default()),
963 lambdas: None,
964 };
965 let result = LogFunc::new()
966 .invoke_with_args(args)
967 .expect("failed to initialize function log");
968
969 match result {
970 ColumnarValue::Array(arr) => {
971 let floats = as_float64_array(&arr)
972 .expect("failed to convert result to a Float64Array");
973
974 assert_eq!(floats.len(), 1);
975 assert!((floats.value(0) - 6.0).abs() < 1e-10);
976 }
977 ColumnarValue::Scalar(_) => {
978 panic!("Expected an array value")
979 }
980 }
981 }
982 }
983
984 #[test]
985 fn test_log_decimal128_value_scale() {
986 for value in [
988 ScalarValue::Decimal128(Some(i128::from(1000)), 38, 0),
989 ScalarValue::Decimal128(Some(i128::from(10000)), 38, 1),
990 ScalarValue::Decimal128(Some(i128::from(1000000)), 38, 3),
991 ] {
992 let arg_fields = vec![
993 Field::new("b", DataType::Decimal128(38, 0), false).into(),
994 Field::new("x", DataType::Decimal128(38, 0), false).into(),
995 ];
996 let args = ScalarFunctionArgs {
997 args: vec![
998 ColumnarValue::Scalar(value), ],
1000 arg_fields,
1001 number_rows: 1,
1002 return_field: Field::new("f", DataType::Float64, true).into(),
1003 config_options: Arc::new(ConfigOptions::default()),
1004 lambdas: None,
1005 };
1006 let result = LogFunc::new()
1007 .invoke_with_args(args)
1008 .expect("failed to initialize function log");
1009
1010 match result {
1011 ColumnarValue::Array(arr) => {
1012 let floats = as_float64_array(&arr)
1013 .expect("failed to convert result to a Float64Array");
1014
1015 assert_eq!(floats.len(), 1);
1016 assert!((floats.value(0) - 3.0).abs() < 1e-10);
1017 }
1018 ColumnarValue::Scalar(_) => {
1019 panic!("Expected an array value")
1020 }
1021 }
1022 }
1023 }
1024
1025 #[test]
1026 fn test_log_decimal256_unary() {
1027 let arg_field = Field::new(
1028 "a",
1029 DataType::Decimal256(DECIMAL256_MAX_PRECISION, 0),
1030 false,
1031 )
1032 .into();
1033 let args = ScalarFunctionArgs {
1034 args: vec![
1035 ColumnarValue::Array(Arc::new(
1036 Decimal256Array::from(vec![
1037 Some(i256::from(10)),
1038 Some(i256::from(100)),
1039 Some(i256::from(1000)),
1040 Some(i256::from(10000)),
1041 Some(i256::from(12600)),
1042 Some(i256::from_i128(i128::MAX) - i256::from(1000)),
1044 Some(i256::from(-123)),
1046 ])
1047 .with_precision_and_scale(DECIMAL256_MAX_PRECISION, 0)
1048 .unwrap(),
1049 )), ],
1051 arg_fields: vec![arg_field],
1052 number_rows: 7,
1053 return_field: Field::new("f", DataType::Float64, true).into(),
1054 config_options: Arc::new(ConfigOptions::default()),
1055 lambdas: None,
1056 };
1057 let result = LogFunc::new()
1058 .invoke_with_args(args)
1059 .expect("failed to initialize function log");
1060
1061 match result {
1062 ColumnarValue::Array(arr) => {
1063 let floats = as_float64_array(&arr)
1064 .expect("failed to convert result to a Float64Array");
1065
1066 assert_eq!(floats.len(), 7);
1067 eprintln!("floats {:?}", &floats);
1068 assert!((floats.value(0) - 1.0).abs() < 1e-10);
1069 assert!((floats.value(1) - 2.0).abs() < 1e-10);
1070 assert!((floats.value(2) - 3.0).abs() < 1e-10);
1071 assert!((floats.value(3) - 4.0).abs() < 1e-10);
1072 assert!((floats.value(4) - 4.0).abs() < 1e-10); assert!((floats.value(5) - 38.0).abs() < 1e-10);
1074 assert!(floats.value(6).is_nan());
1075 }
1076 ColumnarValue::Scalar(_) => {
1077 panic!("Expected an array value")
1078 }
1079 }
1080 }
1081
1082 #[test]
1083 fn test_log_decimal128_wrong_base() {
1084 let arg_fields = vec![
1085 Field::new("b", DataType::Float64, false).into(),
1086 Field::new("x", DataType::Decimal128(38, 0), false).into(),
1087 ];
1088 let args = ScalarFunctionArgs {
1089 args: vec![
1090 ColumnarValue::Scalar(ScalarValue::Float64(Some(-2.0))), ColumnarValue::Scalar(ScalarValue::Decimal128(Some(64), 38, 0)), ],
1093 arg_fields,
1094 number_rows: 1,
1095 return_field: Field::new("f", DataType::Float64, true).into(),
1096 config_options: Arc::new(ConfigOptions::default()),
1097 lambdas: None,
1098 };
1099 let result = LogFunc::new().invoke_with_args(args);
1100 assert!(result.is_err());
1101 assert_eq!(
1102 "Arrow error: Compute error: Log base must be greater than 1: -2",
1103 result.unwrap_err().to_string().lines().next().unwrap()
1104 );
1105 }
1106
1107 #[test]
1108 fn test_log_decimal256_error() {
1109 let arg_field = Field::new("a", DataType::Decimal256(38, 0), false).into();
1110 let args = ScalarFunctionArgs {
1111 args: vec![
1112 ColumnarValue::Array(Arc::new(Decimal256Array::from(vec![
1113 Some(i256::from_i128(i128::MAX) + i256::from(1000)),
1115 ]))), ],
1117 arg_fields: vec![arg_field],
1118 number_rows: 1,
1119 return_field: Field::new("f", DataType::Float64, true).into(),
1120 config_options: Arc::new(ConfigOptions::default()),
1121 lambdas: None,
1122 };
1123 let result = LogFunc::new().invoke_with_args(args);
1124 assert!(result.is_err());
1125 assert_eq!(result.unwrap_err().to_string().lines().next().unwrap(),
1126 "Arrow error: Not yet implemented: Log of Decimal256 larger than Decimal128 is not yet supported: 170141183460469231731687303715884106727"
1127 );
1128 }
1129}