From 222fd60a95d08e9792e5cf04bef843032613f90a Mon Sep 17 00:00:00 2001 From: Dario Pizzamiglio <1150680+mediuminvader@users.noreply.github.com> Date: Tue, 27 Feb 2024 18:02:53 +0100 Subject: [PATCH] Add Decode --- dozer-sql/expression/src/scalar/common.rs | 22 +++++++++++ dozer-sql/expression/src/scalar/field.rs | 45 ++++++++++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/dozer-sql/expression/src/scalar/common.rs b/dozer-sql/expression/src/scalar/common.rs index c2549dbe9f..424cbbc87f 100644 --- a/dozer-sql/expression/src/scalar/common.rs +++ b/dozer-sql/expression/src/scalar/common.rs @@ -11,6 +11,7 @@ use dozer_types::types::Record; use dozer_types::types::{Field, FieldType, Schema}; use std::fmt::{Display, Formatter}; +use super::field::{evaluate_decode, validate_decode}; use super::string::{ evaluate_chr, evaluate_replace, evaluate_substr, validate_replace, validate_substr, }; @@ -27,6 +28,7 @@ pub enum ScalarFunctionType { Substr, Nvl, Replace, + Decode, } impl Display for ScalarFunctionType { @@ -42,6 +44,7 @@ impl Display for ScalarFunctionType { ScalarFunctionType::Substr => f.write_str("SUBSTR"), ScalarFunctionType::Nvl => f.write_str("NVL"), ScalarFunctionType::Replace => f.write_str("REPLACE"), + ScalarFunctionType::Decode => f.write_str("DECODE"), } } } @@ -92,6 +95,7 @@ pub(crate) fn get_scalar_function_type( Ok(validate_two_arguments(args, schema, ScalarFunctionType::Nvl)?.0) } ScalarFunctionType::Replace => validate_replace(args, schema), + ScalarFunctionType::Decode => validate_decode(args, schema), } } @@ -171,6 +175,24 @@ impl ScalarFunctionType { record, ) } + ScalarFunctionType::Decode => { + validate_decode(args, schema)?; + + let (arg0, results) = args.split_at_mut(1); + let (results, default) = if results.len() % 2 == 0 { + results.split_at_mut(results.len() - 1) + } else { + results.split_at_mut(results.len()) + }; + + let default = if default.len() == 0 { + None + } else { + Some(default[0].clone()) + }; + + evaluate_decode(schema, &mut arg0[0], results, default, record) + } } } } diff --git a/dozer-sql/expression/src/scalar/field.rs b/dozer-sql/expression/src/scalar/field.rs index e85c199258..330e6e3a0e 100644 --- a/dozer-sql/expression/src/scalar/field.rs +++ b/dozer-sql/expression/src/scalar/field.rs @@ -1,5 +1,5 @@ use crate::error::Error; -use crate::execution::Expression; +use crate::execution::{Expression, ExpressionType}; use dozer_types::types::Record; use dozer_types::types::{Field, Schema}; @@ -17,3 +17,46 @@ pub(crate) fn evaluate_nvl( Ok(arg_field) } } + +pub fn validate_decode(args: &[Expression], schema: &Schema) -> Result { + if args.len() < 3 { + return Err(Error::InvalidNumberOfArguments { + function_name: "decode".to_string(), + expected: 3..usize::MAX, + actual: args.len(), + }); + } + + let ret_type = args[2].get_type(schema)?.return_type; + + Ok(ExpressionType::new( + ret_type, + false, + dozer_types::types::SourceDefinition::Dynamic, + false, + )) +} + +pub(crate) fn evaluate_decode( + schema: &Schema, + arg: &mut Expression, + results: &mut [Expression], + default: Option, + record: &Record, +) -> Result { + let arg_field = arg.evaluate(record, schema)?; + let mut i = 0; + while i < results.len() { + let result = &mut results[i]; + let result_field = result.evaluate(record, schema)?; + if arg_field == result_field { + return Ok(results[i + 1].evaluate(record, schema)?); + } + i += 2; + } + if let Some(mut default) = default { + default.evaluate(record, schema) + } else { + Ok(Field::Null) + } +}