akar_function/scalar/
utility.rs1use crate::registry::*;
2use crate::scalar::comparison::compare_values;
3use akar_common::types::Value;
4
5pub(crate) fn evaluate_utility(op: UtilityOp, args: &[Value]) -> Result<Value, String> {
8 match op {
9 UtilityOp::Coalesce | UtilityOp::IfNull => {
10 for arg in args {
11 if !matches!(arg, Value::Null) {
12 return Ok(arg.clone());
13 }
14 }
15 Ok(Value::Null)
16 }
17 UtilityOp::TypeOf => {
18 if args.is_empty() {
19 return Ok(Value::String("NULL".into()));
20 }
21 Ok(Value::String(format!("{:?}", args[0].logical_type())))
22 }
23 UtilityOp::NullIf => {
24 if args.len() < 2 {
25 return Err("NULLIF requires 2 arguments".into());
26 }
27 if args[0] == args[1] {
28 Ok(Value::Null)
29 } else {
30 Ok(args[0].clone())
31 }
32 }
33 UtilityOp::Size => {
34 if args.is_empty() {
35 return Err("SIZE requires 1 argument".into());
36 }
37 match &args[0] {
38 Value::List(v) => Ok(Value::Int64(v.len() as i64)),
39 Value::String(s) => Ok(Value::Int64(s.len() as i64)),
40 Value::Map(v) => Ok(Value::Int64(v.len() as i64)),
41 Value::Null => Ok(Value::Null),
42 _ => Err(format!("SIZE does not support type {:?}", args[0].logical_type())),
43 }
44 }
45 UtilityOp::Error => {
46 if args.is_empty() {
47 return Err("ERROR requires 1 argument".into());
48 }
49 match &args[0] {
50 Value::String(s) => Err(s.clone()),
51 Value::Null => Err("user-triggered error".into()),
52 other => Err(format!("{:?}", other)),
53 }
54 }
55 UtilityOp::PgIsReady => Ok(Value::Bool(true)),
56 UtilityOp::Greatest => {
57 if args.is_empty() {
58 return Err("GREATEST requires at least one argument".into());
59 }
60 let mut result = Value::Null;
61 for arg in args {
62 if matches!(arg, Value::Null) {
63 continue;
64 }
65 if matches!(result, Value::Null) {
66 result = arg.clone();
67 } else if compare_values(arg, &result)?.is_gt() {
68 result = arg.clone();
69 }
70 }
71 Ok(result)
72 }
73 UtilityOp::Least => {
74 if args.is_empty() {
75 return Err("LEAST requires at least one argument".into());
76 }
77 let mut result = Value::Null;
78 for arg in args {
79 if matches!(arg, Value::Null) {
80 continue;
81 }
82 if matches!(result, Value::Null) {
83 result = arg.clone();
84 } else if compare_values(arg, &result)?.is_lt() {
85 result = arg.clone();
86 }
87 }
88 Ok(result)
89 }
90 UtilityOp::ConstantOrNull => {
91 if args.len() < 2 {
92 return Err("CONSTANT_OR_NULL requires 2 arguments".into());
93 }
94 if matches!(args[0], Value::Null) || matches!(args[1], Value::Null) {
95 Ok(Value::Null)
96 } else {
97 Ok(args[0].clone())
98 }
99 }
100 }
101}