Skip to content

Commit

Permalink
Add nvl
Browse files Browse the repository at this point in the history
  • Loading branch information
mediuminvader committed Feb 26, 2024
1 parent e28c841 commit 072b43e
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 27 deletions.
34 changes: 22 additions & 12 deletions dozer-sql/expression/src/scalar/common.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -22,6 +23,7 @@ pub enum ScalarFunctionType {
ToChar,
Chr,
Substr,
Nvl,
}

impl Display for ScalarFunctionType {
Expand All @@ -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"),
}
}
}
Expand Down Expand Up @@ -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)
}
}
}

Expand All @@ -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,
}
}
Expand Down Expand Up @@ -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)
}
}
}
Expand Down
19 changes: 19 additions & 0 deletions dozer-sql/expression/src/scalar/field.rs
Original file line number Diff line number Diff line change
@@ -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<Field, Error> {
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)
}
}
1 change: 1 addition & 0 deletions dozer-sql/expression/src/scalar/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod common;
pub mod field;
pub mod number;
pub mod string;
18 changes: 3 additions & 15 deletions dozer-sql/expression/src/scalar/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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)
});
}

Expand Down Expand Up @@ -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())
);
}
}

0 comments on commit 072b43e

Please sign in to comment.