diff --git a/src/Core/Field.cpp b/src/Core/Field.cpp index d1dc5159d8..099241a069 100644 --- a/src/Core/Field.cpp +++ b/src/Core/Field.cpp @@ -11,17 +11,27 @@ #include +using namespace std::literals; + namespace DB { + namespace ErrorCodes { extern const int CANNOT_RESTORE_FROM_FIELD_DUMP; extern const int DECIMAL_OVERFLOW; + extern const int INCORRECT_DATA; } -inline Field getBinaryValue(UInt8 type, ReadBuffer & buf) +template +T DecimalField::getScaleMultiplier() const { - switch (type) + return DecimalUtils::scaleMultiplier(scale); +} + +Field getBinaryValue(UInt8 type, ReadBuffer & buf) +{ + switch (static_cast(type)) { case Field::Types::Null: { @@ -96,7 +106,7 @@ inline Field getBinaryValue(UInt8 type, ReadBuffer & buf) case Field::Types::Array: { Array value; - readBinary(value, buf); + readBinaryArray(value, buf); return value; } case Field::Types::Tuple: @@ -131,37 +141,10 @@ inline Field getBinaryValue(UInt8 type, ReadBuffer & buf) return bool(value); } case Field::Types::Decimal32: - { - Decimal32 value; - UInt32 scale; - readBinary(value, buf); - readVarUInt(scale, buf); - return DecimalField(value, scale); - } case Field::Types::Decimal64: - { - Decimal64 value; - UInt32 scale; - readBinary(value, buf); - readVarUInt(scale, buf); - return DecimalField(value, scale); - } case Field::Types::Decimal128: - { - Decimal128 value; - UInt32 scale; - readBinary(value, buf); - readVarUInt(scale, buf); - return DecimalField(value, scale); - } case Field::Types::Decimal256: - { - Decimal256 value; - UInt32 scale; - readBinary(value, buf); - readVarUInt(scale, buf); - return DecimalField(value, scale); - } + return Field(); } throw Exception(ErrorCodes::INCORRECT_DATA, "Unknown field type {}", std::to_string(type)); } @@ -169,25 +152,19 @@ inline Field getBinaryValue(UInt8 type, ReadBuffer & buf) void readBinaryArray(Array & x, ReadBuffer & buf) { size_t size; - UInt8 type; - readBinary(type, buf); readBinary(size, buf); for (size_t index = 0; index < size; ++index) - x.push_back(getBinaryValue(type, buf)); + x.push_back(readFieldBinary(buf)); } -void writeBinary(const Array & x, WriteBuffer & buf) +void writeBinaryArray(const Array & x, WriteBuffer & buf) { - UInt8 type = Field::Types::Null; size_t size = x.size(); - if (size) - type = x.front().getType(); - writeBinary(type, buf); writeBinary(size, buf); for (const auto & elem : x) - Field::dispatch([&buf] (const auto & value) { FieldVisitorWriteBinary()(value, buf); }, elem); + writeFieldBinary(elem, buf); } void writeText(const Array & x, WriteBuffer & buf) @@ -202,11 +179,7 @@ void readBinary(Tuple & x, ReadBuffer & buf) readBinary(size, buf); for (size_t index = 0; index < size; ++index) - { - UInt8 type; - readBinary(type, buf); - x.push_back(getBinaryValue(type, buf)); - } + x.push_back(readFieldBinary(buf)); } void writeBinary(const Tuple & x, WriteBuffer & buf) @@ -215,11 +188,7 @@ void writeBinary(const Tuple & x, WriteBuffer & buf) writeBinary(size, buf); for (const auto & elem : x) - { - const UInt8 type = elem.getType(); - writeBinary(type, buf); - Field::dispatch([&buf] (const auto & value) { FieldVisitorWriteBinary()(value, buf); }, elem); - } + writeFieldBinary(elem, buf); } void writeText(const Tuple & x, WriteBuffer & buf) @@ -233,11 +202,7 @@ void readBinary(Map & x, ReadBuffer & buf) readBinary(size, buf); for (size_t index = 0; index < size; ++index) - { - UInt8 type; - readBinary(type, buf); - x.push_back(getBinaryValue(type, buf)); - } + x.push_back(readFieldBinary(buf)); } void writeBinary(const Map & x, WriteBuffer & buf) @@ -246,11 +211,7 @@ void writeBinary(const Map & x, WriteBuffer & buf) writeBinary(size, buf); for (const auto & elem : x) - { - const UInt8 type = elem.getType(); - writeBinary(type, buf); - Field::dispatch([&buf] (const auto & value) { FieldVisitorWriteBinary()(value, buf); }, elem); - } + writeFieldBinary(elem, buf); } void writeText(const Map & x, WriteBuffer & buf) @@ -328,7 +289,6 @@ void writeFieldBinary(const Field & x, WriteBuffer & buf) { const UInt8 type = x.getType(); writeBinary(type, buf); - Field::dispatch([&buf] (const auto & value) { FieldVisitorWriteBinary()(value, buf); }, x); } @@ -595,7 +555,7 @@ template bool decimalLessOrEqual(Decimal256 x, Decimal256 y, UInt32 template bool decimalLessOrEqual(DateTime64 x, DateTime64 y, UInt32 x_scale, UInt32 y_scale); -inline void writeText(const Null & x, WriteBuffer & buf) +void writeText(const Null & x, WriteBuffer & buf) { if (x.isNegativeInfinity()) writeText("-inf", buf); @@ -617,33 +577,44 @@ String toString(const Field & x) x); } -String fieldTypeToString(Field::Types::Which type) +std::string_view fieldTypeToString(Field::Types::Which type) { switch (type) { - case Field::Types::Which::Null: return "null"; - case Field::Types::Which::Array: return "array"; - case Field::Types::Which::Tuple: return "tuple"; - case Field::Types::Which::Map: return "map"; - case Field::Types::Which::Object: return "json"; - case Field::Types::Which::AggregateFunctionState: return "aggregate_function_state"; - case Field::Types::Which::Bool: return "bool"; - case Field::Types::Which::String: return "string"; - case Field::Types::Which::Decimal32: return "decimal32"; - case Field::Types::Which::Decimal64: return "decimal64"; - case Field::Types::Which::Decimal128: return "decimal128"; - case Field::Types::Which::Decimal256: return "decimal256"; - case Field::Types::Which::Float64: return "float64"; - case Field::Types::Which::Int64: return "int64"; - case Field::Types::Which::Int128: return "int128"; - case Field::Types::Which::Int256: return "int256"; - case Field::Types::Which::UInt64: return "uint64"; - case Field::Types::Which::UInt128: return "uint128"; - case Field::Types::Which::UInt256: return "uint256"; - case Field::Types::Which::UUID: return "uuid"; - case Field::Types::Which::IPv4: return "ipv4"; - case Field::Types::Which::IPv6: return "ipv6"; + case Field::Types::Which::Null: return "null"sv; + case Field::Types::Which::Array: return "array"sv; + case Field::Types::Which::Tuple: return "tuple"sv; + case Field::Types::Which::Map: return "map"sv; + case Field::Types::Which::Object: return "json"sv; + case Field::Types::Which::AggregateFunctionState: return "aggregate_function_state"sv; + case Field::Types::Which::Bool: return "bool"sv; + case Field::Types::Which::String: return "string"sv; + case Field::Types::Which::Decimal32: return "decimal32"sv; + case Field::Types::Which::Decimal64: return "decimal64"sv; + case Field::Types::Which::Decimal128: return "decimal128"sv; + case Field::Types::Which::Decimal256: return "decimal256"sv; + case Field::Types::Which::Float64: return "float64"sv; + case Field::Types::Which::Int64: return "int64"sv; + case Field::Types::Which::Int128: return "int128"sv; + case Field::Types::Which::Int256: return "int256"sv; + case Field::Types::Which::UInt64: return "uint64"sv; + case Field::Types::Which::UInt128: return "uint128"sv; + case Field::Types::Which::UInt256: return "uint256"sv; + case Field::Types::Which::UUID: return "uuid"sv; + case Field::Types::Which::IPv4: return "ipv4"sv; + case Field::Types::Which::IPv6: return "ipv6"sv; } } +/// Keep in mind, that "magic_enum" is very expensive for compiler, that's why we don't use it. +std::string_view Field::getTypeName() const +{ + return fieldTypeToString(which); +} + +template class DecimalField; +template class DecimalField; +template class DecimalField; +template class DecimalField; +template class DecimalField; } diff --git a/src/Core/Field.h b/src/Core/Field.h index 0b286095b9..976fd0e508 100644 --- a/src/Core/Field.h +++ b/src/Core/Field.h @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -117,7 +116,7 @@ class DecimalField operator T() const { return dec; } /// NOLINT T getValue() const { return dec; } - T getScaleMultiplier() const { return DecimalUtils::scaleMultiplier(scale); } + T getScaleMultiplier() const; UInt32 getScale() const { return scale; } template @@ -166,6 +165,12 @@ class DecimalField UInt32 scale; }; +extern template class DecimalField; +extern template class DecimalField; +extern template class DecimalField; +extern template class DecimalField; +extern template class DecimalField; + template constexpr bool is_decimal_field = false; template <> constexpr inline bool is_decimal_field> = true; template <> constexpr inline bool is_decimal_field> = true; @@ -414,7 +419,7 @@ class Field Types::Which getType() const { return which; } - constexpr std::string_view getTypeName() const { return magic_enum::enum_name(which); } + std::string_view getTypeName() const; bool isNull() const { return which == Types::Null; } template @@ -902,14 +907,15 @@ inline Field & Field::operator=(String && str) class ReadBuffer; class WriteBuffer; -/// It is assumed that all elements of the array have the same type. -void readBinary(Array & x, ReadBuffer & buf); -[[noreturn]] inline void readText(Array &, ReadBuffer &) { throw Exception("Cannot read array.", ErrorCodes::NOT_IMPLEMENTED); } -[[noreturn]] inline void readQuoted(Array &, ReadBuffer &) { throw Exception("Cannot read array.", ErrorCodes::NOT_IMPLEMENTED); } +/// Binary serialization of generic field. +void writeFieldBinary(const Field & x, WriteBuffer & buf); +Field readFieldBinary(ReadBuffer & buf); + +void readBinaryArray(Array & x, ReadBuffer & buf); +[[noreturn]] inline void readText(Array &, ReadBuffer &) { throw Exception(ErrorCodes::NOT_IMPLEMENTED, "Cannot read Array."); } +[[noreturn]] inline void readQuoted(Array &, ReadBuffer &) { throw Exception(ErrorCodes::NOT_IMPLEMENTED, "Cannot read Array."); } -/// It is assumed that all elements of the array have the same type. -/// Also write size and type into buf. UInt64 and Int64 is written in variadic size form -void writeBinary(const Array & x, WriteBuffer & buf); +void writeBinaryArray(const Array & x, WriteBuffer & buf); void writeText(const Array & x, WriteBuffer & buf); [[noreturn]] inline void writeQuoted(const Array &, WriteBuffer &) { throw Exception("Cannot write array quoted.", ErrorCodes::NOT_IMPLEMENTED); } @@ -957,7 +963,7 @@ void writeFieldText(const Field & x, WriteBuffer & buf); String toString(const Field & x); -String fieldTypeToString(Field::Types::Which type); +std::string_view fieldTypeToString(Field::Types::Which type); } diff --git a/src/Interpreters/ConvertStringsToEnumVisitor.cpp b/src/Interpreters/ConvertStringsToEnumVisitor.cpp index 2902c5f148..d021ed71b8 100644 --- a/src/Interpreters/ConvertStringsToEnumVisitor.cpp +++ b/src/Interpreters/ConvertStringsToEnumVisitor.cpp @@ -14,9 +14,9 @@ namespace /// @note We place strings in ascending order here under the assumption it colud speed up String to Enum conversion. String makeStringsEnum(const std::set & values) { - String enum_string = "Enum8("; + String enum_string = "enum8("; if (values.size() >= 255) - enum_string = "Enum16("; + enum_string = "enum16("; size_t number = 1; for (const auto & item : values) diff --git a/src/Interpreters/Streaming/HashJoin/HybridHashJoin/Rows.cpp b/src/Interpreters/Streaming/HashJoin/HybridHashJoin/Rows.cpp new file mode 100644 index 0000000000..6a6691f435 --- /dev/null +++ b/src/Interpreters/Streaming/HashJoin/HybridHashJoin/Rows.cpp @@ -0,0 +1,425 @@ +#include +#include +#include +#include +#include + +namespace DB::Streaming +{ + +void MutableRows::insert(Block & block, size_t row) +{ + rows.emplace_back(); + rows.back().resize(block.columns()); + + OneRow::update(block, row, rows.back()); +} + +void MutableRows::serialize(WriteBuffer & wb) const +{ + writeVarUInt(rows.size(), wb); + + if (!rows.empty()) + { + auto row_size = rows.back().size(); + writeVarUInt(row_size, wb); + + for (const auto & row : rows) + { + assert(row.size() == row_size); + for (const auto & field : row) + writeFieldBinary(field, wb); + } + } +} + +void MutableRows::deserialize(ReadBuffer & rb) +{ + uint64_t number_of_rows = 0; + readVarUInt(number_of_rows, rb); + + if (number_of_rows) + { + uint64_t row_size = 0; + readVarUInt(row_size, rb); + + for (size_t i = 0; i < number_of_rows; ++i) + { + rows.emplace_back(); + auto & current_row = rows.back(); + current_row.reserve(row_size); + for (size_t j = 0; j < row_size; ++j) + current_row.emplace_back(readFieldBinary(rb)); + } + } +} + +void RowList::insert(Block & block, size_t row) +{ + rows.emplace_back(); + rows.back().resize(block.columns()); + OneRow::update(block, row, rows.back()); +} + +void RowList::serialize(WriteBuffer & wb) const +{ + writeVarUInt(rows.size(), wb); + + if (!rows.empty()) + { + writeVarUInt(rows.front().size(), wb); + for (const auto & row : rows) + for (const auto & col : row) + writeFieldBinary(col, wb); + } +} + +void RowList::deserialize(ReadBuffer & rb) +{ + uint64_t num_rows = 0; + readVarUInt(num_rows, rb); + + if (num_rows != 0) + { + size_t row_size = 0; + readVarUInt(row_size, rb); + + for (size_t i = 0; i < num_rows; ++i) + { + rows.emplace_back(); + auto & row = rows.back(); + row.reserve(row_size); + + for (size_t j = 0; j < row_size; ++j) + row.emplace_back(readFieldBinary(rb)); + } + } +} + +AsofRows::AsofRows(TypeIndex type) +{ + auto call = [&](const auto & t) { + using T = std::decay_t; + using LookupType = typename Entry::LookupType; + lookups = std::make_unique(); + }; + + callWithType(type, call); +} + +void AsofRows::insert( + TypeIndex type, const IColumn & asof_column, Block & block, size_t row_num, ASOFJoinInequality inequality, size_t keep_versions) +{ + auto call = [&](const auto & t) { + using T = std::decay_t; + using LookupPtr = typename Entry::LookupPtr; + + auto & container = std::get(lookups); + + using ColumnType = ColumnVectorOrDecimal; + const auto & column = typeid_cast(asof_column); + + /// First insert to row list + rows.insert(block, row_num); + + T key = column.getElement(row_num); + bool ascending = (inequality == ASOFJoinInequality::Less) || (inequality == ASOFJoinInequality::LessOrEquals); + auto removed_entry = container->insert(Entry{key, RowListRef{.iter = rows.lastRowIter()}}, ascending, keep_versions); + if (removed_entry) + { + rows.remove(removed_entry->row_ref); + assert(rows.rows.size() <= keep_versions); + } + }; + + callWithType(type, call); +} + +const RowListRef * AsofRows::findAsof(TypeIndex type, ASOFJoinInequality inequality, const IColumn & asof_column, size_t row_num) const +{ + const RowListRef * out = nullptr; + + bool ascending = (inequality == ASOFJoinInequality::Less) || (inequality == ASOFJoinInequality::LessOrEquals); + bool is_strict = (inequality == ASOFJoinInequality::Less) || (inequality == ASOFJoinInequality::Greater); + + auto call = [&](const auto & t) { + using T = std::decay_t; + using EntryType = Entry; + using LookupPtr = typename EntryType::LookupPtr; + + using ColumnType = ColumnVectorOrDecimal; + const auto & column = typeid_cast(asof_column); + T key = column.getElement(row_num); + auto & typed_lookup = std::get(lookups); + + if (is_strict) + out = typed_lookup->upperBound(EntryType(key), ascending); + else + out = typed_lookup->lowerBound(EntryType(key), ascending); + }; + + callWithType(type, call); + return out; +} + +void AsofRows::serialize(WriteBuffer & wb) const +{ + /// FIXME, lookups + rows.serialize(wb); +} + +void AsofRows::deserialize(ReadBuffer & wb) +{ + /// FIXME, lookups + rows.deserialize(wb); +} + +RangeAsofRows::RangeAsofRows(TypeIndex type) +{ + auto call = [&](const auto & t) { + using T = std::decay_t; + lookups = std::make_unique>(); + }; + + callWithType(type, call); +} + +void RangeAsofRows::insert(TypeIndex type, const IColumn & asof_column, Block & block, size_t row_num) +{ + auto call = [&](const auto & t) { + using T = std::decay_t; + using ColumnType = ColumnVectorOrDecimal; + const auto & column = typeid_cast(asof_column); + + /// First save row in row list + rows.insert(block, row_num); + + T key = column.getElement(row_num); + std::get>(lookups)->emplace(key, RowListRef{.iter = rows.lastRowIter()}); + }; + + callWithType(type, call); +} + +std::vector RangeAsofRows::findRange( + TypeIndex type, const RangeAsofJoinContext & range_join_ctx, const IColumn & asof_column, size_t row_num, bool is_left_block) const +{ + std::vector results; + + auto call_for_left_block = [&](const auto & t) { + using T = std::decay_t; + using ColumnType = ColumnVectorOrDecimal; + const auto & column = typeid_cast(asof_column); + + T key = column.getElement(row_num); + + auto & m = std::get>(lookups); + + /// lower_bound [left_inequality] key - right_key [right_inequality] upper_bound + /// Example: lower_bound < key - right_key <= upper_bound + /// => -upper_bound <= right_key - key < -lower_bound + /// => key - upper_bound <= right_key < key - lower_bound + /// Find key range : [key - upper_bound, key - lower_bound) + + bool is_right_strict = range_join_ctx.right_inequality == ASOFJoinInequality::Less; + + if constexpr (is_decimal) + key -= static_cast(range_join_ctx.upper_bound); + else + key -= static_cast(range_join_ctx.upper_bound); + + decltype(m->begin()) lower_iter; + if (is_right_strict) + lower_iter = m->upper_bound(key); + else + lower_iter = m->lower_bound(key); + + if constexpr (is_decimal) + { + key += static_cast(range_join_ctx.upper_bound); /// restore + key -= static_cast(range_join_ctx.lower_bound); /// upper bound + } + else + { + key += static_cast(range_join_ctx.upper_bound); /// restore + key -= static_cast(range_join_ctx.lower_bound); /// upper bound + } + + if (lower_iter == m->end() || lower_iter->first > key) + /// all keys in the map < key - upper_bound or + /// all keys in the map > key - lower_bound + return; + + bool is_left_strict = range_join_ctx.left_inequality == ASOFJoinInequality::Greater; + + /// >= key + auto upper_iter = m->lower_bound(key); + + if (is_left_strict && upper_iter == m->begin()) + return; + + if (upper_iter == m->end() || is_left_strict || upper_iter->first > key) + /// We need back one step in these cases + --upper_iter; + + assert(upper_iter->first >= lower_iter->first); + + do + { + results.push_back(lower_iter->second); + } while (lower_iter++ != upper_iter); /// We need include value at upper_iter, so postfix lower_iter++ + }; + + auto call_for_right_block = [&](const auto & t) { + using T = std::decay_t; + using ColumnType = ColumnVectorOrDecimal; + const auto & column = typeid_cast(asof_column); + + T key = column.getElement(row_num); + + auto & m = std::get>(lookups); + + /// lower_bound [left_inequality] left_key - key [right_inequality] upper_bound + /// Example: lower_bound < left_key - key <= upper_bound + /// key + lower_bound < left_key <= key + upper_bound + /// Find key range : [key + lower_bound, key + upper_bound) + + bool is_left_strict = range_join_ctx.left_inequality == ASOFJoinInequality::Greater; + + if constexpr (is_decimal) + key += static_cast(range_join_ctx.lower_bound); + else + key += static_cast(range_join_ctx.lower_bound); + + decltype(m->begin()) lower_iter; + if (is_left_strict) + lower_iter = m->upper_bound(key); + else + lower_iter = m->lower_bound(key); + + if constexpr (is_decimal) + { + key -= static_cast(range_join_ctx.lower_bound); /// restore + key += static_cast(range_join_ctx.upper_bound); /// upper bound + } + else + { + key -= static_cast(range_join_ctx.lower_bound); /// restore + key += static_cast(range_join_ctx.upper_bound); /// upper bound + } + + if (lower_iter == m->end() || lower_iter->first > key) + /// all keys in the map < key + lower_bound or + /// all keys in the map > key + upper_bound + return; + + bool is_right_strict = range_join_ctx.right_inequality == ASOFJoinInequality::Less; + + /// >= key + auto upper_iter = m->lower_bound(key); + + if (is_right_strict && upper_iter == m->begin()) + return; + + if (upper_iter == m->end() || is_right_strict || upper_iter->first > key) + /// We need back one step in these cases + --upper_iter; + + assert(upper_iter->first >= lower_iter->first); + + do + { + results.push_back(lower_iter->second); + } while (lower_iter++ != upper_iter); /// We need include value at upper_iter, so postfix lower_iter++ + }; + + if (is_left_block) + callWithType(type, call_for_left_block); + else + callWithType(type, call_for_right_block); + return results; +} + +const RowListRef * +RangeAsofRows::findAsof(TypeIndex type, const RangeAsofJoinContext & range_join_ctx, const IColumn & asof_column, size_t row_num) const +{ + RowListRef * result = nullptr; + + auto call = [&](const auto & t) { + using T = std::decay_t; + using ColumnType = ColumnVectorOrDecimal; + const auto & column = typeid_cast(asof_column); + + T key = column.getElement(row_num); + + auto & m = std::get>(lookups); + + /// lower_bound [left_inequality] key - right_key [right_inequality] upper_bound + /// Example: lower_bound < key - right_key <= upper_bound + /// => -upper_bound <= right_key - key < -lower_bound + /// => key - upper_bound <= right_key < key - lower_bound + /// Find key range : [key - upper_bound, key - lower_bound) + + bool is_right_strict = range_join_ctx.right_inequality == ASOFJoinInequality::Less; + + if constexpr (is_decimal) + key -= static_cast(range_join_ctx.upper_bound); + else + key -= static_cast(range_join_ctx.upper_bound); + + decltype(m->begin()) lower_iter; + if (is_right_strict) + lower_iter = m->upper_bound(key); + else + lower_iter = m->lower_bound(key); + + if (lower_iter == m->end()) + /// all keys in the map < key - upper_bound + return; + + assert(lower_iter->first >= key); + + if constexpr (is_decimal) + { + key += static_cast(range_join_ctx.upper_bound); // restore + key -= static_cast(range_join_ctx.lower_bound); + } + else + { + key += static_cast(range_join_ctx.upper_bound); // restore + key -= static_cast(range_join_ctx.lower_bound); + } + + /// >= key + auto upper_iter = m->lower_bound(key); + + bool is_left_strict = range_join_ctx.left_inequality == ASOFJoinInequality::Greater; + if (is_left_strict && upper_iter == m->begin()) + return; + + if (upper_iter == m->end() || is_left_strict) + --upper_iter; + + assert(upper_iter->first <= key); + assert(upper_iter->first >= lower_iter->first); + + result = &upper_iter->second; + }; + + callWithType(type, call); + return result; +} + +void RangeAsofRows::serialize(WriteBuffer & wb) const +{ + /// FIXME, lookups + rows.serialize(wb); +} + +void RangeAsofRows::deserialize(ReadBuffer & wb) +{ + /// FIXME, lookups + rows.deserialize(wb); +} + +} diff --git a/tests/queries_ported/0_stateless/01324_if_transform_strings_to_enum.reference b/tests/queries_ported/0_stateless/01324_if_transform_strings_to_enum.reference index 558a17c995..c7332ae4d7 100644 --- a/tests/queries_ported/0_stateless/01324_if_transform_strings_to_enum.reference +++ b/tests/queries_ported/0_stateless/01324_if_transform_strings_to_enum.reference @@ -9,7 +9,7 @@ other other other SELECT - transform(number, [2, 4, 6], [\'google\', \'yandex\', \'yahoo\'], \'other\') + transform(number, [2, 4, 6], _cast([\'google\', \'yandex\', \'yahoo\'], \'array(enum8(\\\'google\\\' = 1, \\\'other\\\' = 2, \\\'yahoo\\\' = 3, \\\'yandex\\\' = 4))\'), _cast(\'other\', \'enum8(\\\'google\\\' = 1, \\\'other\\\' = 2, \\\'yahoo\\\' = 3, \\\'yandex\\\' = 4)\')) FROM system.numbers LIMIT 10 diff --git a/tests/queries_ported/0_stateless/02497_if_transform_strings_to_enum.reference b/tests/queries_ported/0_stateless/02497_if_transform_strings_to_enum.reference new file mode 100644 index 0000000000..212d31e81a --- /dev/null +++ b/tests/queries_ported/0_stateless/02497_if_transform_strings_to_enum.reference @@ -0,0 +1,195 @@ +other +other +google +other +censor.net +other +yahoo +other +other +other +SELECT + transform(number, [2, 4, 6], _cast([\'google\', \'censor.net\', \'yahoo\'], \'array(enum8(\\\'censor.net\\\' = 1, \\\'google\\\' = 2, \\\'other\\\' = 3, \\\'yahoo\\\' = 4))\'), _cast(\'other\', \'enum8(\\\'censor.net\\\' = 1, \\\'google\\\' = 2, \\\'other\\\' = 3, \\\'yahoo\\\' = 4)\')) +FROM + system.numbers +LIMIT 10 +google +google +google +google +google +google +censor.net +censor.net +censor.net +censor.net +SELECT + if(number > 5, \'censor.net\', \'google\') +FROM + system.numbers +LIMIT 10 +other1 +other1 +google1 +other1 +censor.net1 +other1 +yahoo1 +other1 +other1 +other1 +SELECT + concat(transform(number, [2, 4, 6], [\'google\', \'censor.net\', \'yahoo\'], \'other\'), \'1\') +FROM + system.numbers +LIMIT 10 +google1 +google1 +google1 +google1 +google1 +google1 +censor.net1 +censor.net1 +censor.net1 +censor.net1 +SELECT + concat(if(number > 5, \'censor.net\', \'google\'), \'1\') +FROM + system.numbers +LIMIT 10 +google +google +google +google +google +google +censor.net +censor.net +censor.net +censor.net +SELECT + t1.value +FROM + ( + SELECT + if(number > 5, \'censor.net\', \'google\') AS value + FROM + system.numbers + LIMIT 10 + ) AS t1 +other +other +google +other +censor.net +other +yahoo +other +other +other +SELECT + t1.value +FROM + ( + SELECT + transform(number, [2, 4, 6], _cast([\'google\', \'censor.net\', \'yahoo\'], \'array(enum8(\\\'censor.net\\\' = 1, \\\'google\\\' = 2, \\\'other\\\' = 3, \\\'yahoo\\\' = 4))\'), _cast(\'other\', \'enum8(\\\'censor.net\\\' = 1, \\\'google\\\' = 2, \\\'other\\\' = 3, \\\'yahoo\\\' = 4)\')) AS value + FROM + system.numbers + LIMIT 10 + ) AS t1 +google google +google google +google google +google google +google google +google google +censor.net censor.net +censor.net censor.net +censor.net censor.net +censor.net censor.net +SELECT + if(number > 5, \'censor.net\', \'google\') AS value, value +FROM + system.numbers +LIMIT 10 +other other +other other +google google +other other +censor.net censor.net +other other +yahoo yahoo +other other +other other +other other +SELECT + transform(number, [2, 4, 6], _cast([\'google\', \'censor.net\', \'yahoo\'], \'array(enum8(\\\'censor.net\\\' = 1, \\\'google\\\' = 2, \\\'other\\\' = 3, \\\'yahoo\\\' = 4))\'), _cast(\'other\', \'enum8(\\\'censor.net\\\' = 1, \\\'google\\\' = 2, \\\'other\\\' = 3, \\\'yahoo\\\' = 4)\')) AS value, value +FROM + system.numbers +LIMIT 10 +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +SELECT + transform(number, [NULL], _cast([\'google\', \'censor.net\', \'yahoo\'], \'array(enum8(\\\'censor.net\\\' = 1, \\\'google\\\' = 2, \\\'other\\\' = 3, \\\'yahoo\\\' = 4))\'), _cast(\'other\', \'enum8(\\\'censor.net\\\' = 1, \\\'google\\\' = 2, \\\'other\\\' = 3, \\\'yahoo\\\' = 4)\')) +FROM + ( + SELECT + NULL AS number + FROM + system.numbers + LIMIT 10 + ) +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +SELECT + transform(number, NULL, _cast([\'google\', \'censor.net\', \'yahoo\'], \'array(enum8(\\\'censor.net\\\' = 1, \\\'google\\\' = 2, \\\'other\\\' = 3, \\\'yahoo\\\' = 4))\'), _cast(\'other\', \'enum8(\\\'censor.net\\\' = 1, \\\'google\\\' = 2, \\\'other\\\' = 3, \\\'yahoo\\\' = 4)\')) +FROM + system.numbers +LIMIT 10 +other +other +google +other +censor.net +other +yahoo +other +other +other +SELECT + transform(number, [2, 4, 6], [\'google\', \'censor.net\', \'yahoo\'], \'other\') +FROM + system.numbers +LIMIT 10 +google +google +google +google +google +google +censor.net +censor.net +censor.net +censor.net +SELECT + if(number > 5, \'censor.net\', \'google\') +FROM + system.numbers +LIMIT 10