diff --git a/dozer-sql/expression/src/scalar/common.rs b/dozer-sql/expression/src/scalar/common.rs index b22e12cd6c..c2549dbe9f 100644 --- a/dozer-sql/expression/src/scalar/common.rs +++ b/dozer-sql/expression/src/scalar/common.rs @@ -11,7 +11,9 @@ use dozer_types::types::Record; use dozer_types::types::{Field, FieldType, Schema}; use std::fmt::{Display, Formatter}; -use super::string::{evaluate_chr, evaluate_substr, validate_substr}; +use super::string::{ + evaluate_chr, evaluate_replace, evaluate_substr, validate_replace, validate_substr, +}; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)] pub enum ScalarFunctionType { @@ -24,6 +26,7 @@ pub enum ScalarFunctionType { Chr, Substr, Nvl, + Replace, } impl Display for ScalarFunctionType { @@ -38,6 +41,7 @@ impl Display for ScalarFunctionType { ScalarFunctionType::Chr => f.write_str("CHR"), ScalarFunctionType::Substr => f.write_str("SUBSTR"), ScalarFunctionType::Nvl => f.write_str("NVL"), + ScalarFunctionType::Replace => f.write_str("REPLACE"), } } } @@ -87,6 +91,7 @@ pub(crate) fn get_scalar_function_type( ScalarFunctionType::Nvl => { Ok(validate_two_arguments(args, schema, ScalarFunctionType::Nvl)?.0) } + ScalarFunctionType::Replace => validate_replace(args, schema), } } @@ -101,6 +106,7 @@ impl ScalarFunctionType { "to_char" => Some(ScalarFunctionType::ToChar), "chr" => Some(ScalarFunctionType::Chr), "substr" => Some(ScalarFunctionType::Substr), + "replace" => Some(ScalarFunctionType::Replace), "nvl" => Some(ScalarFunctionType::Nvl), _ => None, } @@ -155,6 +161,16 @@ impl ScalarFunctionType { validate_two_arguments(args, schema, ScalarFunctionType::Nvl)?; evaluate_nvl(schema, &mut args[0].clone(), &mut args[1].clone(), record) } + ScalarFunctionType::Replace => { + validate_replace(args, schema)?; + evaluate_replace( + schema, + &mut args[0].clone(), + &mut args[1].clone(), + &mut args[2].clone(), + record, + ) + } } } } diff --git a/dozer-sql/expression/src/scalar/string.rs b/dozer-sql/expression/src/scalar/string.rs index a780a68161..945d97b227 100644 --- a/dozer-sql/expression/src/scalar/string.rs +++ b/dozer-sql/expression/src/scalar/string.rs @@ -415,6 +415,58 @@ pub(crate) fn evaluate_substr( Ok(Field::String(result)) } +pub fn validate_replace(args: &[Expression], schema: &Schema) -> Result { + if args.len() != 3 { + return Err(Error::InvalidFunctionArgument { + function_name: ScalarFunctionType::Replace.to_string(), + argument_index: 0, + argument: Field::Null, + }); + } + + let mut ret_type = FieldType::String; + for exp in args { + let r = validate_arg_type( + exp, + vec![FieldType::String, FieldType::Text], + schema, + ScalarFunctionType::Replace, + 0, + )?; + if matches!(r.return_type, FieldType::Text) { + ret_type = FieldType::Text; + } + } + + Ok(ExpressionType::new( + ret_type, + false, + dozer_types::types::SourceDefinition::Dynamic, + false, + )) +} + +pub(crate) fn evaluate_replace( + schema: &Schema, + arg: &mut Expression, + search: &mut Expression, + replace: &mut Expression, + record: &Record, +) -> Result { + let arg_field = arg.evaluate(record, schema)?; + let arg_value = arg_field.to_string(); + + let search_field = search.evaluate(record, schema)?; + let search_value = search_field.to_string(); + + let replace_field = replace.evaluate(record, schema)?; + let replace_value = replace_field.to_string(); + + let result = arg_value.replace(search_value.as_str(), replace_value.as_str()); + + Ok(Field::String(result)) +} + #[cfg(test)] mod tests { use super::*;