blob: ae3783e3de697683830a3c978fec871c6b69643c [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.
#pragma once
#include <charconv>
#include <type_traits>
#include "exec/olap_utils.h"
#include "exprs/create_predicate_function.h"
#include "exprs/hybrid_set.h"
#include "olap/bloom_filter_predicate.h"
#include "olap/column_predicate.h"
#include "olap/comparison_predicate.h"
#include "olap/in_list_predicate.h"
#include "olap/null_predicate.h"
#include "olap/tablet_schema.h"
#include "runtime/define_primitive_type.h"
#include "runtime/primitive_type.h"
#include "util/date_func.h"
#include "util/string_util.h"
namespace doris {
#include "common/compile_check_begin.h"
template <typename ConditionType>
class PredicateCreator {
public:
virtual ColumnPredicate* create(const TabletColumn& column, int index,
const ConditionType& conditions, bool opposite,
vectorized::Arena& arena) = 0;
virtual ~PredicateCreator() = default;
};
template <PrimitiveType Type, PredicateType PT, typename ConditionType>
class IntegerPredicateCreator : public PredicateCreator<ConditionType> {
public:
using CppType = typename PrimitiveTypeTraits<Type>::CppType;
ColumnPredicate* create(const TabletColumn& column, int index, const ConditionType& conditions,
bool opposite, vectorized::Arena& arena) override {
if constexpr (PredicateTypeTraits::is_list(PT)) {
return create_in_list_predicate<Type, PT, ConditionType, decltype(convert)>(
index, conditions, convert, opposite, &column, arena);
} else {
static_assert(PredicateTypeTraits::is_comparison(PT));
return new ComparisonPredicateBase<Type, PT>(index, convert(conditions), opposite);
}
}
private:
static CppType convert(const std::string& condition) {
CppType value = 0;
// because std::from_chars can't compile on macOS
if constexpr (std::is_same_v<CppType, double>) {
value = std::stod(condition, nullptr);
} else if constexpr (std::is_same_v<CppType, float>) {
value = std::stof(condition, nullptr);
} else {
std::from_chars(condition.data(), condition.data() + condition.size(), value);
}
return value;
}
};
template <PrimitiveType Type, PredicateType PT, typename ConditionType>
class DecimalPredicateCreator : public PredicateCreator<ConditionType> {
public:
using CppType = typename PrimitiveTypeTraits<Type>::CppType;
ColumnPredicate* create(const TabletColumn& column, int index, const ConditionType& conditions,
bool opposite, vectorized::Arena& arena) override {
if constexpr (PredicateTypeTraits::is_list(PT)) {
return create_in_list_predicate<Type, PT, ConditionType, decltype(convert)>(
index, conditions, convert, opposite, &column, arena);
} else {
static_assert(PredicateTypeTraits::is_comparison(PT));
return new ComparisonPredicateBase<Type, PT>(index, convert(column, conditions),
opposite);
}
}
private:
static CppType convert(const TabletColumn& column, const std::string& condition) {
StringParser::ParseResult result = StringParser::ParseResult::PARSE_SUCCESS;
// return CppType value cast from int128_t
return CppType(
StringParser::string_to_decimal<Type>(condition.data(), (int)condition.size(),
column.precision(), column.frac(), &result));
}
};
template <PrimitiveType Type, PredicateType PT, typename ConditionType>
class StringPredicateCreator : public PredicateCreator<ConditionType> {
public:
ColumnPredicate* create(const TabletColumn& column, int index, const ConditionType& conditions,
bool opposite, vectorized::Arena& arena) override {
if constexpr (PredicateTypeTraits::is_list(PT)) {
return create_in_list_predicate<Type, PT, ConditionType, decltype(convert)>(
index, conditions, convert, opposite, &column, arena);
} else {
static_assert(PredicateTypeTraits::is_comparison(PT));
return new ComparisonPredicateBase<Type, PT>(index, convert(column, conditions, arena),
opposite);
}
}
private:
static StringRef convert(const TabletColumn& column, const std::string& condition,
vectorized::Arena& arena) {
size_t length = condition.length();
if constexpr (Type == TYPE_CHAR) {
length = std::max(static_cast<size_t>(column.length()), length);
}
char* buffer = arena.alloc(length);
memset(buffer, 0, length);
memcpy(buffer, condition.data(), condition.length());
return {buffer, length};
}
};
template <PrimitiveType Type, PredicateType PT, typename ConditionType>
struct CustomPredicateCreator : public PredicateCreator<ConditionType> {
public:
using CppType = typename PrimitiveTypeTraits<Type>::CppType;
CustomPredicateCreator(const std::function<CppType(const std::string& condition)>& convert)
: _convert(convert) {}
ColumnPredicate* create(const TabletColumn& column, int index, const ConditionType& conditions,
bool opposite, vectorized::Arena& arena) override {
if constexpr (PredicateTypeTraits::is_list(PT)) {
return create_in_list_predicate<Type, PT, ConditionType, decltype(_convert)>(
index, conditions, _convert, opposite, &column, arena);
} else {
static_assert(PredicateTypeTraits::is_comparison(PT));
return new ComparisonPredicateBase<Type, PT>(index, _convert(conditions), opposite);
}
}
private:
std::function<CppType(const std::string& condition)> _convert;
};
template <PredicateType PT, typename ConditionType>
std::unique_ptr<PredicateCreator<ConditionType>> get_creator(const FieldType& type) {
switch (type) {
case FieldType::OLAP_FIELD_TYPE_TINYINT: {
return std::make_unique<IntegerPredicateCreator<TYPE_TINYINT, PT, ConditionType>>();
}
case FieldType::OLAP_FIELD_TYPE_SMALLINT: {
return std::make_unique<IntegerPredicateCreator<TYPE_SMALLINT, PT, ConditionType>>();
}
case FieldType::OLAP_FIELD_TYPE_INT: {
return std::make_unique<IntegerPredicateCreator<TYPE_INT, PT, ConditionType>>();
}
case FieldType::OLAP_FIELD_TYPE_BIGINT: {
return std::make_unique<IntegerPredicateCreator<TYPE_BIGINT, PT, ConditionType>>();
}
case FieldType::OLAP_FIELD_TYPE_LARGEINT: {
return std::make_unique<IntegerPredicateCreator<TYPE_LARGEINT, PT, ConditionType>>();
}
case FieldType::OLAP_FIELD_TYPE_FLOAT: {
return std::make_unique<IntegerPredicateCreator<TYPE_FLOAT, PT, ConditionType>>();
}
case FieldType::OLAP_FIELD_TYPE_DOUBLE: {
return std::make_unique<IntegerPredicateCreator<TYPE_DOUBLE, PT, ConditionType>>();
}
case FieldType::OLAP_FIELD_TYPE_DECIMAL: {
return std::make_unique<CustomPredicateCreator<TYPE_DECIMALV2, PT, ConditionType>>(
[](const std::string& condition) {
decimal12_t value = {0, 0};
static_cast<void>(value.from_string(condition));
// Decimal12t is storage type, we need convert to compute type here to
// do comparisons
return DecimalV2Value(value.integer, value.fraction);
});
}
case FieldType::OLAP_FIELD_TYPE_DECIMAL32: {
return std::make_unique<DecimalPredicateCreator<TYPE_DECIMAL32, PT, ConditionType>>();
}
case FieldType::OLAP_FIELD_TYPE_DECIMAL64: {
return std::make_unique<DecimalPredicateCreator<TYPE_DECIMAL64, PT, ConditionType>>();
}
case FieldType::OLAP_FIELD_TYPE_DECIMAL128I: {
return std::make_unique<DecimalPredicateCreator<TYPE_DECIMAL128I, PT, ConditionType>>();
}
case FieldType::OLAP_FIELD_TYPE_DECIMAL256: {
return std::make_unique<DecimalPredicateCreator<TYPE_DECIMAL256, PT, ConditionType>>();
}
case FieldType::OLAP_FIELD_TYPE_CHAR: {
return std::make_unique<StringPredicateCreator<TYPE_CHAR, PT, ConditionType>>();
}
case FieldType::OLAP_FIELD_TYPE_VARCHAR:
case FieldType::OLAP_FIELD_TYPE_STRING: {
return std::make_unique<StringPredicateCreator<TYPE_STRING, PT, ConditionType>>();
}
case FieldType::OLAP_FIELD_TYPE_DATE: {
return std::make_unique<CustomPredicateCreator<TYPE_DATE, PT, ConditionType>>(
timestamp_from_date);
}
case FieldType::OLAP_FIELD_TYPE_DATEV2: {
return std::make_unique<CustomPredicateCreator<TYPE_DATEV2, PT, ConditionType>>(
timestamp_from_date_v2);
}
case FieldType::OLAP_FIELD_TYPE_DATETIME: {
return std::make_unique<CustomPredicateCreator<TYPE_DATETIME, PT, ConditionType>>(
timestamp_from_datetime);
}
case FieldType::OLAP_FIELD_TYPE_DATETIMEV2: {
return std::make_unique<CustomPredicateCreator<TYPE_DATETIMEV2, PT, ConditionType>>(
timestamp_from_datetime_v2);
}
case FieldType::OLAP_FIELD_TYPE_BOOL: {
return std::make_unique<CustomPredicateCreator<TYPE_BOOLEAN, PT, ConditionType>>(
[](const std::string& condition) {
int32_t ivalue = 0;
auto result = std::from_chars(condition.data(),
condition.data() + condition.size(), ivalue);
if (result.ec == std::errc()) {
return bool(ivalue);
}
StringParser::ParseResult parse_result;
bool value = StringParser::string_to_bool(condition.data(), condition.size(),
&parse_result);
return value;
});
}
case FieldType::OLAP_FIELD_TYPE_IPV4: {
return std::make_unique<CustomPredicateCreator<TYPE_IPV4, PT, ConditionType>>(
[](const std::string& condition) {
IPv4 value;
bool res = IPv4Value::from_string(value, condition);
DCHECK(res);
return value;
});
}
case FieldType::OLAP_FIELD_TYPE_IPV6: {
return std::make_unique<CustomPredicateCreator<TYPE_IPV6, PT, ConditionType>>(
[](const std::string& condition) {
IPv6 value;
bool res = IPv6Value::from_string(value, condition);
DCHECK(res);
return value;
});
}
default:
return nullptr;
}
}
template <PredicateType PT, typename ConditionType>
ColumnPredicate* create_predicate(const TabletColumn& column, int index,
const ConditionType& conditions, bool opposite,
vectorized::Arena& arena) {
return get_creator<PT, ConditionType>(column.type())
->create(column, index, conditions, opposite, arena);
}
template <PredicateType PT>
ColumnPredicate* create_comparison_predicate(const TabletColumn& column, int index,
const std::string& condition, bool opposite,
vectorized::Arena& arena) {
static_assert(PredicateTypeTraits::is_comparison(PT));
return create_predicate<PT, std::string>(column, index, condition, opposite, arena);
}
template <PredicateType PT>
ColumnPredicate* create_list_predicate(const TabletColumn& column, int index,
const std::vector<std::string>& conditions, bool opposite,
vectorized::Arena& arena) {
static_assert(PredicateTypeTraits::is_list(PT));
return create_predicate<PT, std::vector<std::string>>(column, index, conditions, opposite,
arena);
}
// This method is called in reader and in deletehandler.
// The "column" parameter might represent a column resulting from the decomposition of a variant column.
inline ColumnPredicate* parse_to_predicate(const TabletColumn& column, uint32_t index,
const TCondition& condition, vectorized::Arena& arena,
bool opposite = false) {
if (to_lower(condition.condition_op) == "is") {
return new NullPredicate(index, to_lower(condition.condition_values[0]) == "null",
opposite);
}
if ((condition.condition_op == "*=" || condition.condition_op == "!*=") &&
condition.condition_values.size() > 1) {
decltype(create_list_predicate<PredicateType::UNKNOWN>)* create = nullptr;
if (condition.condition_op == "*=") {
create = create_list_predicate<PredicateType::IN_LIST>;
} else {
create = create_list_predicate<PredicateType::NOT_IN_LIST>;
}
return create(column, index, condition.condition_values, opposite, arena);
}
decltype(create_comparison_predicate<PredicateType::UNKNOWN>)* create = nullptr;
if (condition.condition_op == "*=" || condition.condition_op == "=") {
create = create_comparison_predicate<PredicateType::EQ>;
} else if (condition.condition_op == "!*=" || condition.condition_op == "!=") {
create = create_comparison_predicate<PredicateType::NE>;
} else if (condition.condition_op == "<<") {
create = create_comparison_predicate<PredicateType::LT>;
} else if (condition.condition_op == "<=") {
create = create_comparison_predicate<PredicateType::LE>;
} else if (condition.condition_op == ">>") {
create = create_comparison_predicate<PredicateType::GT>;
} else if (condition.condition_op == ">=") {
create = create_comparison_predicate<PredicateType::GE>;
}
return create(column, index, condition.condition_values[0], opposite, arena);
}
#include "common/compile_check_end.h"
} //namespace doris