From 072b43e4597958c7ca6cccd0dd531cffbd36422d Mon Sep 17 00:00:00 2001 From: Dario Pizzamiglio <1150680+mediuminvader@users.noreply.github.com> Date: Mon, 26 Feb 2024 15:08:35 +0100 Subject: [PATCH] Add nvl --- dozer-sql/expression/src/scalar/common.rs | 34 +++++++++++++++-------- dozer-sql/expression/src/scalar/field.rs | 19 +++++++++++++ dozer-sql/expression/src/scalar/mod.rs | 1 + dozer-sql/expression/src/scalar/string.rs | 18 ++---------- 4 files changed, 45 insertions(+), 27 deletions(-) create mode 100644 dozer-sql/expression/src/scalar/field.rs diff --git a/dozer-sql/expression/src/scalar/common.rs b/dozer-sql/expression/src/scalar/common.rs index 1447c5d18e..b22e12cd6c 100644 --- a/dozer-sql/expression/src/scalar/common.rs +++ b/dozer-sql/expression/src/scalar/common.rs @@ -1,6 +1,7 @@ use crate::arg_utils::{validate_num_arguments, validate_one_argument, validate_two_arguments}; use crate::error::Error; use crate::execution::{Expression, ExpressionType}; +use crate::scalar::field::evaluate_nvl; use crate::scalar::number::{evaluate_abs, evaluate_round}; use crate::scalar::string::{ evaluate_concat, evaluate_length, evaluate_to_char, evaluate_ucase, validate_concat, @@ -22,6 +23,7 @@ pub enum ScalarFunctionType { ToChar, Chr, Substr, + Nvl, } impl Display for ScalarFunctionType { @@ -35,6 +37,7 @@ impl Display for ScalarFunctionType { ScalarFunctionType::ToChar => f.write_str("TO_CHAR"), ScalarFunctionType::Chr => f.write_str("CHR"), ScalarFunctionType::Substr => f.write_str("SUBSTR"), + ScalarFunctionType::Nvl => f.write_str("NVL"), } } } @@ -81,6 +84,9 @@ pub(crate) fn get_scalar_function_type( } ScalarFunctionType::Chr => validate_one_argument(args, schema, ScalarFunctionType::Chr), ScalarFunctionType::Substr => validate_substr(args, schema), + ScalarFunctionType::Nvl => { + Ok(validate_two_arguments(args, schema, ScalarFunctionType::Nvl)?.0) + } } } @@ -94,7 +100,8 @@ impl ScalarFunctionType { "length" => Some(ScalarFunctionType::Length), "to_char" => Some(ScalarFunctionType::ToChar), "chr" => Some(ScalarFunctionType::Chr), - + "substr" => Some(ScalarFunctionType::Substr), + "nvl" => Some(ScalarFunctionType::Nvl), _ => None, } } @@ -130,20 +137,23 @@ impl ScalarFunctionType { evaluate_to_char(schema, &mut arg0[0], &mut arg1[0], record) } ScalarFunctionType::Chr => { - validate_num_arguments(1..2, args.len(), ScalarFunctionType::Chr)?; + validate_one_argument(args, schema, ScalarFunctionType::Chr)?; evaluate_chr(schema, &mut args[0], record) } ScalarFunctionType::Substr => { - let (mut arg0, mut arg1, mut arg2) = if let Some(arg) = args.get(2) { - ( - args[0].clone(), - args[1].clone(), - Some(Box::new(arg.clone())), - ) - } else { - (args[0].clone(), args[1].clone(), None) - }; - evaluate_substr(schema, &mut arg0, &mut arg1, &mut arg2, record) + validate_num_arguments(2..3, args.len(), ScalarFunctionType::Substr)?; + let mut arg2 = args.get(2).map(|arg| Box::new(arg.clone())); + evaluate_substr( + schema, + &mut args[0].clone(), + &mut args[1].clone(), + &mut arg2, + record, + ) + } + ScalarFunctionType::Nvl => { + validate_two_arguments(args, schema, ScalarFunctionType::Nvl)?; + evaluate_nvl(schema, &mut args[0].clone(), &mut args[1].clone(), record) } } } diff --git a/dozer-sql/expression/src/scalar/field.rs b/dozer-sql/expression/src/scalar/field.rs new file mode 100644 index 0000000000..e85c199258 --- /dev/null +++ b/dozer-sql/expression/src/scalar/field.rs @@ -0,0 +1,19 @@ +use crate::error::Error; +use crate::execution::Expression; +use dozer_types::types::Record; +use dozer_types::types::{Field, Schema}; + +pub(crate) fn evaluate_nvl( + schema: &Schema, + arg: &mut Expression, + replacement: &mut Expression, + record: &Record, +) -> Result { + let arg_field = arg.evaluate(record, schema)?; + let replacement_field = replacement.evaluate(record, schema)?; + if replacement_field.as_string().is_some() && arg_field == Field::Null { + Ok(replacement_field) + } else { + Ok(arg_field) + } +} diff --git a/dozer-sql/expression/src/scalar/mod.rs b/dozer-sql/expression/src/scalar/mod.rs index 61735d2873..08358522c3 100644 --- a/dozer-sql/expression/src/scalar/mod.rs +++ b/dozer-sql/expression/src/scalar/mod.rs @@ -1,3 +1,4 @@ pub mod common; +pub mod field; pub mod number; pub mod string; diff --git a/dozer-sql/expression/src/scalar/string.rs b/dozer-sql/expression/src/scalar/string.rs index a4f054dfce..a780a68161 100644 --- a/dozer-sql/expression/src/scalar/string.rs +++ b/dozer-sql/expression/src/scalar/string.rs @@ -381,7 +381,7 @@ pub(crate) fn evaluate_substr( let position_field = position.evaluate(record, schema)?; let position_result = position_field.to_i128(); - if !position_result.is_some() { + if position_result.is_none() { return Err(Error::InvalidFunctionArgument { function_name: "SUBSTR".to_string(), argument_index: 1, @@ -394,7 +394,7 @@ pub(crate) fn evaluate_substr( Some(length_expr) => { let length_field = length_expr.evaluate(record, schema)?; let length_result = length_field.to_i128(); - if !length_result.is_some() { + if length_result.is_none() { return Err(Error::InvalidFunctionArgument { function_name: "SUBSTR".to_string(), argument_index: 2, @@ -426,12 +426,11 @@ mod tests { fn test_string() { proptest!( ProptestConfig::with_cases(1000), - move |(s_val in ".+", s_val1 in ".*", s_val2 in ".*", c_val: char, i_val: i64) | { + move |(s_val in ".+", s_val1 in ".*", s_val2 in ".*", c_val: char) | { test_like(&s_val, c_val); test_ucase(&s_val, c_val); test_concat(&s_val1, &s_val2, c_val); test_trim(&s_val, c_val); - test_chr(i_val) }); } @@ -733,15 +732,4 @@ mod tests { ); } } - - fn test_chr(val: i64) { - let row = Record::new(vec![]); - - // Field::String - let mut value = Box::new(Literal(Field::Int(val))); - assert_eq!( - evaluate_chr(&Schema::default(), &mut value, &row).unwrap(), - Field::String((((val % 256) as u8) as char).to_string()) - ); - } }