mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-26 01:22:04 +00:00
Merge pull request #30219 from lhuang09287750/master
make date32 type comparable with date/datetime/string
This commit is contained in:
commit
5544e866f8
@ -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.
|
||||
{
|
||||
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_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)
|
||||
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);
|
||||
|
||||
if (have_datetime64 == 0)
|
||||
if (have_datetime64 == 0 && have_date32 == 0)
|
||||
{
|
||||
for (const auto & type : types)
|
||||
{
|
||||
@ -298,6 +299,22 @@ DataTypePtr getLeastSupertype(const DataTypes & types)
|
||||
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;
|
||||
size_t max_scale_date_time_index = 0;
|
||||
|
||||
|
@ -1088,7 +1088,7 @@ public:
|
||||
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.
|
||||
/// 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.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())
|
||||
@ -1178,8 +1178,8 @@ public:
|
||||
const bool left_is_string = isStringOrFixedString(which_left);
|
||||
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())
|
||||
&& (which_right.isDate() || which_right.isDateTime() || which_right.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.isDate32() || which_right.isDateTime() || which_right.isDateTime64());
|
||||
|
||||
ColumnPtr res;
|
||||
if (left_is_num && right_is_num && !date_and_datetime)
|
||||
@ -1222,8 +1222,8 @@ public:
|
||||
}
|
||||
else if ((isColumnedAsDecimal(left_type) || isColumnedAsDecimal(right_type)))
|
||||
{
|
||||
// Comparing Date and DateTime64 requires implicit conversion,
|
||||
if (date_and_datetime && (isDate(left_type) || isDate(right_type)))
|
||||
// Comparing Date/Date32 and DateTime64 requires implicit conversion,
|
||||
if (date_and_datetime && (isDateOrDate32(left_type) || isDateOrDate32(right_type)))
|
||||
{
|
||||
DataTypePtr common_type = getLeastSupertype({left_type, right_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 c1_converted = castColumn(col_with_type_and_name_right, common_type);
|
||||
if (!((res = executeNumLeftType<UInt32>(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<UInt64>(c0_converted.get(), c1_converted.get()))
|
||||
|| (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;
|
||||
}
|
||||
else if (left_type->equals(*right_type))
|
||||
|
@ -301,7 +301,7 @@ struct ToDateTimeImpl
|
||||
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));
|
||||
}
|
||||
@ -638,7 +638,7 @@ struct ToDateTime64Transform
|
||||
inline DateTime64::NativeType execute(Int32 d, const DateLUTImpl & time_zone) const
|
||||
{
|
||||
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
|
||||
|
@ -203,6 +203,12 @@ Field convertFieldToTypeImpl(const Field & src, const IDataType & type, const ID
|
||||
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)
|
||||
{
|
||||
/// Already in needed type.
|
||||
@ -210,7 +216,7 @@ Field convertFieldToTypeImpl(const Field & src, const IDataType & type, const ID
|
||||
}
|
||||
|
||||
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 decimal_value = DecimalUtils::decimalFromComponents<DateTime64>(src.reinterpret<Int64>(), 0, scale);
|
||||
|
19
tests/queries/0_stateless/02098_date32_comparison.reference
Normal file
19
tests/queries/0_stateless/02098_date32_comparison.reference
Normal file
@ -0,0 +1,19 @@
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
19
tests/queries/0_stateless/02098_date32_comparison.sql
Normal file
19
tests/queries/0_stateless/02098_date32_comparison.sql
Normal 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');
|
Loading…
Reference in New Issue
Block a user