Skip to content

Commit

Permalink
Merge pull request #203 from Qrlew/impl_boolean_conditions
Browse files Browse the repository at this point in the history
Impl boolean conditions
  • Loading branch information
ngrislain authored Dec 1, 2023
2 parents 98459d4 + c1dc238 commit 826697f
Show file tree
Hide file tree
Showing 7 changed files with 481 additions and 25 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Changed
- some cleaning in the translation of Expr -> ast::Expr [#204](https://github.com/Qrlew/qrlew/issues/204)
## Added
- implemented `BETWEEN`, `IS TRUE`, `IS FALSE`, `IS NULL`, `CHOOSE`, `LIKE` and `ILIKE` [#203](https://github.com/Qrlew/qrlew/issues/203)
- implemented `DAYNAME`, `FROM_UNIXTIME`, `UNIX_TIMESTAMP`, `DATETIME_DIFF`, `QUARTER` and `DATE_FORMAT` [#202](https://github.com/Qrlew/qrlew/issues/202)
- implemented `CURRENT_DATE`, `CURRENT_TIME`, `CURRENT_TIMESTAMP` and `EXTRACT(datepart FROM col)` [#200](https://github.com/Qrlew/qrlew/issues/200)
- implemented `DISTINCT` in aggregations [#197](https://github.com/Qrlew/qrlew/issues/197)
Expand Down
170 changes: 170 additions & 0 deletions src/data_type/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1826,6 +1826,48 @@ pub fn unhex() -> impl Function {
)
}

pub fn like() -> impl Function {
Unimplemented::new(
DataType::text(),
DataType::boolean(),
Arc::new(Mutex::new(RefCell::new(|_| unimplemented!())))
)
}

pub fn ilike() -> impl Function {
Unimplemented::new(
DataType::text(),
DataType::boolean(),
Arc::new(Mutex::new(RefCell::new(|_| unimplemented!())))
)
}

pub fn is_null() -> impl Function {
Pointwise::univariate(
DataType::Any,
DataType::boolean(),
|v| if let Value::Optional(o) = v {
o.is_none()
} else {
false
}.into()
)
}

pub fn is_bool() -> impl Function {
Pointwise::bivariate(
(DataType::optional(DataType::boolean()), DataType::boolean()),
data_type::Boolean::default(),
|a, b| if let Value::Optional(o) = a {
o.as_ref()
.map(|x| *x.deref() == b)
.unwrap_or(false)
} else {
a == b
}.into()
)
}

// Date functions
pub fn current_date() -> impl Function {
Unimplemented::new(
Expand Down Expand Up @@ -2211,6 +2253,24 @@ pub fn sign() -> impl Function {
)
}

pub fn choose() -> impl Function {
Pointwise::new(
DataType::structured_from_data_types([DataType::integer(), DataType::list(DataType::Any, 1, i64::MAX as usize)]),
DataType::optional(DataType::Any),
Arc::new(|v| {
if let Value::Struct(s) = v {
if let (Value::Integer(i),Value::List(l)) = (s[0].as_ref(), s[1].as_ref()) {
Ok(value::Optional::new(l.get(*i.deref() as usize).map(|v| Arc::new(v.clone()))).into())
} else {
return Err(Error::other("Argument out of range"))
}
} else {
Err(Error::other("Argument out of range"))
}
})
)
}

/*
Aggregation functions
*/
Expand Down Expand Up @@ -4448,4 +4508,114 @@ mod tests {
println!("im({}) = {}", set, im);
assert!(im == DataType::date_value(NaiveDate::from_ymd_opt(2026, 7, 8).unwrap()));
}

#[test]
fn test_choose() {
println!("\nTest choose");
let fun = choose();
println!("type = {}", fun);
println!("domain = {}", fun.domain());
println!("co_domain = {}", fun.co_domain());
println!("data_type = {}", fun.data_type());

let set = DataType::structured_from_data_types([
DataType::integer_value(2),
DataType::list(DataType::text_values(
["a".to_string(), "b".to_string(), "c".to_string()]
), 1, 3)
]);
let im = fun.super_image(&set).unwrap();
println!("im({}) = {}", set, im);
assert!(im == DataType::optional(DataType::Any));
let arg = Value::structured_from_values([
2.into(),
Value::list(["a".to_string(), "b".to_string(), "c".to_string()].into_iter().map(|s| Value::from(s)))
]);
let val = fun.value(&arg).unwrap();
println!("val({}) = {}", arg, val);
assert_eq!(val, Value::Optional(value::Optional::new(Some(Arc::new("c".to_string().into())))));
}

#[test]
fn test_is_null() {
println!("\nTest is_null");
let fun = is_null();
println!("type = {}", fun);
println!("domain = {}", fun.domain());
println!("co_domain = {}", fun.co_domain());
println!("data_type = {}", fun.data_type());

let set = DataType::optional(DataType::Any);
let im = fun.super_image(&set).unwrap();
println!("im({}) = {}", set, im);
assert!(im == DataType::boolean());

let arg = Value::Optional(value::Optional::none());
let val = fun.value(&arg).unwrap();
println!("val({}) = {}", arg, val);
assert_eq!(val, true.into());

let arg = Value::Optional(value::Optional::some(true.into()));
let val = fun.value(&arg).unwrap();
println!("val({}) = {}", arg, val);
assert_eq!(val, false.into());
}

#[test]
fn test_is_bool() {
println!("\nTest is_bool");
let fun = is_bool();
println!("type = {}", fun);
println!("domain = {}", fun.domain());
println!("co_domain = {}", fun.co_domain());
println!("data_type = {}", fun.data_type());

// True
let set = DataType::structured_from_data_types([
DataType::boolean(),
DataType::boolean_value(true)
]);
let im = fun.super_image(&set).unwrap();
println!("im({}) = {}", set, im);
assert!(im == DataType::boolean());

let arg = Value::structured_from_values([
Value::from(true), Value::from(true)
]);
let val = fun.value(&arg).unwrap();
println!("val({}) = {}", arg, val);
assert_eq!(val, true.into());

let arg = Value::structured_from_values([
Value::from(true), Value::from(false)
]);
let val = fun.value(&arg).unwrap();
println!("val({}) = {}", arg, val);
assert_eq!(val, false.into());

// False
let set = DataType::structured_from_data_types([
DataType::boolean(),
DataType::boolean_value(false)
]);
let im = fun.super_image(&set).unwrap();
println!("im({}) = {}", set, im);
assert!(im == DataType::boolean());

let arg = Value::structured_from_values([
Value::from(false), Value::from(false)
]);
let val = fun.value(&arg).unwrap();
println!("val({}) = {}", arg, val);
assert_eq!(val, true.into());

let arg = Value::structured_from_values([
Value::from(false), Value::from(true)
]);
let val = fun.value(&arg).unwrap();
println!("val({}) = {}", arg, val);
assert_eq!(val, false.into());
}


}
37 changes: 29 additions & 8 deletions src/expr/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ pub enum Function {
BitwiseOr,
BitwiseAnd,
BitwiseXor,
InList,
Coalesce,
Sign,
// Functions
Exp,
Ln,
Expand Down Expand Up @@ -95,7 +92,15 @@ pub enum Function {
DateFormat,
Quarter,
DatetimeDiff,
Date
Date,
InList,
Coalesce,
Sign,
Like,
Ilike,
Choose,
IsNull,
IsBool
}

#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
Expand Down Expand Up @@ -182,6 +187,7 @@ impl Function {
| Function::UnixTimestamp
| Function::Quarter
| Function::Date
| Function::IsNull
// Binary Functions
| Function::Pow
| Function::Position
Expand All @@ -198,6 +204,10 @@ impl Function {
| Function::Decode
| Function::FromUnixtime
| Function::DateFormat
| Function::Choose
| Function::Like
| Function::Ilike
| Function::IsBool
// Ternary Function
| Function::Case
| Function::SubstrWithSize
Expand All @@ -211,7 +221,7 @@ impl Function {

/// Return the arity of the function
pub fn arity(self) -> Arity {
match self {
let arity = match self {
// Unary Operators
Function::Opposite | Function::Not => Arity::Unary,
// Binary Operators
Expand Down Expand Up @@ -279,7 +289,8 @@ impl Function {
| Function::Dayname
| Function::UnixTimestamp
| Function::Quarter
| Function::Date => Arity::Unary,
| Function::Date
| Function::IsNull => Arity::Unary,
// Binary Function
Function::Pow
| Function::Position
Expand All @@ -293,7 +304,11 @@ impl Function {
| Function::Trunc
| Function::RegexpContains
| Function::FromUnixtime
| Function::DateFormat => {
| Function::DateFormat
| Function::Choose
| Function::Like
| Function::Ilike
| Function::IsBool => {
Arity::Nary(2)
}
// Ternary Function
Expand All @@ -302,7 +317,8 @@ impl Function {
Function::RegexpExtract => Arity::Nary(4),
// Nary Function
Function::Concat(_) => Arity::Varying,
}
};
arity
}

/// Return the function object implementing the function
Expand Down Expand Up @@ -396,6 +412,7 @@ impl fmt::Display for Function {
Function::UnixTimestamp => "unix_timestamp",
Function::Quarter => "quarter",
Function::Date => "date",
Function::IsNull => "is_null",
// Binary Functions
Function::Pow => "pow",
Function::Position => "position",
Expand All @@ -412,6 +429,10 @@ impl fmt::Display for Function {
Function::Decode => "decode",
Function::FromUnixtime => "from_unixtime",
Function::DateFormat => "date_format",
Function::Choose => "choose",
Function::Like => "like",
Function::Ilike => "ilike",
Function::IsBool => "is_bool",
// Ternary Functions
Function::Case => "case",
Function::SubstrWithSize => "substr",
Expand Down
11 changes: 7 additions & 4 deletions src/expr/implementation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,14 @@ macro_rules! function_implementations {

// All functions:
// Nullary: Pi, Newid, CurrentDate, CurrentTime, CurrentTimestamp
// Unary: Opposite, Not, Exp, Ln, Abs, Sin, Cos, CharLength, Lower, Upper, Md5, Ceil, Floor, Sign, Dayname, Quarter, Date, UnixTimestamp
// 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, DateFormat, FromUnixtime
// Unary: Opposite, Not, Exp, Ln, Abs, Sin, Cos, CharLength, Lower, Upper, Md5, Ceil, Floor, Sign, Dayname, Quarter, Date, UnixTimestamp, IsNull
// 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, DateFormat, FromUnixtime, Like, Ilike, Choose, IsBool
// Ternary: Case, Position, DateTimeDiff
// Quaternary: RegexExtract
// Nary: Concat
function_implementations!(
[Pi, Newid, CurrentDate, CurrentTime, CurrentTimestamp],
[Opposite, Not, Exp, Ln, Log, Abs, Sin, Cos, Sqrt, Md5, Ceil, Floor, Sign, Unhex, Dayname, Quarter, Date, UnixTimestamp],
[Opposite, Not, Exp, Ln, Log, Abs, Sin, Cos, Sqrt, Md5, Ceil, Floor, Sign, Unhex, Dayname, Quarter, Date, UnixTimestamp, IsNull],
[
Plus,
Minus,
Expand Down Expand Up @@ -100,7 +100,10 @@ function_implementations!(
ExtractDow,
ExtractWeek,
DateFormat,
FromUnixtime
FromUnixtime,
Like,
Ilike,
IsBool
],
[Case, Position, SubstrWithSize, RegexpReplace, DatetimeDiff],
[RegexpExtract],
Expand Down
9 changes: 7 additions & 2 deletions src/expr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,8 @@ impl_unary_function_constructors!(
Dayname,
Quarter,
Date,
UnixTimestamp
UnixTimestamp,
IsNull
); // TODO Complete that

/// Implement binary function constructors
Expand Down Expand Up @@ -395,7 +396,11 @@ impl_binary_function_constructors!(
Encode,
Decode,
DateFormat,
FromUnixtime
FromUnixtime,
Like,
Ilike,
Choose,
IsBool
);

/// Implement ternary function constructors
Expand Down
Loading

0 comments on commit 826697f

Please sign in to comment.