Skip to content

Commit

Permalink
feat: support timestamp comparison (#580)
Browse files Browse the repository at this point in the history
Co-authored-by: mtoropygin <[email protected]>
  • Loading branch information
maksimtor and mtoropygin authored Nov 30, 2023
1 parent 57fca5d commit 3c50a4a
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## unreleased
* `parse_regex_all` `pattern` param can now be resolved from a variable
* fixed `parse_json` data corruption issue for numbers greater or equal to `i64::MAX`
* support timestamp comparison using operators <, <=, >, >=

## `0.8.0` (2023-10-31)

Expand Down
10 changes: 9 additions & 1 deletion lib/tests/tests/expressions/comparison/ge.vrl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# result: [false, true, true, false, true, true, false, true, true, false, true, true, true, true, false, "nope", "nope", "nope", "nope", "nope"]
# result: [false, true, true, false, true, true, false, true, true, false, true, true, true, true, false, false, true, true, true, false, true, "nope", "nope", "nope", "nope", "nope"]

[
1 >= 2,
Expand All @@ -21,6 +21,14 @@
"foo" >= "foo",
"bar" >= "foo",

t'2024-04-04T22:22:22.234142Z' >= t'2024-05-04T22:22:22.234142Z',
t'2024-04-04T22:22:22.234142Z' >= t'2024-04-04T22:22:22.234142Z',
t'2024-05-04T22:22:22.234142Z' >= t'2024-04-04T22:22:22.234142Z',

t'2024-04-04T22:22:22.234142+01:00' >= t'2024-04-04T22:22:22.234142+01:00',
t'2024-04-04T22:22:22.234142+03:00' >= t'2024-04-04T22:22:22.234142+01:00',
t'2024-04-04T22:22:22.234142+01:00' >= t'2024-04-04T22:22:22.234142+04:00',

# fallible
null >= 1 ?? "nope",
1 >= "bar" ?? "nope",
Expand Down
10 changes: 9 additions & 1 deletion lib/tests/tests/expressions/comparison/gt.vrl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# result: [false, true, false, true, false, true, false, true, true, false, "nope", "nope", "nope", "nope", "nope"]
# result: [false, true, false, true, false, true, false, true, true, false, false, false, true, false, false, true, "nope", "nope", "nope", "nope", "nope"]

[
1 > 2,
Expand All @@ -16,6 +16,14 @@
"foo" > "bar",
"bar" > "foo",

t'2024-04-04T22:22:22.234142Z' > t'2024-05-04T22:22:22.234142Z',
t'2024-04-04T22:22:22.234142Z' > t'2024-04-04T22:22:22.234142Z',
t'2024-05-04T22:22:22.234142Z' > t'2024-04-04T22:22:22.234142Z',

t'2024-04-04T22:22:22.234142+01:00' > t'2024-04-04T22:22:22.234142+01:00',
t'2024-04-04T22:22:22.234142+03:00' > t'2024-04-04T22:22:22.234142+01:00',
t'2024-04-04T22:22:22.234142+01:00' > t'2024-04-04T22:22:22.234142+04:00',

# fallible
null > 1 ?? "nope",
1 > "foo" ?? "nope",
Expand Down
10 changes: 9 additions & 1 deletion lib/tests/tests/expressions/comparison/le.vrl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# result: [true, false, true, true, false, true, true, false, true, true, false, true, false, true, true, "nope", "nope", "nope", "nope", "nope"]
# result: [true, false, true, true, false, true, true, false, true, true, false, true, false, true, true, true, true, false, true, true, false, "nope", "nope", "nope", "nope", "nope"]

[
1 <= 2,
Expand All @@ -21,6 +21,14 @@
"foo" <= "foo",
"bar" <= "foo",

t'2024-04-04T22:22:22.234142Z' <= t'2024-05-04T22:22:22.234142Z',
t'2024-04-04T22:22:22.234142Z' <= t'2024-04-04T22:22:22.234142Z',
t'2024-05-04T22:22:22.234142Z' <= t'2024-04-04T22:22:22.234142Z',

t'2024-04-04T22:22:22.234142+01:00' <= t'2024-04-04T22:22:22.234142+01:00',
t'2024-04-04T22:22:22.234142+03:00' <= t'2024-04-04T22:22:22.234142+01:00',
t'2024-04-04T22:22:22.234142+01:00' <= t'2024-04-04T22:22:22.234142+04:00',

# fallible
null <= 1 ?? "nope",
1 <= "foo" ?? "nope",
Expand Down
10 changes: 9 additions & 1 deletion lib/tests/tests/expressions/comparison/lt.vrl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# result: [true, false, true, false, true, false, true, false, false, true, "nope", "nope", "nope", "nope", "nope"]
# result: [true, false, true, false, true, false, true, false, false, true, true, false, false, false, true, false, "nope", "nope", "nope", "nope", "nope"]

[
1 < 2,
Expand All @@ -16,6 +16,14 @@
"foo" < "bar",
"bar" < "foo",

t'2024-04-04T22:22:22.234142Z' < t'2024-05-04T22:22:22.234142Z',
t'2024-04-04T22:22:22.234142Z' < t'2024-04-04T22:22:22.234142Z',
t'2024-05-04T22:22:22.234142Z' < t'2024-04-04T22:22:22.234142Z',

t'2024-04-04T22:22:22.234142+01:00' < t'2024-04-04T22:22:22.234142+01:00',
t'2024-04-04T22:22:22.234142+03:00' < t'2024-04-04T22:22:22.234142+01:00',
t'2024-04-04T22:22:22.234142+01:00' < t'2024-04-04T22:22:22.234142+04:00',

# fallible
null < 1 ?? "nope",
1 < "foo" ?? "nope",
Expand Down
29 changes: 28 additions & 1 deletion src/compiler/expression/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,13 @@ impl Expression for Op {
// "a" >= "a"
// "a" < "b"
// "b" <= "b"
if lhs_def.is_bytes() && rhs_def.is_bytes() {
// t'2023-05-04T22:22:22.234142Z' > t'2023-04-04T22:22:22.234142Z'
// t'2023-05-04T22:22:22.234142Z' >= t'2023-04-04T22:22:22.234142Z'
// t'2023-05-04T22:22:22.234142Z' < t'2023-04-04T22:22:22.234142Z'
// t'2023-05-04T22:22:22.234142Z' <= t'2023-04-04T22:22:22.234142Z'
if (lhs_def.is_bytes() && rhs_def.is_bytes())
|| (lhs_def.is_timestamp() && rhs_def.is_timestamp())
{
lhs_def.union(rhs_def).with_kind(K::boolean())
}
// ... > ...
Expand Down Expand Up @@ -413,6 +419,7 @@ impl DiagnosticMessage for Error {
mod tests {
use std::convert::TryInto;

use chrono::Utc;
use ordered_float::NotNan;

use ast::{
Expand Down Expand Up @@ -665,6 +672,11 @@ mod tests {
want: TypeDef::boolean().infallible(),
}

greater_timestamps {
expr: |_| op(Gt, Utc::now(), Utc::now()),
want: TypeDef::boolean().infallible(),
}

greater_other {
expr: |_| op(Gt, 1, "foo"),
want: TypeDef::boolean().fallible(),
Expand All @@ -690,6 +702,11 @@ mod tests {
want: TypeDef::boolean().infallible(),
}

greater_or_equal_timestamps {
expr: |_| op(Ge, Utc::now(), Utc::now()),
want: TypeDef::boolean().infallible(),
}

greater_or_equal_other {
expr: |_| op(Ge, 1, "foo"),
want: TypeDef::boolean().fallible(),
Expand All @@ -715,6 +732,11 @@ mod tests {
want: TypeDef::boolean().infallible(),
}

less_timestamps {
expr: |_| op(Lt, Utc::now(), Utc::now()),
want: TypeDef::boolean().infallible(),
}

less_other {
expr: |_| op(Lt, 1, "foo"),
want: TypeDef::boolean().fallible(),
Expand All @@ -740,6 +762,11 @@ mod tests {
want: TypeDef::boolean().infallible(),
}

less_or_equal_timestamps {
expr: |_| op(Le, Utc::now(), Utc::now()),
want: TypeDef::boolean().infallible(),
}

less_or_equal_other {
expr: |_| op(Le, 1, "baz"),
want: TypeDef::boolean().fallible(),
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/value/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ impl VrlValueArithmetic for Value {
Value::Integer(lhv) => (lhv > rhs.try_into_i64().map_err(|_| err())?).into(),
Value::Float(lhv) => (lhv.into_inner() > rhs.try_into_f64().map_err(|_| err())?).into(),
Value::Bytes(lhv) => (lhv > rhs.try_bytes()?).into(),
Value::Timestamp(lhv) => (lhv > rhs.try_timestamp()?).into(),
_ => return Err(err()),
};

Expand All @@ -256,6 +257,7 @@ impl VrlValueArithmetic for Value {
(lhv.into_inner() >= rhs.try_into_f64().map_err(|_| err())?).into()
}
Value::Bytes(lhv) => (lhv >= rhs.try_bytes()?).into(),
Value::Timestamp(lhv) => (lhv >= rhs.try_timestamp()?).into(),
_ => return Err(err()),
};

Expand All @@ -271,6 +273,7 @@ impl VrlValueArithmetic for Value {
Value::Integer(lhv) => (lhv < rhs.try_into_i64().map_err(|_| err())?).into(),
Value::Float(lhv) => (lhv.into_inner() < rhs.try_into_f64().map_err(|_| err())?).into(),
Value::Bytes(lhv) => (lhv < rhs.try_bytes()?).into(),
Value::Timestamp(lhv) => (lhv < rhs.try_timestamp()?).into(),
_ => return Err(err()),
};

Expand All @@ -288,6 +291,7 @@ impl VrlValueArithmetic for Value {
(lhv.into_inner() <= rhs.try_into_f64().map_err(|_| err())?).into()
}
Value::Bytes(lhv) => (lhv <= rhs.try_bytes()?).into(),
Value::Timestamp(lhv) => (lhv <= rhs.try_timestamp()?).into(),
_ => return Err(err()),
};

Expand Down

0 comments on commit 3c50a4a

Please sign in to comment.