diff --git a/src/Core/AccurateComparison.h b/src/Core/AccurateComparison.h index 500346872db..4fecab5b5f7 100644 --- a/src/Core/AccurateComparison.h +++ b/src/Core/AccurateComparison.h @@ -515,15 +515,23 @@ inline bool NO_SANITIZE_UNDEFINED convertNumeric(From value, To & result) return true; } - /// Note that NaNs doesn't compare equal to anything, but they are still in range of any Float type. - if (isNaN(value) && std::is_floating_point_v) + if constexpr (std::is_floating_point_v && std::is_floating_point_v) { + /// Note that NaNs doesn't compare equal to anything, but they are still in range of any Float type. + if (isNaN(value)) + { + result = value; + return true; + } + } + + if (accurate::greaterOp(value, std::numeric_limits::max()) + || accurate::greaterOp(std::numeric_limits::min(), value)) { - result = value; - return true; + return false; } result = static_cast(value); - return equalsOp(value, result); + return true; } } diff --git a/src/Functions/FunctionsConversion.h b/src/Functions/FunctionsConversion.h index 78bf586a32c..6a6be30ba0f 100644 --- a/src/Functions/FunctionsConversion.h +++ b/src/Functions/FunctionsConversion.h @@ -2897,8 +2897,6 @@ public: ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {1}; } -protected: - FunctionBaseImplPtr build(const ColumnsWithTypeAndName & arguments, const DataTypePtr & return_type) const override { DataTypes data_types(arguments.size()); @@ -2909,7 +2907,7 @@ protected: auto monotonicity = MonotonicityHelper::getMonotonicityInformation(arguments.front().type, return_type.get()); return std::make_unique(name, std::move(monotonicity), data_types, return_type, std::optional(), true); } - +protected: DataTypePtr getReturnType(const ColumnsWithTypeAndName & arguments) const override { const auto & column = arguments.back().column; diff --git a/src/Interpreters/Set.cpp b/src/Interpreters/Set.cpp index 08e6107590e..6437a0bc063 100644 --- a/src/Interpreters/Set.cpp +++ b/src/Interpreters/Set.cpp @@ -14,6 +14,8 @@ #include #include +#include + #include #include #include @@ -30,6 +32,7 @@ #include #include +#include namespace DB { @@ -254,8 +257,15 @@ ColumnPtr Set::execute(const Block & block, bool negative) const for (size_t i = 0; i < num_key_columns; ++i) { - checkTypesEqual(i, block.safeGetByPosition(i).type); - materialized_columns.emplace_back(block.safeGetByPosition(i).column->convertToFullColumnIfConst()); + /// TODO: Optimize making cast only if types different + /// TODO: This case SELECT '1' IN (SELECT 1); should not work but with AccurateCastOrNull it works + auto & column_before_cast = block.safeGetByPosition(i); + ColumnWithTypeAndName column + = {column_before_cast.column->convertToFullColumnIfConst(), column_before_cast.type, column_before_cast.name}; + auto accurate_cast = AccurateCastOverloadResolver().build({column}, data_types[i]); + auto accurate_cast_executable = accurate_cast->prepare({column}); + auto casted_column = accurate_cast_executable->execute({column}, data_types[i], column.column->size()); + materialized_columns.emplace_back() = casted_column; key_columns.emplace_back() = materialized_columns.back().get(); } diff --git a/src/Storages/MergeTree/KeyCondition.cpp b/src/Storages/MergeTree/KeyCondition.cpp index 5903dc89e9b..e0256e99657 100644 --- a/src/Storages/MergeTree/KeyCondition.cpp +++ b/src/Storages/MergeTree/KeyCondition.cpp @@ -825,6 +825,8 @@ bool KeyCondition::tryPrepareSetIndex( const ASTPtr & right_arg = args[1]; + /// TODO: Check this place after cast introduced in Set + SetPtr prepared_set; if (right_arg->as() || right_arg->as()) { diff --git a/tests/queries/0_stateless/01600_select_in_different_types.reference b/tests/queries/0_stateless/01600_select_in_different_types.reference new file mode 100644 index 00000000000..b8e54f07240 --- /dev/null +++ b/tests/queries/0_stateless/01600_select_in_different_types.reference @@ -0,0 +1,6 @@ +1 +1 +2 +2 +1 +1 diff --git a/tests/queries/0_stateless/01600_select_in_different_types.sql b/tests/queries/0_stateless/01600_select_in_different_types.sql new file mode 100644 index 00000000000..d39a6896d59 --- /dev/null +++ b/tests/queries/0_stateless/01600_select_in_different_types.sql @@ -0,0 +1,28 @@ +-- SELECT 1 IN (SELECT -1) +-- SELECT -1 IN (SELECT 1) + +CREATE TABLE select_in_test(value UInt8) ENGINE=TinyLog; +INSERT INTO select_in_test VALUES (1), (2), (3); + +SELECT value FROM select_in_test WHERE value IN (-1); +SELECT value FROM select_in_test WHERE value IN (SELECT -1); + +SELECT value FROM select_in_test WHERE value IN (1); +SELECT value FROM select_in_test WHERE value IN (SELECT 1); + +DROP TABLE select_in_test; + +CREATE TABLE select_in_test(value Int8) ENGINE=TinyLog; +INSERT INTO select_in_test VALUES (-1), (2), (3); + +SELECT value FROM select_in_test WHERE value IN (1); +SELECT value FROM select_in_test WHERE value IN (SELECT 1); + +SELECT value FROM select_in_test WHERE value IN (2); +SELECT value FROM select_in_test WHERE value IN (SELECT 2); + +DROP TABLE select_in_test; + +SELECT 1 IN (1); +-- Right now this working because of accurate cast. Need to discuss. +SELECT '1' IN (SELECT 1);