From 63a79328c459b1ab982234e37de2e7bfc3aa50b5 Mon Sep 17 00:00:00 2001 From: victoria de sainte agathe Date: Mon, 20 Nov 2023 17:31:41 +0100 Subject: [PATCH 1/3] ok --- src/data_type/function.rs | 22 +++++++++++++++- src/expr/function.rs | 6 ++++- src/expr/implementation.rs | 4 +-- src/expr/mod.rs | 51 +++++++++++++++++++++++++++++++++++++- src/expr/sql.rs | 3 ++- 5 files changed, 80 insertions(+), 6 deletions(-) diff --git a/src/data_type/function.rs b/src/data_type/function.rs index 0a20d500..5d5a22c2 100644 --- a/src/data_type/function.rs +++ b/src/data_type/function.rs @@ -1838,7 +1838,7 @@ pub fn trunc() -> impl Function { pub fn sign() -> impl Function { PartitionnedMonotonic::univariate( data_type::Float::default(), - |a| a.signum() + |a| if a == 0. {0} else if a < 0. {-1} else {1} ) } @@ -3561,4 +3561,24 @@ mod tests { println!("im({}) = {}", set, im); assert!(im == DataType::boolean_value(true)); } + + #[test] + fn test_sign() { + println!("\nTest sign"); + let fun = sign(); + println!("type = {}", fun); + println!("domain = {}", fun.domain()); + println!("co_domain = {}", fun.co_domain()); + println!("data_type = {}", fun.data_type()); + + let set = DataType::float_interval(-5., 5.); + let im = fun.super_image(&set).unwrap(); + println!("im({}) = {}", set, im); + assert!(im == DataType::integer_interval(-1, 1)); + + let set = DataType::float_value(0.); + let im = fun.super_image(&set).unwrap(); + println!("im({}) = {}", set, im); + assert!(im == DataType::integer_value(0)); + } } diff --git a/src/expr/function.rs b/src/expr/function.rs index f746c562..e96dec1a 100644 --- a/src/expr/function.rs +++ b/src/expr/function.rs @@ -33,6 +33,7 @@ pub enum Function { BitwiseXor, InList, Coalesce, + Sign, // Functions Exp, Ln, @@ -132,6 +133,7 @@ impl Function { | Function::Floor | Function::CastAsDate | Function::CastAsTime + | Function::Sign // Binary Functions | Function::Pow | Function::Position @@ -198,7 +200,8 @@ impl Function { | Function::CastAsDate | Function::CastAsTime | Function::Ceil - | Function::Floor => Arity::Unary, + | Function::Floor + | Function::Sign => Arity::Unary, // Binary Function Function::Pow | Function::Position @@ -289,6 +292,7 @@ impl fmt::Display for Function { Function::Floor => "floor", Function::CastAsDate => "cast_as_date", Function::CastAsTime => "cast_as_time", + Function::Sign => "sign", // Binary Functions Function::Pow => "pow", Function::Position => "position", diff --git a/src/expr/implementation.rs b/src/expr/implementation.rs index 9d035759..344ddfac 100644 --- a/src/expr/implementation.rs +++ b/src/expr/implementation.rs @@ -40,12 +40,12 @@ macro_rules! function_implementations { } // All functions: -// Unary: Opposite, Not, Exp, Ln, Abs, Sin, Cos, CharLength, Lower, Upper, Md5, Ceil, Floor +// Unary: Opposite, Not, Exp, Ln, Abs, Sin, Cos, CharLength, Lower, Upper, Md5, Ceil, Floor, Sign // Binary: Plus, Minus, Multiply, Divide, Modulo, StringConcat, Gt, Lt, GtEq, LtEq, Eq, NotEq, And, Or, Xor, BitwiseOr, BitwiseAnd, BitwiseXor, Position, Concat, Greatest, Least, Round, Trunc // Ternary: Case, Position // Nary: Concat function_implementations!( - [Opposite, Not, Exp, Ln, Log, Abs, Sin, Cos, Sqrt, Md5, Ceil, Floor], + [Opposite, Not, Exp, Ln, Log, Abs, Sin, Cos, Sqrt, Md5, Ceil, Floor, Sign], [ Plus, Minus, diff --git a/src/expr/mod.rs b/src/expr/mod.rs index 0facd6f2..be6af12f 100644 --- a/src/expr/mod.rs +++ b/src/expr/mod.rs @@ -286,7 +286,8 @@ impl_unary_function_constructors!( CastAsDate, CastAsTime, Ceil, - Floor + Floor, + Sign ); // TODO Complete that /// Implement binary function constructors @@ -2998,4 +2999,52 @@ mod tests { DataType::boolean_value(false) ); } + + #[test] + fn test_sign() { + println!("sign"); + let expression = Expr::sign( + Expr::col("col1".to_string()) + ); + println!("expression = {}", expression); + println!("expression domain = {}", expression.domain()); + println!("expression co domain = {}", expression.co_domain()); + println!("expression data type = {}", expression.data_type()); + + let set = DataType::structured([ + ("col1", DataType::float_interval(-10., 1.)), + ]); + println!( + "expression super image = {}", + expression.super_image(&set).unwrap() + ); + assert_eq!( + expression.super_image(&set).unwrap(), + DataType::integer_interval(-1, 1) + ); + + let set = DataType::structured([ + ("col1", DataType::integer_min(-0)), + ]); + println!( + "expression super image = {}", + expression.super_image(&set).unwrap() + ); + assert_eq!( + expression.super_image(&set).unwrap(), + DataType::integer_interval(0, 1) + ); + + let set = DataType::structured([ + ("col1", DataType::float_min(1.)), + ]); + println!( + "expression super image = {}", + expression.super_image(&set).unwrap() + ); + assert_eq!( + expression.super_image(&set).unwrap(), + DataType::integer_value(1) + ); + } } diff --git a/src/expr/sql.rs b/src/expr/sql.rs index c78eaced..029fa611 100644 --- a/src/expr/sql.rs +++ b/src/expr/sql.rs @@ -186,7 +186,8 @@ impl<'a> expr::Visitor<'a, ast::Expr> for FromExprVisitor { | expr::function::Function::Substr | expr::function::Function::SubstrWithSize | expr::function::Function::Ceil - | expr::function::Function::Floor => ast::Expr::Function(ast::Function { + | expr::function::Function::Floor + | expr::function::Function::Sign => ast::Expr::Function(ast::Function { name: ast::ObjectName(vec![ast::Ident::new(function.to_string())]), args: arguments .into_iter() From dd8c319d7c9faf5479a105f0ff7adb372276d7d6 Mon Sep 17 00:00:00 2001 From: victoria de sainte agathe Date: Mon, 20 Nov 2023 17:33:52 +0100 Subject: [PATCH 2/3] ok --- src/expr/sql.rs | 11 +++++++++++ src/sql/expr.rs | 1 + 2 files changed, 12 insertions(+) diff --git a/src/expr/sql.rs b/src/expr/sql.rs index 029fa611..a364032b 100644 --- a/src/expr/sql.rs +++ b/src/expr/sql.rs @@ -652,4 +652,15 @@ mod tests { println!("ast::expr = {gen_expr}"); assert_eq!(ast_expr.to_string().to_lowercase(), gen_expr.to_string().to_lowercase()); } + + #[test] + fn test_sign() { + let str_expr = "sign(a)"; + let ast_expr: ast::Expr = parse_expr(str_expr).unwrap(); + let expr = Expr::try_from(&ast_expr).unwrap(); + println!("expr = {}", expr); + let gen_expr = ast::Expr::from(&expr); + println!("ast::expr = {gen_expr}"); + assert_eq!(ast_expr, gen_expr); + } } diff --git a/src/sql/expr.rs b/src/sql/expr.rs index 941ca1df..2af7561c 100644 --- a/src/sql/expr.rs +++ b/src/sql/expr.rs @@ -980,6 +980,7 @@ impl<'a> Visitor<'a, Result> for TryIntoExprVisitor<'a> { precision, ) } + "sign" => Expr::sign(flat_args[0].clone()), // Aggregates "min" => Expr::min(flat_args[0].clone()), "max" => Expr::max(flat_args[0].clone()), From a6fa1645220d6026287b098a41814dad0641b219 Mon Sep 17 00:00:00 2001 From: victoria de sainte agathe Date: Mon, 20 Nov 2023 17:35:01 +0100 Subject: [PATCH 3/3] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2af7cdf9..48789fa7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ## Added +- `SIGN` funtion [#194](https://github.com/Qrlew/qrlew/issues/194) - `CEIL`, `ROUND`, `FLOOR`and `TRUNC` funtions [#192](https://github.com/Qrlew/qrlew/issues/192) ## [0.5.1] - 2023-11-19