blob: c6da060f2a3f1639dc8d30c85f91c01e803865ff [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include "util/min-max-filter.h"
#include <sstream>
#include <unordered_map>
#include "common/object-pool.h"
#include "runtime/decimal-value.inline.h"
#include "runtime/raw-value.h"
#include "runtime/string-value.inline.h"
#include "runtime/timestamp-value.inline.h"
using std::numeric_limits;
using std::stringstream;
namespace impala {
static std::unordered_map<int, string> MIN_MAX_FILTER_LLVM_CLASS_NAMES = {
{PrimitiveType::TYPE_BOOLEAN, BoolMinMaxFilter::LLVM_CLASS_NAME},
{PrimitiveType::TYPE_TINYINT, TinyIntMinMaxFilter::LLVM_CLASS_NAME},
{PrimitiveType::TYPE_SMALLINT, SmallIntMinMaxFilter::LLVM_CLASS_NAME},
{PrimitiveType::TYPE_INT, IntMinMaxFilter::LLVM_CLASS_NAME},
{PrimitiveType::TYPE_BIGINT, BigIntMinMaxFilter::LLVM_CLASS_NAME},
{PrimitiveType::TYPE_FLOAT, FloatMinMaxFilter::LLVM_CLASS_NAME},
{PrimitiveType::TYPE_DOUBLE, DoubleMinMaxFilter::LLVM_CLASS_NAME},
{PrimitiveType::TYPE_STRING, StringMinMaxFilter::LLVM_CLASS_NAME},
{PrimitiveType::TYPE_TIMESTAMP, TimestampMinMaxFilter::LLVM_CLASS_NAME},
{PrimitiveType::TYPE_DECIMAL, DecimalMinMaxFilter::LLVM_CLASS_NAME}};
static std::unordered_map<int, IRFunction::Type> MIN_MAX_FILTER_IR_FUNCTION_TYPES = {
{PrimitiveType::TYPE_BOOLEAN, IRFunction::BOOL_MIN_MAX_FILTER_INSERT},
{PrimitiveType::TYPE_TINYINT, IRFunction::TINYINT_MIN_MAX_FILTER_INSERT},
{PrimitiveType::TYPE_SMALLINT, IRFunction::SMALLINT_MIN_MAX_FILTER_INSERT},
{PrimitiveType::TYPE_INT, IRFunction::INT_MIN_MAX_FILTER_INSERT},
{PrimitiveType::TYPE_BIGINT, IRFunction::BIGINT_MIN_MAX_FILTER_INSERT},
{PrimitiveType::TYPE_FLOAT, IRFunction::FLOAT_MIN_MAX_FILTER_INSERT},
{PrimitiveType::TYPE_DOUBLE, IRFunction::DOUBLE_MIN_MAX_FILTER_INSERT},
{PrimitiveType::TYPE_STRING, IRFunction::STRING_MIN_MAX_FILTER_INSERT},
{PrimitiveType::TYPE_TIMESTAMP, IRFunction::TIMESTAMP_MIN_MAX_FILTER_INSERT}};
static std::unordered_map<int, IRFunction::Type>
DECIMAL_MIN_MAX_FILTER_IR_FUNCTION_TYPES = {
{DECIMAL_SIZE_4BYTE, IRFunction::DECIMAL_MIN_MAX_FILTER_INSERT4},
{DECIMAL_SIZE_8BYTE, IRFunction::DECIMAL_MIN_MAX_FILTER_INSERT8},
{DECIMAL_SIZE_16BYTE, IRFunction::DECIMAL_MIN_MAX_FILTER_INSERT16}};
string MinMaxFilter::GetLlvmClassName(PrimitiveType type) {
auto llvm_class = MIN_MAX_FILTER_LLVM_CLASS_NAMES.find(type);
DCHECK(llvm_class != MIN_MAX_FILTER_LLVM_CLASS_NAMES.end())
<< "Not a valid type: " << type;
return llvm_class->second;
}
IRFunction::Type MinMaxFilter::GetInsertIRFunctionType(ColumnType column_type) {
if (column_type.type != PrimitiveType::TYPE_DECIMAL) {
auto ir_function_type = MIN_MAX_FILTER_IR_FUNCTION_TYPES.find(column_type.type);
DCHECK(ir_function_type != MIN_MAX_FILTER_IR_FUNCTION_TYPES.end())
<< "Not a valid type: " << column_type.type;
return ir_function_type->second;
} else {
auto ir_function_type = DECIMAL_MIN_MAX_FILTER_IR_FUNCTION_TYPES.find(
ColumnType::GetDecimalByteSize(column_type.precision));
DCHECK(ir_function_type != DECIMAL_MIN_MAX_FILTER_IR_FUNCTION_TYPES.end())
<< "Not a valid precision: " << column_type.precision;
return ir_function_type->second;
}
}
#define NUMERIC_MIN_MAX_FILTER_FUNCS(NAME, TYPE, THRIFT_TYPE, PRIMITIVE_TYPE) \
const char* NAME##MinMaxFilter::LLVM_CLASS_NAME = \
"class.impala::" #NAME "MinMaxFilter"; \
NAME##MinMaxFilter::NAME##MinMaxFilter(const TMinMaxFilter& thrift) { \
DCHECK(!thrift.always_true); \
if (thrift.always_false) { \
min_ = numeric_limits<TYPE>::max(); \
max_ = numeric_limits<TYPE>::lowest(); \
} else { \
DCHECK(thrift.__isset.min); \
DCHECK(thrift.__isset.max); \
DCHECK(thrift.min.__isset.THRIFT_TYPE##_val); \
DCHECK(thrift.max.__isset.THRIFT_TYPE##_val); \
min_ = thrift.min.THRIFT_TYPE##_val; \
max_ = thrift.max.THRIFT_TYPE##_val; \
} \
} \
PrimitiveType NAME##MinMaxFilter::type() { \
return PrimitiveType::TYPE_##PRIMITIVE_TYPE; \
} \
void NAME##MinMaxFilter::ToThrift(TMinMaxFilter* thrift) const { \
if (!AlwaysFalse()) { \
thrift->min.__set_##THRIFT_TYPE##_val(min_); \
thrift->__isset.min = true; \
thrift->max.__set_##THRIFT_TYPE##_val(max_); \
thrift->__isset.max = true; \
} \
thrift->__set_always_false(AlwaysFalse()); \
thrift->__set_always_true(false); \
} \
string NAME##MinMaxFilter::DebugString() const { \
stringstream out; \
out << #NAME << "MinMaxFilter(min=" << min_ << ", max=" << max_ \
<< ", always_false=" << (AlwaysFalse() ? "true" : "false") << ")"; \
return out.str(); \
} \
void NAME##MinMaxFilter::Or(const TMinMaxFilter& in, TMinMaxFilter* out) { \
if (out->always_false) { \
out->min.__set_##THRIFT_TYPE##_val(in.min.THRIFT_TYPE##_val); \
out->__isset.min = true; \
out->max.__set_##THRIFT_TYPE##_val(in.max.THRIFT_TYPE##_val); \
out->__isset.max = true; \
out->__set_always_false(false); \
} else { \
out->min.__set_##THRIFT_TYPE##_val( \
std::min(in.min.THRIFT_TYPE##_val, out->min.THRIFT_TYPE##_val)); \
out->max.__set_##THRIFT_TYPE##_val( \
std::max(in.max.THRIFT_TYPE##_val, out->max.THRIFT_TYPE##_val)); \
} \
} \
void NAME##MinMaxFilter::Copy(const TMinMaxFilter& in, TMinMaxFilter* out) { \
out->min.__set_##THRIFT_TYPE##_val(in.min.THRIFT_TYPE##_val); \
out->__isset.min = true; \
out->max.__set_##THRIFT_TYPE##_val(in.max.THRIFT_TYPE##_val); \
out->__isset.max = true; \
}
NUMERIC_MIN_MAX_FILTER_FUNCS(Bool, bool, bool, BOOLEAN);
NUMERIC_MIN_MAX_FILTER_FUNCS(TinyInt, int8_t, byte, TINYINT);
NUMERIC_MIN_MAX_FILTER_FUNCS(SmallInt, int16_t, short, SMALLINT);
NUMERIC_MIN_MAX_FILTER_FUNCS(Int, int32_t, int, INT);
NUMERIC_MIN_MAX_FILTER_FUNCS(BigInt, int64_t, long, BIGINT);
NUMERIC_MIN_MAX_FILTER_FUNCS(Float, float, double, FLOAT);
NUMERIC_MIN_MAX_FILTER_FUNCS(Double, double, double, DOUBLE);
int64_t GetIntTypeMax(const ColumnType& type) {
switch (type.type) {
case TYPE_TINYINT:
return numeric_limits<int8_t>::max();
case TYPE_SMALLINT:
return numeric_limits<int16_t>::max();
case TYPE_INT:
return numeric_limits<int32_t>::max();
case TYPE_BIGINT:
return numeric_limits<int64_t>::max();
default:
DCHECK(false) << "Not an int type: " << type;
}
return -1;
}
int64_t GetIntTypeMin(const ColumnType& type) {
switch (type.type) {
case TYPE_TINYINT:
return numeric_limits<int8_t>::lowest();
case TYPE_SMALLINT:
return numeric_limits<int16_t>::lowest();
case TYPE_INT:
return numeric_limits<int32_t>::lowest();
case TYPE_BIGINT:
return numeric_limits<int64_t>::lowest();
default:
DCHECK(false) << "Not an int type: " << type;
}
return -1;
}
#define NUMERIC_MIN_MAX_FILTER_CAST(NAME) \
bool NAME##MinMaxFilter::GetCastIntMinMax( \
const ColumnType& type, int64_t* out_min, int64_t* out_max) { \
int64_t type_min = GetIntTypeMin(type); \
int64_t type_max = GetIntTypeMax(type); \
if (min_ < type_min) { \
*out_min = type_min; \
} else if (min_ > type_max) { \
return false; \
} else { \
*out_min = min_; \
} \
if (max_ > type_max) { \
*out_max = type_max; \
} else if (max_ < type_min) { \
return false; \
} else { \
*out_max = max_; \
} \
return true; \
}
NUMERIC_MIN_MAX_FILTER_CAST(TinyInt);
NUMERIC_MIN_MAX_FILTER_CAST(SmallInt);
NUMERIC_MIN_MAX_FILTER_CAST(Int);
NUMERIC_MIN_MAX_FILTER_CAST(BigInt);
#define NUMERIC_MIN_MAX_FILTER_NO_CAST(NAME) \
bool NAME##MinMaxFilter::GetCastIntMinMax( \
const ColumnType& type, int64_t* out_min, int64_t* out_max) { \
DCHECK(false) << "Casting min-max filters of type " << #NAME << " not supported."; \
return true; \
}
NUMERIC_MIN_MAX_FILTER_NO_CAST(Bool);
NUMERIC_MIN_MAX_FILTER_NO_CAST(Float);
NUMERIC_MIN_MAX_FILTER_NO_CAST(Double);
// STRING
const char* StringMinMaxFilter::LLVM_CLASS_NAME = "class.impala::StringMinMaxFilter";
const int StringMinMaxFilter::MAX_BOUND_LENGTH = 1024;
StringMinMaxFilter::StringMinMaxFilter(
const TMinMaxFilter& thrift, MemTracker* mem_tracker)
: mem_pool_(mem_tracker),
min_buffer_(&mem_pool_),
max_buffer_(&mem_pool_) {
always_false_ = thrift.always_false;
always_true_ = thrift.always_true;
if (!always_true_ && !always_false_) {
DCHECK(thrift.__isset.min);
DCHECK(thrift.__isset.max);
DCHECK(thrift.min.__isset.string_val);
DCHECK(thrift.max.__isset.string_val);
min_ = StringValue(thrift.min.string_val);
max_ = StringValue(thrift.max.string_val);
CopyToBuffer(&min_buffer_, &min_, min_.len);
CopyToBuffer(&max_buffer_, &max_, max_.len);
}
}
PrimitiveType StringMinMaxFilter::type() {
return PrimitiveType::TYPE_STRING;
}
void StringMinMaxFilter::MaterializeValues() {
if (always_true_ || always_false_) return;
if (min_buffer_.IsEmpty()) {
if (min_.len > MAX_BOUND_LENGTH) {
// Truncating 'value' gives a valid min bound as the result will be <= 'value'.
CopyToBuffer(&min_buffer_, &min_, MAX_BOUND_LENGTH);
} else {
CopyToBuffer(&min_buffer_, &min_, min_.len);
}
}
if (max_buffer_.IsEmpty()) {
if (max_.len > MAX_BOUND_LENGTH) {
CopyToBuffer(&max_buffer_, &max_, MAX_BOUND_LENGTH);
if (always_true_) return;
// After truncating 'value', to still have a valid max bound we add 1 to one char in
// the string, so that the result will be > 'value'. If the entire string is already
// the max char, then disable this filter by making it always_true.
int i = MAX_BOUND_LENGTH - 1;
while (i >= 0 && static_cast<int32_t>(max_buffer_.buffer()[i]) == -1) {
max_buffer_.buffer()[i] = max_buffer_.buffer()[i] + 1;
--i;
}
if (i == -1) {
SetAlwaysTrue();
return;
}
max_buffer_.buffer()[i] = max_buffer_.buffer()[i] + 1;
} else {
CopyToBuffer(&max_buffer_, &max_, max_.len);
}
}
}
void StringMinMaxFilter::ToThrift(TMinMaxFilter* thrift) const {
if (!always_true_ && !always_false_) {
thrift->min.string_val.assign(static_cast<char*>(min_.ptr), min_.len);
thrift->min.__isset.string_val = true;
thrift->__isset.min = true;
thrift->max.string_val.assign(static_cast<char*>(max_.ptr), max_.len);
thrift->max.__isset.string_val = true;
thrift->__isset.max = true;
}
thrift->__set_always_false(always_false_);
thrift->__set_always_true(always_true_);
}
string StringMinMaxFilter::DebugString() const {
stringstream out;
out << "StringMinMaxFilter(min=" << min_ << ", max=" << max_
<< ", always_false=" << (always_false_ ? "true" : "false")
<< ", always_true=" << (always_true_ ? "true" : "false") << ")";
return out.str();
}
void StringMinMaxFilter::Or(const TMinMaxFilter& in, TMinMaxFilter* out) {
if (out->always_false) {
out->min.__set_string_val(in.min.string_val);
out->__isset.min = true;
out->max.__set_string_val(in.max.string_val);
out->__isset.max = true;
out->__set_always_false(false);
} else {
StringValue in_min_val = StringValue(in.min.string_val);
StringValue out_min_val = StringValue(out->min.string_val);
if (in_min_val < out_min_val) out->min.__set_string_val(in.min.string_val);
StringValue in_max_val = StringValue(in.max.string_val);
StringValue out_max_val = StringValue(out->max.string_val);
if (in_max_val > out_max_val) out->max.__set_string_val(in.max.string_val);
}
}
void StringMinMaxFilter::Copy(const TMinMaxFilter& in, TMinMaxFilter* out) {
out->min.__set_string_val(in.min.string_val);
out->__isset.min = true;
out->max.__set_string_val(in.max.string_val);
out->__isset.max = true;
}
void StringMinMaxFilter::CopyToBuffer(
StringBuffer* buffer, StringValue* value, int64_t len) {
if (value->ptr == buffer->buffer()) return;
buffer->Clear();
if (!buffer->Append(value->ptr, len).ok()) {
// If Append() fails, for example because we're out of memory, disable the filter.
SetAlwaysTrue();
return;
}
value->ptr = buffer->buffer();
value->len = len;
}
void StringMinMaxFilter::SetAlwaysTrue() {
always_true_ = true;
max_buffer_.Clear();
min_buffer_.Clear();
min_.ptr = nullptr;
min_.len = 0;
max_.ptr = nullptr;
max_.len = 0;
}
// TIMESTAMP
const char* TimestampMinMaxFilter::LLVM_CLASS_NAME =
"class.impala::TimestampMinMaxFilter";
TimestampMinMaxFilter::TimestampMinMaxFilter(const TMinMaxFilter& thrift) {
always_false_ = thrift.always_false;
if (!always_false_) {
DCHECK(thrift.min.__isset.timestamp_val);
DCHECK(thrift.max.__isset.timestamp_val);
min_ = TimestampValue::FromTColumnValue(thrift.min);
max_ = TimestampValue::FromTColumnValue(thrift.max);
}
}
PrimitiveType TimestampMinMaxFilter::type() {
return PrimitiveType::TYPE_TIMESTAMP;
}
void TimestampMinMaxFilter::ToThrift(TMinMaxFilter* thrift) const {
if (!always_false_) {
min_.ToTColumnValue(&thrift->min);
thrift->__isset.min = true;
max_.ToTColumnValue(&thrift->max);
thrift->__isset.max = true;
}
thrift->__set_always_false(always_false_);
thrift->__set_always_true(false);
}
string TimestampMinMaxFilter::DebugString() const {
stringstream out;
out << "TimestampMinMaxFilter(min=" << min_ << ", max=" << max_
<< " always_false=" << (always_false_ ? "true" : "false") << ")";
return out.str();
}
void TimestampMinMaxFilter::Or(const TMinMaxFilter& in, TMinMaxFilter* out) {
if (out->always_false) {
out->min.__set_timestamp_val(in.min.timestamp_val);
out->__isset.min = true;
out->max.__set_timestamp_val(in.max.timestamp_val);
out->__isset.max = true;
out->__set_always_false(false);
} else {
TimestampValue in_min_val = TimestampValue::FromTColumnValue(in.min);
TimestampValue out_min_val = TimestampValue::FromTColumnValue(out->min);
if (in_min_val < out_min_val) out->min.__set_timestamp_val(in.min.timestamp_val);
TimestampValue in_max_val = TimestampValue::FromTColumnValue(in.max);
TimestampValue out_max_val = TimestampValue::FromTColumnValue(out->max);
if (in_max_val > out_max_val) out->max.__set_timestamp_val(in.max.timestamp_val);
}
}
void TimestampMinMaxFilter::Copy(const TMinMaxFilter& in, TMinMaxFilter* out) {
out->min.__set_timestamp_val(in.min.timestamp_val);
out->__isset.min = true;
out->max.__set_timestamp_val(in.max.timestamp_val);
out->__isset.max = true;
}
// DECIMAL
const char* DecimalMinMaxFilter::LLVM_CLASS_NAME = "class.impala::DecimalMinMaxFilter";
#define DECIMAL_SET_MINMAX(SIZE) \
do { \
DCHECK(thrift.min.__isset.decimal_val); \
DCHECK(thrift.max.__isset.decimal_val); \
min##SIZE##_ = Decimal##SIZE##Value::FromTColumnValue(thrift.min); \
max##SIZE##_ = Decimal##SIZE##Value::FromTColumnValue(thrift.max); \
} while (false)
// Construct the Decimal min-max filter when the min-max filter information
// comes in through thrift. This can get called in coordinator, after the filter
// is sent by executor
DecimalMinMaxFilter::DecimalMinMaxFilter(const TMinMaxFilter& thrift, int precision)
: size_(ColumnType::GetDecimalByteSize(precision)), always_false_(thrift.always_false) {
if (!always_false_) {
switch (size_) {
case DECIMAL_SIZE_4BYTE:
DECIMAL_SET_MINMAX(4);
break;
case DECIMAL_SIZE_8BYTE:
DECIMAL_SET_MINMAX(8);
break;
case DECIMAL_SIZE_16BYTE:
DECIMAL_SET_MINMAX(16);
break;
default:
DCHECK(false) << "DecimalMinMaxFilter: Unknown decimal byte size: " << size_;
}
}
}
PrimitiveType DecimalMinMaxFilter::type() {
return PrimitiveType::TYPE_DECIMAL;
}
#define DECIMAL_TO_THRIFT(SIZE) \
do { \
min##SIZE##_.ToTColumnValue(&thrift->min); \
max##SIZE##_.ToTColumnValue(&thrift->max); \
} while (false)
// Construct a thrift min-max filter. Will be called by the executor
// to be sent to the coordinator
void DecimalMinMaxFilter::ToThrift(TMinMaxFilter* thrift) const {
if (!always_false_) {
switch (size_) {
case DECIMAL_SIZE_4BYTE:
DECIMAL_TO_THRIFT(4);
break;
case DECIMAL_SIZE_8BYTE:
DECIMAL_TO_THRIFT(8);
break;
case DECIMAL_SIZE_16BYTE:
DECIMAL_TO_THRIFT(16);
break;
default:
DCHECK(false) << "DecimalMinMaxFilter: Unknown decimal byte size: " << size_;
}
thrift->__isset.min = true;
thrift->__isset.max = true;
}
thrift->__set_always_false(always_false_);
thrift->__set_always_true(false);
}
void DecimalMinMaxFilter::Insert(void* val) {
if (val == nullptr) return;
switch (size_) {
case 4:
Insert4(val);
break;
case 8:
Insert8(val);
break;
case 16:
Insert16(val);
break;
default:
DCHECK(false) << "Unknown decimal size: " << size_;
}
}
#define DECIMAL_DEBUG_STRING(SIZE) \
do { \
out << "DecimalMinMaxFilter(min=" << min##SIZE##_ << ", max=" << max##SIZE##_ \
<< " always_false=" << (always_false_ ? "true" : "false") << ")"; \
} while (false)
string DecimalMinMaxFilter::DebugString() const {
stringstream out;
switch (size_) {
case DECIMAL_SIZE_4BYTE:
DECIMAL_DEBUG_STRING(4);
break;
case DECIMAL_SIZE_8BYTE:
DECIMAL_DEBUG_STRING(8);
break;
case DECIMAL_SIZE_16BYTE:
DECIMAL_DEBUG_STRING(16);
break;
default:
DCHECK(false) << "DecimalMinMaxFilter: Unknown decimal byte size: " << size_;
}
return out.str();
}
#define DECIMAL_OR(SIZE) \
do { \
if (Decimal##SIZE##Value::FromTColumnValue(in.min) \
< Decimal##SIZE##Value::FromTColumnValue(out->min)) \
out->min.__set_decimal_val(in.min.decimal_val); \
if (Decimal##SIZE##Value::FromTColumnValue(in.max) \
> Decimal##SIZE##Value::FromTColumnValue(out->max)) \
out->max.__set_decimal_val(in.max.decimal_val); \
} while (false)
void DecimalMinMaxFilter::Or(const TMinMaxFilter& in, TMinMaxFilter* out, int precision) {
if (in.always_false) {
return;
} else if (out->always_false) {
out->min.__set_decimal_val(in.min.decimal_val);
out->__isset.min = true;
out->max.__set_decimal_val(in.max.decimal_val);
out->__isset.max = true;
out->__set_always_false(false);
} else {
int size = ColumnType::GetDecimalByteSize(precision);
switch (size) {
case DECIMAL_SIZE_4BYTE:
DECIMAL_OR(4);
break;
case DECIMAL_SIZE_8BYTE:
DECIMAL_OR(8);
break;
case DECIMAL_SIZE_16BYTE:
DECIMAL_OR(16);
break;
default:
DCHECK(false) << "Unknown decimal size: " << size;
}
}
}
void DecimalMinMaxFilter::Copy(const TMinMaxFilter& in, TMinMaxFilter* out) {
out->min.__set_decimal_val(in.min.decimal_val);
out->__isset.min = true;
out->max.__set_decimal_val(in.max.decimal_val);
out->__isset.max = true;
}
// MinMaxFilter
bool MinMaxFilter::GetCastIntMinMax(
const ColumnType& type, int64_t* out_min, int64_t* out_max) {
DCHECK(false) << "Casting min-max filters of type " << this->type()
<< " not supported.";
return true;
}
MinMaxFilter* MinMaxFilter::Create(
ColumnType type, ObjectPool* pool, MemTracker* mem_tracker) {
switch (type.type) {
case PrimitiveType::TYPE_BOOLEAN:
return pool->Add(new BoolMinMaxFilter());
case PrimitiveType::TYPE_TINYINT:
return pool->Add(new TinyIntMinMaxFilter());
case PrimitiveType::TYPE_SMALLINT:
return pool->Add(new SmallIntMinMaxFilter());
case PrimitiveType::TYPE_INT:
return pool->Add(new IntMinMaxFilter());
case PrimitiveType::TYPE_BIGINT:
return pool->Add(new BigIntMinMaxFilter());
case PrimitiveType::TYPE_FLOAT:
return pool->Add(new FloatMinMaxFilter());
case PrimitiveType::TYPE_DOUBLE:
return pool->Add(new DoubleMinMaxFilter());
case PrimitiveType::TYPE_STRING:
return pool->Add(new StringMinMaxFilter(mem_tracker));
case PrimitiveType::TYPE_TIMESTAMP:
return pool->Add(new TimestampMinMaxFilter());
case PrimitiveType::TYPE_DECIMAL:
return pool->Add(new DecimalMinMaxFilter(type.precision));
default:
DCHECK(false) << "Unsupported MinMaxFilter type: " << type;
}
return nullptr;
}
MinMaxFilter* MinMaxFilter::Create(const TMinMaxFilter& thrift, ColumnType type,
ObjectPool* pool, MemTracker* mem_tracker) {
switch (type.type) {
case PrimitiveType::TYPE_BOOLEAN:
return pool->Add(new BoolMinMaxFilter(thrift));
case PrimitiveType::TYPE_TINYINT:
return pool->Add(new TinyIntMinMaxFilter(thrift));
case PrimitiveType::TYPE_SMALLINT:
return pool->Add(new SmallIntMinMaxFilter(thrift));
case PrimitiveType::TYPE_INT:
return pool->Add(new IntMinMaxFilter(thrift));
case PrimitiveType::TYPE_BIGINT:
return pool->Add(new BigIntMinMaxFilter(thrift));
case PrimitiveType::TYPE_FLOAT:
return pool->Add(new FloatMinMaxFilter(thrift));
case PrimitiveType::TYPE_DOUBLE:
return pool->Add(new DoubleMinMaxFilter(thrift));
case PrimitiveType::TYPE_STRING:
return pool->Add(new StringMinMaxFilter(thrift, mem_tracker));
case PrimitiveType::TYPE_TIMESTAMP:
return pool->Add(new TimestampMinMaxFilter(thrift));
case PrimitiveType::TYPE_DECIMAL:
return pool->Add(new DecimalMinMaxFilter(thrift, type.precision));
default:
DCHECK(false) << "Unsupported MinMaxFilter type: " << type;
}
return nullptr;
}
void MinMaxFilter::Or(
const TMinMaxFilter& in, TMinMaxFilter* out, const ColumnType& columnType) {
if (in.always_false || out->always_true) return;
if (in.always_true) {
out->__set_always_true(true);
return;
}
if (in.min.__isset.bool_val) {
DCHECK(out->min.__isset.bool_val);
BoolMinMaxFilter::Or(in, out);
return;
} else if (in.min.__isset.byte_val) {
DCHECK(out->min.__isset.byte_val);
TinyIntMinMaxFilter::Or(in, out);
return;
} else if (in.min.__isset.short_val) {
DCHECK(out->min.__isset.short_val);
SmallIntMinMaxFilter::Or(in, out);
return;
} else if (in.min.__isset.int_val) {
DCHECK(out->min.__isset.int_val);
IntMinMaxFilter::Or(in, out);
return;
} else if (in.min.__isset.long_val) {
DCHECK(out->min.__isset.long_val);
BigIntMinMaxFilter::Or(in, out);
return;
} else if (in.min.__isset.double_val) {
// Handles FloatMinMaxFilter also as TColumnValue doesn't have a float type.
DCHECK(out->min.__isset.double_val);
DoubleMinMaxFilter::Or(in, out);
return;
} else if (in.min.__isset.string_val) {
DCHECK(out->min.__isset.string_val);
StringMinMaxFilter::Or(in, out);
return;
} else if (in.min.__isset.timestamp_val) {
DCHECK(out->min.__isset.timestamp_val);
TimestampMinMaxFilter::Or(in, out);
return;
} else if (in.min.__isset.decimal_val) {
DCHECK(out->min.__isset.decimal_val);
DecimalMinMaxFilter::Or(in, out, columnType.precision);
return;
}
DCHECK(false) << "Unsupported MinMaxFilter type.";
}
void MinMaxFilter::Copy(const TMinMaxFilter& in, TMinMaxFilter* out) {
out->__set_always_false(in.always_false);
out->__set_always_true(in.always_true);
if (in.always_false || in.always_true) return;
if (in.min.__isset.bool_val) {
DCHECK(!out->min.__isset.bool_val);
BoolMinMaxFilter::Copy(in, out);
return;
} else if (in.min.__isset.byte_val) {
DCHECK(!out->min.__isset.byte_val);
TinyIntMinMaxFilter::Copy(in, out);
return;
} else if (in.min.__isset.short_val) {
DCHECK(!out->min.__isset.short_val);
SmallIntMinMaxFilter::Copy(in, out);
return;
} else if (in.min.__isset.int_val) {
DCHECK(!out->min.__isset.int_val);
IntMinMaxFilter::Copy(in, out);
return;
} else if (in.min.__isset.long_val) {
// Handles TimestampMinMaxFilter also as TColumnValue doesn't have a timestamp type.
DCHECK(!out->min.__isset.long_val);
BigIntMinMaxFilter::Copy(in, out);
return;
} else if (in.min.__isset.double_val) {
// Handles FloatMinMaxFilter also as TColumnValue doesn't have a float type.
DCHECK(!out->min.__isset.double_val);
DoubleMinMaxFilter::Copy(in, out);
return;
} else if (in.min.__isset.string_val) {
DCHECK(!out->min.__isset.string_val);
StringMinMaxFilter::Copy(in, out);
return;
} else if (in.min.__isset.timestamp_val) {
DCHECK(!out->min.__isset.timestamp_val);
TimestampMinMaxFilter::Copy(in, out);
return;
} else if (in.min.__isset.decimal_val) {
DCHECK(!out->min.__isset.decimal_val);
DecimalMinMaxFilter::Copy(in, out);
return;
}
DCHECK(false) << "Unsupported MinMaxFilter type.";
}
} // namespace impala