in crates/iceberg/src/expr/predicate.rs [325:492]
fn bind(&self, schema: SchemaRef, case_sensitive: bool) -> Result<BoundPredicate> {
match self {
Predicate::And(expr) => {
let bound_expr = expr.bind(schema, case_sensitive)?;
let [left, right] = bound_expr.inputs;
Ok(match (left, right) {
(_, r) if matches!(&*r, &BoundPredicate::AlwaysFalse) => {
BoundPredicate::AlwaysFalse
}
(l, _) if matches!(&*l, &BoundPredicate::AlwaysFalse) => {
BoundPredicate::AlwaysFalse
}
(left, r) if matches!(&*r, &BoundPredicate::AlwaysTrue) => *left,
(l, right) if matches!(&*l, &BoundPredicate::AlwaysTrue) => *right,
(left, right) => BoundPredicate::And(LogicalExpression::new([left, right])),
})
}
Predicate::Not(expr) => {
let bound_expr = expr.bind(schema, case_sensitive)?;
let [inner] = bound_expr.inputs;
Ok(match inner {
e if matches!(&*e, &BoundPredicate::AlwaysTrue) => BoundPredicate::AlwaysFalse,
e if matches!(&*e, &BoundPredicate::AlwaysFalse) => BoundPredicate::AlwaysTrue,
e => BoundPredicate::Not(LogicalExpression::new([e])),
})
}
Predicate::Or(expr) => {
let bound_expr = expr.bind(schema, case_sensitive)?;
let [left, right] = bound_expr.inputs;
Ok(match (left, right) {
(l, r)
if matches!(&*r, &BoundPredicate::AlwaysTrue)
|| matches!(&*l, &BoundPredicate::AlwaysTrue) =>
{
BoundPredicate::AlwaysTrue
}
(left, r) if matches!(&*r, &BoundPredicate::AlwaysFalse) => *left,
(l, right) if matches!(&*l, &BoundPredicate::AlwaysFalse) => *right,
(left, right) => BoundPredicate::Or(LogicalExpression::new([left, right])),
})
}
Predicate::Unary(expr) => {
let bound_expr = expr.bind(schema, case_sensitive)?;
match &bound_expr.op {
&PredicateOperator::IsNull => {
if bound_expr.term.field().required {
return Ok(BoundPredicate::AlwaysFalse);
}
}
&PredicateOperator::NotNull => {
if bound_expr.term.field().required {
return Ok(BoundPredicate::AlwaysTrue);
}
}
&PredicateOperator::IsNan | &PredicateOperator::NotNan => {
if !bound_expr.term.field().field_type.is_floating_type() {
return Err(Error::new(
ErrorKind::DataInvalid,
format!(
"Expecting floating point type, but found {}",
bound_expr.term.field().field_type
),
));
}
}
op => {
return Err(Error::new(
ErrorKind::Unexpected,
format!("Expecting unary operator, but found {op}"),
))
}
}
Ok(BoundPredicate::Unary(bound_expr))
}
Predicate::Binary(expr) => {
let bound_expr = expr.bind(schema, case_sensitive)?;
let bound_literal = bound_expr.literal.to(&bound_expr.term.field().field_type)?;
match bound_literal.literal() {
PrimitiveLiteral::AboveMax => match &bound_expr.op {
&PredicateOperator::LessThan
| &PredicateOperator::LessThanOrEq
| &PredicateOperator::NotEq => {
return Ok(BoundPredicate::AlwaysTrue);
}
&PredicateOperator::GreaterThan
| &PredicateOperator::GreaterThanOrEq
| &PredicateOperator::Eq => {
return Ok(BoundPredicate::AlwaysFalse);
}
_ => {}
},
PrimitiveLiteral::BelowMin => match &bound_expr.op {
&PredicateOperator::GreaterThan
| &PredicateOperator::GreaterThanOrEq
| &PredicateOperator::NotEq => {
return Ok(BoundPredicate::AlwaysTrue);
}
&PredicateOperator::LessThan
| &PredicateOperator::LessThanOrEq
| &PredicateOperator::Eq => {
return Ok(BoundPredicate::AlwaysFalse);
}
_ => {}
},
_ => {}
}
Ok(BoundPredicate::Binary(BinaryExpression::new(
bound_expr.op,
bound_expr.term,
bound_literal,
)))
}
Predicate::Set(expr) => {
let bound_expr = expr.bind(schema, case_sensitive)?;
let bound_literals = bound_expr
.literals
.into_iter()
.map(|l| l.to(&bound_expr.term.field().field_type))
.collect::<Result<FnvHashSet<Datum>>>()?;
match &bound_expr.op {
&PredicateOperator::In => {
if bound_literals.is_empty() {
return Ok(BoundPredicate::AlwaysFalse);
}
if bound_literals.len() == 1 {
return Ok(BoundPredicate::Binary(BinaryExpression::new(
PredicateOperator::Eq,
bound_expr.term,
bound_literals.into_iter().next().unwrap(),
)));
}
}
&PredicateOperator::NotIn => {
if bound_literals.is_empty() {
return Ok(BoundPredicate::AlwaysTrue);
}
if bound_literals.len() == 1 {
return Ok(BoundPredicate::Binary(BinaryExpression::new(
PredicateOperator::NotEq,
bound_expr.term,
bound_literals.into_iter().next().unwrap(),
)));
}
}
op => {
return Err(Error::new(
ErrorKind::Unexpected,
format!("Expecting unary operator,but found {op}"),
))
}
}
Ok(BoundPredicate::Set(SetExpression::new(
bound_expr.op,
bound_expr.term,
bound_literals,
)))
}
Predicate::AlwaysTrue => Ok(BoundPredicate::AlwaysTrue),
Predicate::AlwaysFalse => Ok(BoundPredicate::AlwaysFalse),
}
}