in c++/src/sargs/PredicateLeaf.cc [508:605]
TruthValue PredicateLeaf::evaluatePredicateMinMax(const proto::ColumnStatistics& colStats) const {
TruthValue result = TruthValue::YES_NO_NULL;
switch (type_) {
case PredicateDataType::LONG: {
if (colStats.has_int_statistics() && colStats.int_statistics().has_minimum() &&
colStats.int_statistics().has_maximum()) {
const auto& stats = colStats.int_statistics();
result = evaluatePredicateRange(operator_, literal2Long(literals_), stats.minimum(),
stats.maximum(), colStats.has_null());
}
break;
}
case PredicateDataType::FLOAT: {
if (colStats.has_double_statistics() && colStats.double_statistics().has_minimum() &&
colStats.double_statistics().has_maximum()) {
const auto& stats = colStats.double_statistics();
if (!std::isfinite(stats.sum())) {
result = colStats.has_null() ? TruthValue::YES_NO_NULL : TruthValue::YES_NO;
} else {
result = evaluatePredicateRange(operator_, literal2Double(literals_), stats.minimum(),
stats.maximum(), colStats.has_null());
}
}
break;
}
case PredicateDataType::STRING: {
/// TODO: check lowerBound and upperBound as well
if (colStats.has_string_statistics() && colStats.string_statistics().has_minimum() &&
colStats.string_statistics().has_maximum()) {
const auto& stats = colStats.string_statistics();
result = evaluatePredicateRange(operator_, literal2String(literals_), stats.minimum(),
stats.maximum(), colStats.has_null());
}
break;
}
case PredicateDataType::DATE: {
if (colStats.has_date_statistics() && colStats.date_statistics().has_minimum() &&
colStats.date_statistics().has_maximum()) {
const auto& stats = colStats.date_statistics();
result = evaluatePredicateRange(operator_, literal2Date(literals_), stats.minimum(),
stats.maximum(), colStats.has_null());
}
break;
}
case PredicateDataType::TIMESTAMP: {
if (colStats.has_timestamp_statistics() &&
colStats.timestamp_statistics().has_minimum_utc() &&
colStats.timestamp_statistics().has_maximum_utc()) {
const auto& stats = colStats.timestamp_statistics();
constexpr int32_t DEFAULT_MIN_NANOS = 0;
constexpr int32_t DEFAULT_MAX_NANOS = 999999;
int32_t minNano =
stats.has_minimum_nanos() ? stats.minimum_nanos() - 1 : DEFAULT_MIN_NANOS;
int32_t maxNano =
stats.has_maximum_nanos() ? stats.maximum_nanos() - 1 : DEFAULT_MAX_NANOS;
Literal::Timestamp minTimestamp(
stats.minimum_utc() / 1000,
static_cast<int32_t>((stats.minimum_utc() % 1000) * 1000000) + minNano);
Literal::Timestamp maxTimestamp(
stats.maximum_utc() / 1000,
static_cast<int32_t>((stats.maximum_utc() % 1000) * 1000000) + maxNano);
result = evaluatePredicateRange(operator_, literal2Timestamp(literals_), minTimestamp,
maxTimestamp, colStats.has_null());
}
break;
}
case PredicateDataType::DECIMAL: {
if (colStats.has_decimal_statistics() && colStats.decimal_statistics().has_minimum() &&
colStats.decimal_statistics().has_maximum()) {
const auto& stats = colStats.decimal_statistics();
result = evaluatePredicateRange(operator_, literal2Decimal(literals_),
Decimal(stats.minimum()), Decimal(stats.maximum()),
colStats.has_null());
}
break;
}
case PredicateDataType::BOOLEAN: {
if (colStats.has_bucket_statistics()) {
result = evaluateBoolPredicate(operator_, literals_, colStats);
}
break;
}
default:
break;
}
// make sure null literal is respected for IN operator
if (operator_ == Operator::IN && colStats.has_null()) {
for (const auto& literal : literals_) {
if (literal.isNull()) {
result = TruthValue::YES_NO_NULL;
break;
}
}
}
return result;
}