Merge pull request #31966 from ucasfl/comp-decimal-float

Enable comparison between Decimal and Float
This commit is contained in:
Anton Popov 2022-01-14 12:56:26 +03:00 committed by GitHub
commit 12195b149f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 118 additions and 17 deletions

View File

@ -52,7 +52,6 @@ struct DecCompareInt
using TypeB = Type;
};
///
template <typename A, typename B, template <typename, typename> typename Operation, bool _check_overflow = true,
bool _actual = is_decimal<A> || is_decimal<B>>
class DecimalComparison

View File

@ -506,7 +506,7 @@ inline bool isNotCreatable(const T & data_type)
inline bool isNotDecimalButComparableToDecimal(const DataTypePtr & data_type)
{
WhichDataType which(data_type);
return which.isInt() || which.isUInt();
return which.isInt() || which.isUInt() || which.isFloat();
}
inline bool isCompilableType(const DataTypePtr & data_type)

View File

@ -11,17 +11,17 @@
#include <Columns/ColumnTuple.h>
#include <Columns/ColumnArray.h>
#include <DataTypes/DataTypesNumber.h>
#include <DataTypes/DataTypeNullable.h>
#include <DataTypes/DataTypeNothing.h>
#include <DataTypes/DataTypeDate.h>
#include <DataTypes/DataTypeDateTime.h>
#include <DataTypes/DataTypeDateTime64.h>
#include <DataTypes/DataTypeDate.h>
#include <DataTypes/DataTypeString.h>
#include <DataTypes/DataTypeUUID.h>
#include <DataTypes/DataTypeFixedString.h>
#include <DataTypes/DataTypeTuple.h>
#include <DataTypes/DataTypeEnum.h>
#include <DataTypes/DataTypeFixedString.h>
#include <DataTypes/DataTypeNothing.h>
#include <DataTypes/DataTypeNullable.h>
#include <DataTypes/DataTypeString.h>
#include <DataTypes/DataTypeTuple.h>
#include <DataTypes/DataTypeUUID.h>
#include <DataTypes/DataTypesNumber.h>
#include <DataTypes/getLeastSupertype.h>
#include <Interpreters/convertFieldToType.h>
@ -1175,8 +1175,11 @@ public:
const bool left_is_num = col_left_untyped->isNumeric();
const bool right_is_num = col_right_untyped->isNumeric();
const bool left_is_string = isStringOrFixedString(which_left);
const bool right_is_string = isStringOrFixedString(which_right);
const bool left_is_string = which_left.isStringOrFixedString();
const bool right_is_string = which_right.isStringOrFixedString();
const bool left_is_float = which_left.isFloat();
const bool right_is_float = which_right.isFloat();
bool date_and_datetime = (which_left.idx != which_right.idx) && (which_left.isDate() || which_left.isDate32() || which_left.isDateTime() || which_left.isDateTime64())
&& (which_right.isDate() || which_right.isDate32() || which_right.isDateTime() || which_right.isDateTime64());
@ -1232,11 +1235,23 @@ public:
}
else
{
// compare
/// Check does another data type is comparable to Decimal, includes Int and Float.
if (!allowDecimalComparison(left_type, right_type) && !date_and_datetime)
throw Exception(
"No operation " + getName() + " between " + left_type->getName() + " and " + right_type->getName(),
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
/// When Decimal comparing to Float32/64, we convert both of them into Float64.
/// Other systems like MySQL and Spark also do as this.
if (left_is_float || right_is_float)
{
const auto converted_type = std::make_shared<DataTypeFloat64>();
ColumnPtr c0_converted = castColumn(col_with_type_and_name_left, converted_type);
ColumnPtr c1_converted = castColumn(col_with_type_and_name_right, converted_type);
auto new_arguments
= ColumnsWithTypeAndName{{c0_converted, converted_type, "left"}, {c1_converted, converted_type, "right"}};
return executeImpl(new_arguments, result_type, input_rows_count);
}
return executeDecimal(col_with_type_and_name_left, col_with_type_and_name_right);
}

View File

@ -1,5 +1,9 @@
0
1
0
1
0
1
-42 -42 1 0 0 0 1 1
42 42 1 0 0 0 1 1
-42 -42.42 0 0 1 1 0 1
@ -17,6 +21,8 @@
42 42 42
42 42 42
42 42 42
42 42 42
42 42 42
-42 -42.42 -42 -42
42 42 42 42.42
-42 -42 -42.42

View File

@ -17,8 +17,8 @@ CREATE TABLE IF NOT EXISTS decimal
INSERT INTO decimal (a, b, c, d, e, f, g, h, i, j) VALUES (42, 42, 42, 0.42, 0.42, 0.42, 42.42, 42.42, 42.42, 42.42);
INSERT INTO decimal (a, b, c, d, e, f, g, h, i, j) VALUES (-42, -42, -42, -0.42, -0.42, -0.42, -42.42, -42.42, -42.42, -42.42);
SELECT a > toFloat64(0) FROM decimal; -- { serverError 43 }
SELECT g > toFloat32(0) FROM decimal; -- { serverError 43 }
SELECT a > toFloat64(0) FROM decimal ORDER BY a;
SELECT g > toFloat32(0) FROM decimal ORDER BY g;
SELECT a > '0.0' FROM decimal ORDER BY a;
SELECT a, b, a = b, a < b, a > b, a != b, a <= b, a >= b FROM decimal ORDER BY a;
@ -36,8 +36,8 @@ SELECT a, b, c FROM decimal WHERE a = toInt8(42) AND b = toInt8(42) AND c = toIn
SELECT a, b, c FROM decimal WHERE a = toInt16(42) AND b = toInt16(42) AND c = toInt16(42);
SELECT a, b, c FROM decimal WHERE a = toInt32(42) AND b = toInt32(42) AND c = toInt32(42);
SELECT a, b, c FROM decimal WHERE a = toInt64(42) AND b = toInt64(42) AND c = toInt64(42);
SELECT a, b, c FROM decimal WHERE a = toFloat32(42); -- { serverError 43 }
SELECT a, b, c FROM decimal WHERE a = toFloat64(42); -- { serverError 43 }
SELECT a, b, c FROM decimal WHERE a = toFloat32(42);
SELECT a, b, c FROM decimal WHERE a = toFloat64(42);
SELECT least(a, b), least(a, g), greatest(a, b), greatest(a, g) FROM decimal ORDER BY a;
SELECT least(a, 0), least(b, 0), least(g, 0) FROM decimal ORDER BY a;

View File

@ -0,0 +1,34 @@
0
1
0
0
1
0
0
1
0
1
0
0
1
0
0
1
1
1
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0

View File

@ -0,0 +1,47 @@
select CAST(1.0, 'Decimal(15,2)') > CAST(1, 'Float64');
select CAST(1.0, 'Decimal(15,2)') = CAST(1, 'Float64');
select CAST(1.0, 'Decimal(15,2)') < CAST(1, 'Float64');
select CAST(1.0, 'Decimal(15,2)') != CAST(1, 'Float64');
select CAST(1.0, 'Decimal(15,2)') > CAST(-1, 'Float64');
select CAST(1.0, 'Decimal(15,2)') = CAST(-1, 'Float64');
select CAST(1.0, 'Decimal(15,2)') < CAST(-1, 'Float64');
select CAST(1.0, 'Decimal(15,2)') != CAST(-1, 'Float64');
select CAST(1.0, 'Decimal(15,2)') > CAST(1, 'Float32');
select CAST(1.0, 'Decimal(15,2)') = CAST(1, 'Float32');
select CAST(1.0, 'Decimal(15,2)') < CAST(1, 'Float32');
select CAST(1.0, 'Decimal(15,2)') != CAST(1, 'Float32');
select CAST(1.0, 'Decimal(15,2)') > CAST(-1, 'Float32');
select CAST(1.0, 'Decimal(15,2)') = CAST(-1, 'Float32');
select CAST(1.0, 'Decimal(15,2)') < CAST(-1, 'Float32');
select CAST(1.0, 'Decimal(15,2)') != CAST(-1, 'Float32');
SELECT toDecimal32('11.00', 2) > 1.;
SELECT 0.1000000000000000055511151231257827021181583404541015625::Decimal256(70) = 0.1;
DROP TABLE IF EXISTS t;
CREATE TABLE t
(
d1 Decimal32(5),
d2 Decimal64(10),
d3 Decimal128(30),
d4 Decimal256(50),
f1 Float32,
f2 Float32
)ENGINE = Memory;
INSERT INTO t values (-1.5, -1.5, -1.5, -1.5, 1.5, 1.5);
INSERT INTO t values (1.5, 1.5, 1.5, 1.5, -1.5, -1.5);
SELECT d1 > f1 FROM t ORDER BY f1;
SELECT d2 > f1 FROM t ORDER BY f1;
SELECT d3 > f1 FROM t ORDER BY f1;
SELECT d4 > f1 FROM t ORDER BY f1;
SELECT d1 > f2 FROM t ORDER BY f2;
SELECT d2 > f2 FROM t ORDER BY f2;
SELECT d3 > f2 FROM t ORDER BY f2;
SELECT d4 > f2 FROM t ORDER BY f2;
DROP TABLE t;