diff --git a/src/Functions/FunctionBinaryArithmetic.h b/src/Functions/FunctionBinaryArithmetic.h index 1c625d84ac6..b951fe89c5f 100644 --- a/src/Functions/FunctionBinaryArithmetic.h +++ b/src/Functions/FunctionBinaryArithmetic.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -107,6 +108,9 @@ template constexpr bool IsDateOrDateTime = false; template <> inline constexpr bool IsDateOrDateTime = true; template <> inline constexpr bool IsDateOrDateTime = true; +template constexpr bool IsIPv4 = false; +template <> inline constexpr bool IsIPv4 = true; + template constexpr bool UseLeftDecimal = false; template <> inline constexpr bool UseLeftDecimal, DataTypeDecimal> = true; template <> inline constexpr bool UseLeftDecimal, DataTypeDecimal> = true; @@ -1210,6 +1214,17 @@ public: return arguments[0]; } + /// Special case - one or both arguments are IPv4 + if (isIPv4(arguments[0]) || isIPv4(arguments[1])) + { + DataTypes new_arguments { + isIPv4(arguments[0]) ? std::make_shared() : arguments[0], + isIPv4(arguments[1]) ? std::make_shared() : arguments[1], + }; + + return getReturnTypeImplStatic(new_arguments, context); + } + /// Special case when the function is plus or minus, one of arguments is Date/DateTime and another is Interval. if (auto function_builder = getFunctionForIntervalArithmetic(arguments[0], arguments[1], context)) { @@ -1707,6 +1722,25 @@ public: return executeAggregateAddition(arguments, result_type, input_rows_count); } + /// Special case - one or both arguments are IPv4 + if (isIPv4(arguments[0].type) || isIPv4(arguments[1].type)) + { + ColumnsWithTypeAndName new_arguments { + { + isIPv4(arguments[0].type) ? castColumn(arguments[0], std::make_shared()) : arguments[0].column, + isIPv4(arguments[0].type) ? std::make_shared() : arguments[0].type, + arguments[0].name, + }, + { + isIPv4(arguments[1].type) ? castColumn(arguments[1], std::make_shared()) : arguments[1].column, + isIPv4(arguments[1].type) ? std::make_shared() : arguments[1].type, + arguments[1].name + } + }; + + return executeImpl(new_arguments, result_type, input_rows_count); + } + /// Special case when the function is plus or minus, one of arguments is Date/DateTime and another is Interval. if (auto function_builder = getFunctionForIntervalArithmetic(arguments[0].type, arguments[1].type, context)) { diff --git a/tests/queries/0_stateless/02531_ipv4_arithmetic.reference b/tests/queries/0_stateless/02531_ipv4_arithmetic.reference new file mode 100644 index 00000000000..6f03e4e6903 --- /dev/null +++ b/tests/queries/0_stateless/02531_ipv4_arithmetic.reference @@ -0,0 +1,20 @@ +10 1.2.3.4 0 +11 1.2.3.4 3 +12 1.2.3.4 4 +13 1.2.3.4 12 +14 1.2.3.4 0 +15 1.2.3.4 10 +16 1.2.3.4 4 +17 1.2.3.4 10 +18 1.2.3.4 4 +19 1.2.3.4 10 +20 1.2.3.4 0 +21 1.2.3.4 7 +22 1.2.3.4 14 +23 1.2.3.4 12 +24 1.2.3.4 4 +25 1.2.3.4 10 +26 1.2.3.4 12 +27 1.2.3.4 13 +28 1.2.3.4 0 +29 1.2.3.4 1 diff --git a/tests/queries/0_stateless/02531_ipv4_arithmetic.sql b/tests/queries/0_stateless/02531_ipv4_arithmetic.sql new file mode 100644 index 00000000000..59a99842d61 --- /dev/null +++ b/tests/queries/0_stateless/02531_ipv4_arithmetic.sql @@ -0,0 +1 @@ +SELECT number, ip, ip % number FROM (SELECT number, toIPv4('1.2.3.4') as ip FROM numbers(10, 20)); \ No newline at end of file