in c++/src/sargs/PredicateLeaf.cc [305:389]
TruthValue evaluatePredicateRange(const PredicateLeaf::Operator op, const std::vector<T>& values,
const T& minValue, const T& maxValue, bool hasNull) {
Location loc;
switch (op) {
case PredicateLeaf::Operator::NULL_SAFE_EQUALS:
loc = compareToRange(values.at(0), minValue, maxValue);
if (loc == Location::BEFORE || loc == Location::AFTER) {
return TruthValue::NO;
} else {
return TruthValue::YES_NO;
}
case PredicateLeaf::Operator::EQUALS:
loc = compareToRange(values.at(0), minValue, maxValue);
if (minValue == maxValue && loc == Location::MIN) {
return hasNull ? TruthValue::YES_NULL : TruthValue::YES;
} else if (loc == Location::BEFORE || loc == Location::AFTER) {
return hasNull ? TruthValue::NO_NULL : TruthValue::NO;
} else {
return hasNull ? TruthValue::YES_NO_NULL : TruthValue::YES_NO;
}
case PredicateLeaf::Operator::LESS_THAN:
loc = compareToRange(values.at(0), minValue, maxValue);
if (loc == Location::AFTER) {
return hasNull ? TruthValue::YES_NULL : TruthValue::YES;
} else if (loc == Location::BEFORE || loc == Location::MIN) {
return hasNull ? TruthValue::NO_NULL : TruthValue::NO;
} else {
return hasNull ? TruthValue::YES_NO_NULL : TruthValue::YES_NO;
}
case PredicateLeaf::Operator::LESS_THAN_EQUALS:
loc = compareToRange(values.at(0), minValue, maxValue);
if (loc == Location::AFTER || loc == Location::MAX ||
(loc == Location::MIN && minValue == maxValue)) {
return hasNull ? TruthValue::YES_NULL : TruthValue::YES;
} else if (loc == Location::BEFORE) {
return hasNull ? TruthValue::NO_NULL : TruthValue::NO;
} else {
return hasNull ? TruthValue::YES_NO_NULL : TruthValue::YES_NO;
}
case PredicateLeaf::Operator::IN:
if (minValue == maxValue) {
// for a single value, look through to see if that value is in the set
for (auto& value : values) {
loc = compareToRange(value, minValue, maxValue);
if (loc == Location::MIN) {
return hasNull ? TruthValue::YES_NULL : TruthValue::YES;
}
}
return hasNull ? TruthValue::NO_NULL : TruthValue::NO;
} else {
// are all of the values outside of the range?
for (auto& value : values) {
loc = compareToRange(value, minValue, maxValue);
if (loc == Location::MIN || loc == Location::MIDDLE || loc == Location::MAX) {
return hasNull ? TruthValue::YES_NO_NULL : TruthValue::YES_NO;
}
}
return hasNull ? TruthValue::NO_NULL : TruthValue::NO;
}
case PredicateLeaf::Operator::BETWEEN:
if (values.empty()) {
return TruthValue::YES_NO;
}
loc = compareToRange(values.at(0), minValue, maxValue);
if (loc == Location::BEFORE || loc == Location::MIN) {
Location loc2 = compareToRange(values.at(1), minValue, maxValue);
if (loc2 == Location::AFTER || loc2 == Location::MAX) {
return hasNull ? TruthValue::YES_NULL : TruthValue::YES;
} else if (loc2 == Location::BEFORE) {
return hasNull ? TruthValue::NO_NULL : TruthValue::NO;
} else {
return hasNull ? TruthValue::YES_NO_NULL : TruthValue::YES_NO;
}
} else if (loc == Location::AFTER) {
return hasNull ? TruthValue::NO_NULL : TruthValue::NO;
} else {
return hasNull ? TruthValue::YES_NO_NULL : TruthValue::YES_NO;
}
case PredicateLeaf::Operator::IS_NULL:
// min = null condition above handles the all-nulls YES case
return hasNull ? TruthValue::YES_NO : TruthValue::NO;
default:
return hasNull ? TruthValue::YES_NO_NULL : TruthValue::YES_NO;
}
}