Merge pull request #30219 from lhuang09287750/master

make date32 type comparable with date/datetime/string
This commit is contained in:
Kseniia Sumarokova 2021-10-21 09:38:55 +03:00 committed by GitHub
commit 5544e866f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 77 additions and 14 deletions

View File

@ -277,17 +277,18 @@ DataTypePtr getLeastSupertype(const DataTypes & types)
/// For Date and DateTime/DateTime64, the common type is DateTime/DateTime64. No other types are compatible. /// For Date and DateTime/DateTime64, the common type is DateTime/DateTime64. No other types are compatible.
{ {
UInt32 have_date = type_ids.count(TypeIndex::Date); UInt32 have_date = type_ids.count(TypeIndex::Date);
UInt32 have_date32 = type_ids.count(TypeIndex::Date32);
UInt32 have_datetime = type_ids.count(TypeIndex::DateTime); UInt32 have_datetime = type_ids.count(TypeIndex::DateTime);
UInt32 have_datetime64 = type_ids.count(TypeIndex::DateTime64); UInt32 have_datetime64 = type_ids.count(TypeIndex::DateTime64);
if (have_date || have_datetime || have_datetime64) if (have_date || have_date32 || have_datetime || have_datetime64)
{ {
bool all_date_or_datetime = type_ids.size() == (have_date + have_datetime + have_datetime64); bool all_date_or_datetime = type_ids.size() == (have_date + have_date32 + have_datetime + have_datetime64);
if (!all_date_or_datetime) if (!all_date_or_datetime)
throw Exception(getExceptionMessagePrefix(types) + " because some of them are Date/DateTime/DateTime64 and some of them are not", throw Exception(getExceptionMessagePrefix(types) + " because some of them are Date/Date32/DateTime/DateTime64 and some of them are not",
ErrorCodes::NO_COMMON_TYPE); ErrorCodes::NO_COMMON_TYPE);
if (have_datetime64 == 0) if (have_datetime64 == 0 && have_date32 == 0)
{ {
for (const auto & type : types) for (const auto & type : types)
{ {
@ -298,6 +299,22 @@ DataTypePtr getLeastSupertype(const DataTypes & types)
return std::make_shared<DataTypeDateTime>(); return std::make_shared<DataTypeDateTime>();
} }
/// For Date and Date32, the common type is Date32
if (have_datetime == 0 && have_datetime64 == 0)
{
for (const auto & type : types)
{
if (isDate32(type))
return type;
}
}
/// For Datetime and Date32, the common type is Datetime64
if (have_datetime == 1 && have_date32 == 1 && have_datetime64 == 0)
{
return std::make_shared<DataTypeDateTime64>(0);
}
UInt8 max_scale = 0; UInt8 max_scale = 0;
size_t max_scale_date_time_index = 0; size_t max_scale_date_time_index = 0;

View File

@ -1088,7 +1088,7 @@ public:
if (!((both_represented_by_number && !has_date) /// Do not allow to compare date and number. if (!((both_represented_by_number && !has_date) /// Do not allow to compare date and number.
|| (left.isStringOrFixedString() || right.isStringOrFixedString()) /// Everything can be compared with string by conversion. || (left.isStringOrFixedString() || right.isStringOrFixedString()) /// Everything can be compared with string by conversion.
/// You can compare the date, datetime, or datatime64 and an enumeration with a constant string. /// You can compare the date, datetime, or datatime64 and an enumeration with a constant string.
|| ((left.isDate() || left.isDateTime() || left.isDateTime64()) && (right.isDate() || right.isDateTime() || right.isDateTime64()) && left.idx == right.idx) /// only date vs date, or datetime vs datetime || ((left.isDate() || left.isDate32() || left.isDateTime() || left.isDateTime64()) && (right.isDate() || right.isDate32() || right.isDateTime() || right.isDateTime64()) && left.idx == right.idx) /// only date vs date, or datetime vs datetime
|| (left.isUUID() && right.isUUID()) || (left.isUUID() && right.isUUID())
|| (left.isEnum() && right.isEnum() && arguments[0]->getName() == arguments[1]->getName()) /// only equivalent enum type values can be compared against || (left.isEnum() && right.isEnum() && arguments[0]->getName() == arguments[1]->getName()) /// only equivalent enum type values can be compared against
|| (left_tuple && right_tuple && left_tuple->getElements().size() == right_tuple->getElements().size()) || (left_tuple && right_tuple && left_tuple->getElements().size() == right_tuple->getElements().size())
@ -1178,8 +1178,8 @@ public:
const bool left_is_string = isStringOrFixedString(which_left); const bool left_is_string = isStringOrFixedString(which_left);
const bool right_is_string = isStringOrFixedString(which_right); const bool right_is_string = isStringOrFixedString(which_right);
bool date_and_datetime = (which_left.idx != which_right.idx) && (which_left.isDate() || which_left.isDateTime() || which_left.isDateTime64()) 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.isDateTime() || which_right.isDateTime64()); && (which_right.isDate() || which_right.isDate32() || which_right.isDateTime() || which_right.isDateTime64());
ColumnPtr res; ColumnPtr res;
if (left_is_num && right_is_num && !date_and_datetime) if (left_is_num && right_is_num && !date_and_datetime)
@ -1222,8 +1222,8 @@ public:
} }
else if ((isColumnedAsDecimal(left_type) || isColumnedAsDecimal(right_type))) else if ((isColumnedAsDecimal(left_type) || isColumnedAsDecimal(right_type)))
{ {
// Comparing Date and DateTime64 requires implicit conversion, // Comparing Date/Date32 and DateTime64 requires implicit conversion,
if (date_and_datetime && (isDate(left_type) || isDate(right_type))) if (date_and_datetime && (isDateOrDate32(left_type) || isDateOrDate32(right_type)))
{ {
DataTypePtr common_type = getLeastSupertype({left_type, right_type}); DataTypePtr common_type = getLeastSupertype({left_type, right_type});
ColumnPtr c0_converted = castColumn(col_with_type_and_name_left, common_type); ColumnPtr c0_converted = castColumn(col_with_type_and_name_left, common_type);
@ -1247,8 +1247,10 @@ public:
ColumnPtr c0_converted = castColumn(col_with_type_and_name_left, common_type); ColumnPtr c0_converted = castColumn(col_with_type_and_name_left, common_type);
ColumnPtr c1_converted = castColumn(col_with_type_and_name_right, common_type); ColumnPtr c1_converted = castColumn(col_with_type_and_name_right, common_type);
if (!((res = executeNumLeftType<UInt32>(c0_converted.get(), c1_converted.get())) if (!((res = executeNumLeftType<UInt32>(c0_converted.get(), c1_converted.get()))
|| (res = executeNumLeftType<UInt64>(c0_converted.get(), c1_converted.get())))) || (res = executeNumLeftType<UInt64>(c0_converted.get(), c1_converted.get()))
throw Exception("Date related common types can only be UInt32 or UInt64", ErrorCodes::LOGICAL_ERROR); || (res = executeNumLeftType<Int32>(c0_converted.get(), c1_converted.get()))
|| (res = executeDecimal({c0_converted, common_type, "left"}, {c1_converted, common_type, "right"}))))
throw Exception("Date related common types can only be UInt32/UInt64/Int32/Decimal", ErrorCodes::LOGICAL_ERROR);
return res; return res;
} }
else if (left_type->equals(*right_type)) else if (left_type->equals(*right_type))

View File

@ -301,7 +301,7 @@ struct ToDateTimeImpl
return time_zone.fromDayNum(DayNum(d)); return time_zone.fromDayNum(DayNum(d));
} }
static inline UInt32 execute(Int32 d, const DateLUTImpl & time_zone) static inline Int64 execute(Int32 d, const DateLUTImpl & time_zone)
{ {
return time_zone.fromDayNum(ExtendedDayNum(d)); return time_zone.fromDayNum(ExtendedDayNum(d));
} }
@ -638,7 +638,7 @@ struct ToDateTime64Transform
inline DateTime64::NativeType execute(Int32 d, const DateLUTImpl & time_zone) const inline DateTime64::NativeType execute(Int32 d, const DateLUTImpl & time_zone) const
{ {
const auto dt = ToDateTimeImpl::execute(d, time_zone); const auto dt = ToDateTimeImpl::execute(d, time_zone);
return execute(dt, time_zone); return DecimalUtils::decimalFromComponentsWithMultiplier<DateTime64>(dt, 0, scale_multiplier);
} }
inline DateTime64::NativeType execute(UInt32 dt, const DateLUTImpl & /*time_zone*/) const inline DateTime64::NativeType execute(UInt32 dt, const DateLUTImpl & /*time_zone*/) const

View File

@ -203,6 +203,12 @@ Field convertFieldToTypeImpl(const Field & src, const IDataType & type, const ID
return src; return src;
} }
if (which_type.isDate32() && src.getType() == Field::Types::Int64)
{
/// We don't need any conversion Int64 is under type of Date32
return src;
}
if (which_type.isDateTime64() && src.getType() == Field::Types::Decimal64) if (which_type.isDateTime64() && src.getType() == Field::Types::Decimal64)
{ {
/// Already in needed type. /// Already in needed type.
@ -210,7 +216,7 @@ Field convertFieldToTypeImpl(const Field & src, const IDataType & type, const ID
} }
if (which_type.isDateTime64() if (which_type.isDateTime64()
&& (which_from_type.isNativeInt() || which_from_type.isNativeUInt() || which_from_type.isDate() || which_from_type.isDateTime() || which_from_type.isDateTime64())) && (which_from_type.isNativeInt() || which_from_type.isNativeUInt() || which_from_type.isDate() || which_from_type.isDate32() || which_from_type.isDateTime() || which_from_type.isDateTime64()))
{ {
const auto scale = static_cast<const DataTypeDateTime64 &>(type).getScale(); const auto scale = static_cast<const DataTypeDateTime64 &>(type).getScale();
const auto decimal_value = DecimalUtils::decimalFromComponents<DateTime64>(src.reinterpret<Int64>(), 0, scale); const auto decimal_value = DecimalUtils::decimalFromComponents<DateTime64>(src.reinterpret<Int64>(), 0, scale);

View File

@ -0,0 +1,19 @@
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1

View File

@ -0,0 +1,19 @@
select toDate32('1990-01-01') = toDate('1990-01-01');
select toDate('1991-01-02') > toDate32('1990-01-01');
select toDate32('1925-01-01') <= toDate('1990-01-01');
select toDate('1991-01-01') < toDate32('2283-11-11');
select toDate32('1990-01-01') = toDateTime('1990-01-01');
select toDateTime('1991-01-02') > toDate32('1990-01-01');
select toDate32('1925-01-01') <= toDateTime('1990-01-01');
select toDateTime('1991-01-01') < toDate32('2283-11-11');
select toDate32('1990-01-01') = toDateTime64('1990-01-01',2);
select toDateTime64('1991-01-02',2) > toDate32('1990-01-01');
select toDate32('1925-01-01') = toDateTime64('1925-01-01',2);
select toDateTime64('1925-01-02',2) > toDate32('1925-01-01');
select toDate32('2283-11-11') = toDateTime64('2283-11-11',2);
select toDateTime64('2283-11-11',2) > toDate32('1925-01-01');
select toDate32('1990-01-01') = '1990-01-01';
select '1991-01-02' > toDate32('1990-01-01');
select toDate32('1925-01-01') = '1925-01-01';
select '2283-11-11' >= toDate32('2283-11-10');
select '2283-11-11' > toDate32('1925-01-01');