Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enhancement(remap): improved type definitions for or with nullable fields #6462

Merged
merged 3 commits into from
Feb 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 43 additions & 8 deletions lib/vrl/compiler/src/expression/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,15 @@ impl Expression for Op {
// null || ...
Or if lhs_kind.is_null() => rhs_def,

// "foo" || ...
Or if !lhs_kind.is_boolean() => lhs_def,
// not null || ...
Or if !lhs_kind.contains(K::Null) => lhs_def,

// ... || ...
Or if !lhs_kind.is_boolean() => {
// We can remove Null from the lhs since we know that if the lhs is Null
// we will be taking the rhs and only the rhs type_def will then be relevant.
(lhs_def - K::Null).merge(rhs_def)
}

// ... || ...
Or => merged_def,
Expand Down Expand Up @@ -224,7 +231,7 @@ impl DiagnosticError for Error {
#[cfg(test)]
mod tests {
use super::*;
use crate::expression::Literal;
use crate::expression::{Block, IfStatement, Literal, Predicate};
use crate::{test_type_def, value::Kind};
use ast::Opcode::*;
use ordered_float::NotNan;
Expand Down Expand Up @@ -329,17 +336,17 @@ mod tests {

add_other {
expr: |_| op(Add, (), ()),
want: TypeDef::new().fallible().scalar(Kind::Bytes | Kind::Integer | Kind::Float),
want: TypeDef::new().fallible().bytes().add_integer().add_float(),
}

remainder {
expr: |_| op(Rem, (), ()),
want: TypeDef::new().fallible().scalar(Kind::Integer | Kind::Float),
want: TypeDef::new().fallible().integer().add_float(),
}

subtract {
expr: |_| op(Sub, (), ()),
want: TypeDef::new().fallible().scalar(Kind::Integer | Kind::Float),
want: TypeDef::new().fallible().integer().add_float(),
}

divide {
Expand Down Expand Up @@ -406,7 +413,7 @@ mod tests {
rhs: Box::new(Literal::from(true).into()),
opcode: Err,
},
want: TypeDef::new().scalar(Kind::Float | Kind::Boolean),
want: TypeDef::new().float().add_boolean(),
}

error_or_fallible {
Expand Down Expand Up @@ -444,7 +451,35 @@ mod tests {
}.into()),
opcode: Err,
},
want: TypeDef::new().scalar(Kind::Float | Kind::Bytes),
want: TypeDef::new().float().add_bytes(),
}

or_nullable {
expr: |_| Op {
lhs: Box::new(
IfStatement {
predicate: Predicate::new_unchecked(vec![Literal::from(true).into()]),
consequent: Block::new(vec![Literal::from("string").into()]),
alternative: None,
}.into()),
rhs: Box::new(Literal::from("another string").into()),
opcode: Or,
},
want: TypeDef::new().bytes(),
}

or_not_nullable {
expr: |_| Op {
lhs: Box::new(
IfStatement {
predicate: Predicate::new_unchecked(vec![Literal::from(true).into()]),
consequent: Block::new(vec![Literal::from("string").into()]),
alternative: Some(Block::new(vec![Literal::from(42).into()]))
}.into()),
rhs: Box::new(Literal::from("another string").into()),
opcode: Or,
},
want: TypeDef::new().bytes().add_integer(),
}
];
}
21 changes: 20 additions & 1 deletion lib/vrl/compiler/src/type_def.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::value::Kind;
use crate::{map, path, Path};
use std::collections::{BTreeMap, BTreeSet};
use std::{
collections::{BTreeMap, BTreeSet},
ops::Sub,
};

/// Properties for a given expression that express the expected outcome of the
/// expression.
Expand All @@ -19,6 +22,22 @@ pub struct TypeDef {
kind: KindInfo,
}

impl Sub<Kind> for TypeDef {
type Output = Self;

/// Removes the given kinds from this type definition.
fn sub(mut self, other: Kind) -> Self::Output {
self.kind = match self.kind {
KindInfo::Unknown => KindInfo::Unknown,
KindInfo::Known(kinds) => {
KindInfo::Known(kinds.into_iter().filter(|k| k.to_kind() != other).collect())
}
};

self
}
}

#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
enum KindInfo {
Unknown,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
.message = to_string!(.message)
result = parse_syslog!(.message)
sha = sha3(value: result.message)
sha + (result.appname || "<no app name>") ?? ""
sha + (result.appname || "<no app name>")