mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-27 01:51:59 +00:00
Merge pull request #55589 from rschu1ze/string-args-in-week-functions
MySQL compatibility: `toDayOfWeek()` now supports string arguments
This commit is contained in:
commit
f7cf512824
@ -587,20 +587,22 @@ The two-argument form of `toDayOfWeek()` enables you to specify whether the week
|
||||
| 2 | Sunday | 0-6: Sunday = 0, Monday = 1, ..., Saturday = 6 |
|
||||
| 3 | Sunday | 1-7: Sunday = 1, Monday = 2, ..., Saturday = 7 |
|
||||
|
||||
Alias: `DAYOFWEEK`.
|
||||
|
||||
**Syntax**
|
||||
|
||||
``` sql
|
||||
toDayOfWeek(t[, mode[, timezone]])
|
||||
```
|
||||
|
||||
Alias: `DAYOFWEEK`.
|
||||
|
||||
**Arguments**
|
||||
|
||||
- `t` - a [Date](../data-types/date.md), [Date32](../data-types/date32.md), [DateTime](../data-types/datetime.md) or [DateTime64](../data-types/datetime64.md)
|
||||
- `mode` - determines what the first day of the week is. Possible values are 0, 1, 2 or 3. See the table above for the differences.
|
||||
- `timezone` - optional parameter, it behaves like any other conversion function
|
||||
|
||||
The first argument can also be specified as [String](../data-types/string.md) in a format supported by [parseDateTime64BestEffort()](type-conversion-functions.md#parsedatetime64besteffort). Support for string arguments exists only for reasons of compatibility with MySQL which is expected by certain 3rd party tools. As string argument support may in future be made dependent on new MySQL-compatibility settings and because string parsing is generally slow, it is recommended to not use it.
|
||||
|
||||
**Returned value**
|
||||
|
||||
- The day of the month (1 - 31) of the given date/time
|
||||
@ -1489,12 +1491,16 @@ For mode values with a meaning of “contains January 1”, the week contains Ja
|
||||
toWeek(t[, mode[, time_zone]])
|
||||
```
|
||||
|
||||
Alias: `WEEK`
|
||||
|
||||
**Arguments**
|
||||
|
||||
- `t` – Date or DateTime.
|
||||
- `mode` – Optional parameter, Range of values is \[0,9\], default is 0.
|
||||
- `Timezone` – Optional parameter, it behaves like any other conversion function.
|
||||
|
||||
The first argument can also be specified as [String](../data-types/string.md) in a format supported by [parseDateTime64BestEffort()](type-conversion-functions.md#parsedatetime64besteffort). Support for string arguments exists only for reasons of compatibility with MySQL which is expected by certain 3rd party tools. As string argument support may in future be made dependent on new MySQL-compatibility settings and because string parsing is generally slow, it is recommended to not use it.
|
||||
|
||||
**Example**
|
||||
|
||||
``` sql
|
||||
@ -1525,6 +1531,10 @@ The week number returned by `toYearWeek()` can be different from what the `toWee
|
||||
toYearWeek(t[, mode[, timezone]])
|
||||
```
|
||||
|
||||
Alias: `YEARWEEK`
|
||||
|
||||
The first argument can also be specified as [String](../data-types/string.md) in a format supported by [parseDateTime64BestEffort()](type-conversion-functions.md#parsedatetime64besteffort). Support for string arguments exists only for reasons of compatibility with MySQL which is expected by certain 3rd party tools. As string argument support may in future be made dependent on new MySQL-compatibility settings and because string parsing is generally slow, it is recommended to not use it.
|
||||
|
||||
**Example**
|
||||
|
||||
``` sql
|
||||
|
@ -1,18 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <Columns/ColumnString.h>
|
||||
#include <Columns/ColumnVector.h>
|
||||
#include <Columns/ColumnsNumber.h>
|
||||
#include <base/types.h>
|
||||
#include <Common/DateLUTImpl.h>
|
||||
#include <Common/Exception.h>
|
||||
#include <Core/DecimalFunctions.h>
|
||||
#include <DataTypes/DataTypeString.h>
|
||||
#include <Functions/DateTimeTransforms.h>
|
||||
#include <Functions/FunctionHelpers.h>
|
||||
#include <Functions/extractTimeZoneFromFunctionArguments.h>
|
||||
#include <Functions/IFunction.h>
|
||||
#include <Common/Exception.h>
|
||||
#include <Common/DateLUTImpl.h>
|
||||
|
||||
/// The default mode value to use for the WEEK() function
|
||||
#define DEFAULT_WEEK_MODE 0
|
||||
#include <Functions/extractTimeZoneFromFunctionArguments.h>
|
||||
#include <IO/ReadBufferFromString.h>
|
||||
#include <IO/parseDateTimeBestEffort.h>
|
||||
#include <base/types.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -22,132 +23,6 @@ namespace ErrorCodes
|
||||
extern const int ILLEGAL_COLUMN;
|
||||
}
|
||||
|
||||
/**
|
||||
* CustomWeek Transformations.
|
||||
*/
|
||||
|
||||
struct ToYearWeekImpl
|
||||
{
|
||||
static constexpr auto name = "toYearWeek";
|
||||
|
||||
static inline UInt32 execute(Int64 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
// TODO: ditch toDayNum()
|
||||
YearWeek yw = time_zone.toYearWeek(time_zone.toDayNum(t), week_mode | static_cast<UInt32>(WeekModeFlag::YEAR));
|
||||
return yw.first * 100 + yw.second;
|
||||
}
|
||||
|
||||
static inline UInt32 execute(UInt32 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
YearWeek yw = time_zone.toYearWeek(time_zone.toDayNum(t), week_mode | static_cast<UInt32>(WeekModeFlag::YEAR));
|
||||
return yw.first * 100 + yw.second;
|
||||
}
|
||||
static inline UInt32 execute(Int32 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
YearWeek yw = time_zone.toYearWeek(ExtendedDayNum (d), week_mode | static_cast<UInt32>(WeekModeFlag::YEAR));
|
||||
return yw.first * 100 + yw.second;
|
||||
}
|
||||
static inline UInt32 execute(UInt16 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
YearWeek yw = time_zone.toYearWeek(DayNum(d), week_mode | static_cast<UInt32>(WeekModeFlag::YEAR));
|
||||
return yw.first * 100 + yw.second;
|
||||
}
|
||||
|
||||
using FactorTransform = ZeroTransform;
|
||||
};
|
||||
|
||||
struct ToStartOfWeekImpl
|
||||
{
|
||||
static constexpr auto name = "toStartOfWeek";
|
||||
|
||||
static inline UInt16 execute(Int64 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toFirstDayNumOfWeek(time_zone.toDayNum(t), week_mode);
|
||||
}
|
||||
static inline UInt16 execute(UInt32 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toFirstDayNumOfWeek(time_zone.toDayNum(t), week_mode);
|
||||
}
|
||||
static inline UInt16 execute(Int32 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toFirstDayNumOfWeek(ExtendedDayNum(d), week_mode);
|
||||
}
|
||||
static inline UInt16 execute(UInt16 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toFirstDayNumOfWeek(DayNum(d), week_mode);
|
||||
}
|
||||
static inline Int64 executeExtendedResult(Int64 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toFirstDayNumOfWeek(time_zone.toDayNum(t), week_mode);
|
||||
}
|
||||
static inline Int32 executeExtendedResult(Int32 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toFirstDayNumOfWeek(ExtendedDayNum(d), week_mode);
|
||||
}
|
||||
|
||||
using FactorTransform = ZeroTransform;
|
||||
};
|
||||
|
||||
struct ToLastDayOfWeekImpl
|
||||
{
|
||||
static constexpr auto name = "toLastDayOfWeek";
|
||||
|
||||
static inline UInt16 execute(Int64 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toLastDayNumOfWeek(time_zone.toDayNum(t), week_mode);
|
||||
}
|
||||
static inline UInt16 execute(UInt32 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toLastDayNumOfWeek(time_zone.toDayNum(t), week_mode);
|
||||
}
|
||||
static inline UInt16 execute(Int32 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toLastDayNumOfWeek(ExtendedDayNum(d), week_mode);
|
||||
}
|
||||
static inline UInt16 execute(UInt16 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toLastDayNumOfWeek(DayNum(d), week_mode);
|
||||
}
|
||||
static inline Int64 executeExtendedResult(Int64 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toLastDayNumOfWeek(time_zone.toDayNum(t), week_mode);
|
||||
}
|
||||
static inline Int32 executeExtendedResult(Int32 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toLastDayNumOfWeek(ExtendedDayNum(d), week_mode);
|
||||
}
|
||||
|
||||
using FactorTransform = ZeroTransform;
|
||||
};
|
||||
|
||||
struct ToWeekImpl
|
||||
{
|
||||
static constexpr auto name = "toWeek";
|
||||
|
||||
static inline UInt8 execute(Int64 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
// TODO: ditch conversion to DayNum, since it doesn't support extended range.
|
||||
YearWeek yw = time_zone.toYearWeek(time_zone.toDayNum(t), week_mode);
|
||||
return yw.second;
|
||||
}
|
||||
static inline UInt8 execute(UInt32 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
YearWeek yw = time_zone.toYearWeek(time_zone.toDayNum(t), week_mode);
|
||||
return yw.second;
|
||||
}
|
||||
static inline UInt8 execute(Int32 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
YearWeek yw = time_zone.toYearWeek(ExtendedDayNum(d), week_mode);
|
||||
return yw.second;
|
||||
}
|
||||
static inline UInt8 execute(UInt16 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
YearWeek yw = time_zone.toYearWeek(DayNum(d), week_mode);
|
||||
return yw.second;
|
||||
}
|
||||
|
||||
using FactorTransform = ToStartOfYearImpl;
|
||||
};
|
||||
|
||||
template <typename FromType, typename ToType, typename Transform, bool is_extended_result = false>
|
||||
struct WeekTransformer
|
||||
@ -157,8 +32,7 @@ struct WeekTransformer
|
||||
{}
|
||||
|
||||
template <typename FromVectorType, typename ToVectorType>
|
||||
void
|
||||
vector(const FromVectorType & vec_from, ToVectorType & vec_to, UInt8 week_mode, const DateLUTImpl & time_zone) const
|
||||
void vector(const FromVectorType & vec_from, ToVectorType & vec_to, UInt8 week_mode, const DateLUTImpl & time_zone) const
|
||||
{
|
||||
using ValueType = typename ToVectorType::value_type;
|
||||
size_t size = vec_from.size();
|
||||
@ -186,7 +60,8 @@ struct CustomWeekTransformImpl
|
||||
{
|
||||
const auto op = WeekTransformer<typename FromDataType::FieldType, typename ToDataType::FieldType, Transform, is_extended_result>{std::move(transform)};
|
||||
|
||||
UInt8 week_mode = DEFAULT_WEEK_MODE;
|
||||
static constexpr UInt8 default_week_mode = 0;
|
||||
UInt8 week_mode = default_week_mode;
|
||||
if (arguments.size() > 1)
|
||||
{
|
||||
if (const auto * week_mode_column = checkAndGetColumnConst<ColumnUInt8>(arguments[1].column.get()))
|
||||
@ -195,7 +70,26 @@ struct CustomWeekTransformImpl
|
||||
|
||||
const DateLUTImpl & time_zone = extractTimeZoneFromFunctionArguments(arguments, 2, 0);
|
||||
const ColumnPtr source_col = arguments[0].column;
|
||||
if (const auto * sources = checkAndGetColumn<typename FromDataType::ColumnType>(source_col.get()))
|
||||
|
||||
if constexpr (std::is_same_v<FromDataType, DataTypeString>)
|
||||
{
|
||||
static const DateLUTImpl & utc_time_zone = DateLUT::instance("UTC");
|
||||
const auto * sources = checkAndGetColumn<DataTypeString::ColumnType>(source_col.get());
|
||||
|
||||
auto col_to = ToDataType::ColumnType::create();
|
||||
col_to->getData().resize(sources->size());
|
||||
|
||||
for (size_t i = 0; i < sources->size(); ++i)
|
||||
{
|
||||
DateTime64 dt64;
|
||||
ReadBufferFromString buf(sources->getDataAt(i).toView());
|
||||
parseDateTime64BestEffort(dt64, 0, buf, time_zone, utc_time_zone);
|
||||
col_to->getData()[i] = static_cast<ToDataType::FieldType>(transform.execute(dt64, week_mode, time_zone));
|
||||
}
|
||||
|
||||
return col_to;
|
||||
}
|
||||
else if (const auto * sources = checkAndGetColumn<typename FromDataType::ColumnType>(source_col.get()))
|
||||
{
|
||||
auto col_to = ToDataType::ColumnType::create();
|
||||
op.vector(sources->getData(), col_to->getData(), week_mode, time_zone);
|
||||
|
@ -305,6 +305,132 @@ struct ToStartOfYearImpl
|
||||
using FactorTransform = ZeroTransform;
|
||||
};
|
||||
|
||||
struct ToYearWeekImpl
|
||||
{
|
||||
static constexpr auto name = "toYearWeek";
|
||||
static constexpr bool value_may_be_string = true;
|
||||
|
||||
static UInt32 execute(Int64 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
// TODO: ditch toDayNum()
|
||||
YearWeek yw = time_zone.toYearWeek(time_zone.toDayNum(t), week_mode | static_cast<UInt32>(WeekModeFlag::YEAR));
|
||||
return yw.first * 100 + yw.second;
|
||||
}
|
||||
|
||||
static UInt32 execute(UInt32 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
YearWeek yw = time_zone.toYearWeek(time_zone.toDayNum(t), week_mode | static_cast<UInt32>(WeekModeFlag::YEAR));
|
||||
return yw.first * 100 + yw.second;
|
||||
}
|
||||
static UInt32 execute(Int32 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
YearWeek yw = time_zone.toYearWeek(ExtendedDayNum (d), week_mode | static_cast<UInt32>(WeekModeFlag::YEAR));
|
||||
return yw.first * 100 + yw.second;
|
||||
}
|
||||
static UInt32 execute(UInt16 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
YearWeek yw = time_zone.toYearWeek(DayNum(d), week_mode | static_cast<UInt32>(WeekModeFlag::YEAR));
|
||||
return yw.first * 100 + yw.second;
|
||||
}
|
||||
|
||||
using FactorTransform = ZeroTransform;
|
||||
};
|
||||
|
||||
struct ToStartOfWeekImpl
|
||||
{
|
||||
static constexpr auto name = "toStartOfWeek";
|
||||
static constexpr bool value_may_be_string = false;
|
||||
|
||||
static UInt16 execute(Int64 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toFirstDayNumOfWeek(time_zone.toDayNum(t), week_mode);
|
||||
}
|
||||
static UInt16 execute(UInt32 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toFirstDayNumOfWeek(time_zone.toDayNum(t), week_mode);
|
||||
}
|
||||
static UInt16 execute(Int32 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toFirstDayNumOfWeek(ExtendedDayNum(d), week_mode);
|
||||
}
|
||||
static UInt16 execute(UInt16 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toFirstDayNumOfWeek(DayNum(d), week_mode);
|
||||
}
|
||||
static Int64 executeExtendedResult(Int64 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toFirstDayNumOfWeek(time_zone.toDayNum(t), week_mode);
|
||||
}
|
||||
static Int32 executeExtendedResult(Int32 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toFirstDayNumOfWeek(ExtendedDayNum(d), week_mode);
|
||||
}
|
||||
|
||||
using FactorTransform = ZeroTransform;
|
||||
};
|
||||
|
||||
struct ToLastDayOfWeekImpl
|
||||
{
|
||||
static constexpr auto name = "toLastDayOfWeek";
|
||||
static constexpr bool value_may_be_string = false;
|
||||
|
||||
static UInt16 execute(Int64 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toLastDayNumOfWeek(time_zone.toDayNum(t), week_mode);
|
||||
}
|
||||
static UInt16 execute(UInt32 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toLastDayNumOfWeek(time_zone.toDayNum(t), week_mode);
|
||||
}
|
||||
static UInt16 execute(Int32 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toLastDayNumOfWeek(ExtendedDayNum(d), week_mode);
|
||||
}
|
||||
static UInt16 execute(UInt16 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toLastDayNumOfWeek(DayNum(d), week_mode);
|
||||
}
|
||||
static Int64 executeExtendedResult(Int64 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toLastDayNumOfWeek(time_zone.toDayNum(t), week_mode);
|
||||
}
|
||||
static Int32 executeExtendedResult(Int32 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toLastDayNumOfWeek(ExtendedDayNum(d), week_mode);
|
||||
}
|
||||
|
||||
using FactorTransform = ZeroTransform;
|
||||
};
|
||||
|
||||
struct ToWeekImpl
|
||||
{
|
||||
static constexpr auto name = "toWeek";
|
||||
static constexpr bool value_may_be_string = true;
|
||||
|
||||
static UInt8 execute(Int64 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
// TODO: ditch conversion to DayNum, since it doesn't support extended range.
|
||||
YearWeek yw = time_zone.toYearWeek(time_zone.toDayNum(t), week_mode);
|
||||
return yw.second;
|
||||
}
|
||||
static UInt8 execute(UInt32 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
YearWeek yw = time_zone.toYearWeek(time_zone.toDayNum(t), week_mode);
|
||||
return yw.second;
|
||||
}
|
||||
static UInt8 execute(Int32 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
YearWeek yw = time_zone.toYearWeek(ExtendedDayNum(d), week_mode);
|
||||
return yw.second;
|
||||
}
|
||||
static UInt8 execute(UInt16 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
YearWeek yw = time_zone.toYearWeek(DayNum(d), week_mode);
|
||||
return yw.second;
|
||||
}
|
||||
|
||||
using FactorTransform = ToStartOfYearImpl;
|
||||
};
|
||||
|
||||
template <IntervalKind::Kind unit>
|
||||
struct ToStartOfInterval;
|
||||
@ -1176,6 +1302,7 @@ struct ToDayOfMonthImpl
|
||||
struct ToDayOfWeekImpl
|
||||
{
|
||||
static constexpr auto name = "toDayOfWeek";
|
||||
static constexpr bool value_may_be_string = true;
|
||||
|
||||
static UInt8 execute(Int64 t, UInt8 mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
|
@ -16,19 +16,19 @@ private:
|
||||
const bool enable_extended_results_for_datetime_functions = false;
|
||||
|
||||
public:
|
||||
static FunctionPtr create(ContextPtr context_)
|
||||
static FunctionPtr create(ContextPtr context)
|
||||
{
|
||||
return std::make_shared<FunctionCustomWeekToDateOrDate32>(context_);
|
||||
return std::make_shared<FunctionCustomWeekToDateOrDate32>(context);
|
||||
}
|
||||
|
||||
explicit FunctionCustomWeekToDateOrDate32(ContextPtr context_)
|
||||
: enable_extended_results_for_datetime_functions(context_->getSettingsRef().enable_extended_results_for_datetime_functions)
|
||||
explicit FunctionCustomWeekToDateOrDate32(ContextPtr context)
|
||||
: enable_extended_results_for_datetime_functions(context->getSettingsRef().enable_extended_results_for_datetime_functions)
|
||||
{
|
||||
}
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
||||
{
|
||||
this->checkArguments(arguments, /*is_result_type_date_or_date32*/ true);
|
||||
this->checkArguments(arguments, /*is_result_type_date_or_date32*/ true, Transform::value_may_be_string);
|
||||
|
||||
const IDataType * from_type = arguments[0].type.get();
|
||||
WhichDataType which(from_type);
|
||||
@ -44,16 +44,13 @@ public:
|
||||
WhichDataType which(from_type);
|
||||
|
||||
if (which.isDate())
|
||||
return CustomWeekTransformImpl<DataTypeDate, DataTypeDate>::execute(
|
||||
arguments, result_type, input_rows_count, Transform{});
|
||||
return CustomWeekTransformImpl<DataTypeDate, DataTypeDate>::execute(arguments, result_type, input_rows_count, Transform{});
|
||||
else if (which.isDate32())
|
||||
{
|
||||
if (enable_extended_results_for_datetime_functions)
|
||||
return CustomWeekTransformImpl<DataTypeDate32, DataTypeDate32, /*is_extended_result*/ true>::execute(
|
||||
arguments, result_type, input_rows_count, Transform{});
|
||||
return CustomWeekTransformImpl<DataTypeDate32, DataTypeDate32, /*is_extended_result*/ true>::execute(arguments, result_type, input_rows_count, Transform{});
|
||||
else
|
||||
return CustomWeekTransformImpl<DataTypeDate32, DataTypeDate>::execute(
|
||||
arguments, result_type, input_rows_count, Transform{});
|
||||
return CustomWeekTransformImpl<DataTypeDate32, DataTypeDate>::execute(arguments, result_type, input_rows_count, Transform{});
|
||||
}
|
||||
else if (which.isDateTime())
|
||||
return CustomWeekTransformImpl<DataTypeDateTime, DataTypeDate>::execute(
|
||||
@ -61,14 +58,14 @@ public:
|
||||
else if (which.isDateTime64())
|
||||
{
|
||||
if (enable_extended_results_for_datetime_functions)
|
||||
return CustomWeekTransformImpl<DataTypeDateTime64, DataTypeDate32, /*is_extended_result*/ true>::execute(
|
||||
arguments, result_type, input_rows_count,
|
||||
return CustomWeekTransformImpl<DataTypeDateTime64, DataTypeDate32, /*is_extended_result*/ true>::execute(arguments, result_type, input_rows_count,
|
||||
TransformDateTime64<Transform>{assert_cast<const DataTypeDateTime64 *>(from_type)->getScale()});
|
||||
else
|
||||
return CustomWeekTransformImpl<DataTypeDateTime64, DataTypeDate>::execute(
|
||||
arguments, result_type, input_rows_count,
|
||||
return CustomWeekTransformImpl<DataTypeDateTime64, DataTypeDate>::execute(arguments, result_type, input_rows_count,
|
||||
TransformDateTime64<Transform>{assert_cast<const DataTypeDateTime64 *>(from_type)->getScale()});
|
||||
}
|
||||
else if (Transform::value_may_be_string && which.isString())
|
||||
return CustomWeekTransformImpl<DataTypeString, DataTypeDate>::execute(arguments, result_type, input_rows_count, Transform{}); // TODO
|
||||
else
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
|
||||
"Illegal type {} of argument of function {}",
|
||||
|
@ -19,8 +19,7 @@ public:
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
||||
{
|
||||
this->checkArguments(arguments);
|
||||
|
||||
this->checkArguments(arguments, /*is_result_type_date_or_date32*/ false, Transform::value_may_be_string);
|
||||
return std::make_shared<ToDataType>();
|
||||
}
|
||||
|
||||
@ -30,20 +29,16 @@ public:
|
||||
WhichDataType which(from_type);
|
||||
|
||||
if (which.isDate())
|
||||
return CustomWeekTransformImpl<DataTypeDate, ToDataType>::execute(
|
||||
arguments, result_type, input_rows_count, Transform{});
|
||||
return CustomWeekTransformImpl<DataTypeDate, ToDataType>::execute(arguments, result_type, input_rows_count, Transform{});
|
||||
else if (which.isDate32())
|
||||
return CustomWeekTransformImpl<DataTypeDate32, ToDataType>::execute(
|
||||
arguments, result_type, input_rows_count, Transform{});
|
||||
return CustomWeekTransformImpl<DataTypeDate32, ToDataType>::execute(arguments, result_type, input_rows_count, Transform{});
|
||||
else if (which.isDateTime())
|
||||
return CustomWeekTransformImpl<DataTypeDateTime, ToDataType>::execute(
|
||||
arguments, result_type, input_rows_count, Transform{});
|
||||
return CustomWeekTransformImpl<DataTypeDateTime, ToDataType>::execute(arguments, result_type, input_rows_count, Transform{});
|
||||
else if (which.isDateTime64())
|
||||
{
|
||||
return CustomWeekTransformImpl<DataTypeDateTime64, ToDataType>::execute(
|
||||
arguments, result_type, input_rows_count,
|
||||
return CustomWeekTransformImpl<DataTypeDateTime64, ToDataType>::execute(arguments, result_type, input_rows_count,
|
||||
TransformDateTime64<Transform>{assert_cast<const DataTypeDateTime64 *>(from_type)->getScale()});
|
||||
}
|
||||
else if (Transform::value_may_be_string && which.isString())
|
||||
return CustomWeekTransformImpl<DataTypeString, ToDataType>::execute(arguments, result_type, input_rows_count, Transform{});
|
||||
else
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
|
||||
"Illegal type {} of argument of function {}",
|
||||
|
@ -65,41 +65,47 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
void checkArguments(const ColumnsWithTypeAndName & arguments, bool is_result_type_date_or_date32 = false) const
|
||||
void checkArguments(const ColumnsWithTypeAndName & arguments, bool is_result_type_date_or_date32, bool value_may_be_string) const
|
||||
{
|
||||
if (arguments.size() == 1)
|
||||
{
|
||||
if (!isDate(arguments[0].type) && !isDate32(arguments[0].type) && !isDateTime(arguments[0].type) && !isDateTime64(arguments[0].type))
|
||||
auto type0 = arguments[0].type;
|
||||
if (!isDate(type0) && !isDate32(type0) && !isDateTime(type0) && !isDateTime64(type0) && !(value_may_be_string && isString(type0)))
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
|
||||
"Illegal type {} of argument of function {}. Must be Date, Date32, DateTime or DateTime64.",
|
||||
arguments[0].type->getName(), getName());
|
||||
type0->getName(), getName());
|
||||
}
|
||||
else if (arguments.size() == 2)
|
||||
{
|
||||
if (!isDate(arguments[0].type) && !isDate32(arguments[0].type) && !isDateTime(arguments[0].type) && !isDateTime64(arguments[0].type))
|
||||
auto type0 = arguments[0].type;
|
||||
auto type1 = arguments[1].type;
|
||||
if (!isDate(type0) && !isDate32(type0) && !isDateTime(type0) && !isDateTime64(type0) && !(value_may_be_string && isString(type0)))
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
|
||||
"Illegal type {} of 1st argument of function {}. Must be Date, Date32, DateTime or DateTime64.",
|
||||
arguments[0].type->getName(), getName());
|
||||
if (!isUInt8(arguments[1].type))
|
||||
type0->getName(), getName());
|
||||
if (!isUInt8(type1))
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
|
||||
"Illegal type {} of 2nd (optional) argument of function {}. Must be constant UInt8 (week mode).",
|
||||
arguments[1].type->getName(), getName());
|
||||
type1->getName(), getName());
|
||||
}
|
||||
else if (arguments.size() == 3)
|
||||
{
|
||||
if (!isDate(arguments[0].type) && !isDate32(arguments[0].type) && !isDateTime(arguments[0].type) && !isDateTime64(arguments[0].type))
|
||||
auto type0 = arguments[0].type;
|
||||
auto type1 = arguments[1].type;
|
||||
auto type2 = arguments[2].type;
|
||||
if (!isDate(type0) && !isDate32(type0) && !isDateTime(type0) && !isDateTime64(type0) && !(value_may_be_string && isString(type0)))
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
|
||||
"Illegal type {} of argument of function {}. Must be Date, Date32, DateTime or DateTime64",
|
||||
arguments[0].type->getName(), getName());
|
||||
if (!isUInt8(arguments[1].type))
|
||||
type0->getName(), getName());
|
||||
if (!isUInt8(type1))
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
|
||||
"Illegal type {} of 2nd (optional) argument of function {}. Must be constant UInt8 (week mode).",
|
||||
arguments[1].type->getName(), getName());
|
||||
if (!isString(arguments[2].type))
|
||||
type1->getName(), getName());
|
||||
if (!isString(type2))
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
|
||||
"Illegal type {} of 3rd (optional) argument of function {}. Must be constant string (timezone name).",
|
||||
arguments[2].type->getName(), getName());
|
||||
if ((isDate(arguments[0].type) || isDate32(arguments[0].type)) && is_result_type_date_or_date32)
|
||||
type2->getName(), getName());
|
||||
if (is_result_type_date_or_date32 && (isDate(type0) || isDate32(type0)))
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
|
||||
"The timezone argument of function {} is allowed only when the 1st argument is DateTime or DateTime64.",
|
||||
getName());
|
||||
|
@ -0,0 +1,17 @@
|
||||
-- Constant argument
|
||||
3 3 3 3
|
||||
24 24 24 24
|
||||
201624 201624 201624 201624
|
||||
-- Non-constant argument
|
||||
3 3 3 3 3 3
|
||||
7 7 7 7 7 7
|
||||
1 1 1 1 1 1
|
||||
4 4 4 4 4 4
|
||||
37 37 37 37 37 37
|
||||
39 39 39 39 39 39
|
||||
4 4 4 4 4 4
|
||||
7 7 7 7 7 7
|
||||
201737 201737 201737 201737 201737 201737
|
||||
201739 201739 201739 201739 201739 201739
|
||||
201804 201804 201804 201804 201804 201804
|
||||
201907 201907 201907 201907 201907 201907
|
@ -0,0 +1,40 @@
|
||||
-- Tests that functions `toDayOfWeek()`, 'toWeek()' and 'toYearWeek()' accepts a date given as string (for compatibility with MySQL)
|
||||
|
||||
SELECT '-- Constant argument';
|
||||
|
||||
SELECT toDayOfWeek(toDateTime('2016-06-15 23:00:00')), toDayOfWeek('2016-06-15'), toDayOfWeek('2016-06-15 23:00:00'), toDayOfWeek('2016-06-15 23:00:00.123456');
|
||||
SELECT toWeek(toDateTime('2016-06-15 23:00:00')), toWeek('2016-06-15'), toWeek('2016-06-15 23:00:00'), toWeek('2016-06-15 23:00:00.123456');
|
||||
SELECT toYearWeek(toDateTime('2016-06-15 23:00:00')), toYearWeek('2016-06-15'), toYearWeek('2016-06-15 23:00:00'), toYearWeek('2016-06-15 23:00:00.123456');
|
||||
|
||||
SELECT toDayOfWeek('invalid'); -- { serverError CANNOT_PARSE_DATETIME }
|
||||
SELECT toWeek('invalid'); -- { serverError CANNOT_PARSE_DATETIME }
|
||||
SELECT toYearWeek('invalid'); -- { serverError CANNOT_PARSE_DATETIME }
|
||||
|
||||
SELECT '-- Non-constant argument';
|
||||
|
||||
DROP TABLE IF EXISTS tab;
|
||||
CREATE TABLE tab
|
||||
(
|
||||
d Date,
|
||||
dt DateTime('UTC'),
|
||||
dt64 DateTime64(6, 'UTC'),
|
||||
str_d String,
|
||||
str_dt String,
|
||||
str_dt64 String,
|
||||
invalid String
|
||||
) ENGINE MergeTree ORDER BY dt;
|
||||
|
||||
INSERT INTO `tab` VALUES (toDate('2017-09-13'), toDateTime('2017-09-13 19:10:22', 'UTC'), toDateTime64('2017-09-13 19:10:22.123456', 6, 'UTC'), '2017-09-13', '2017-09-13 19:10:22', '2017-09-13 19:10:22.123456', 'foo');
|
||||
INSERT INTO `tab` VALUES (toDate('2017-09-24'), toDateTime('2017-09-24 12:05:34', 'UTC'), toDateTime64('2017-09-24 12:05:34.123456', 6, 'UTC'), '2017-09-24', '2017-09-24 12:05:34', '2017-09-24 12:05:34.123456', 'bar');
|
||||
INSERT INTO `tab` VALUES (toDate('2018-01-29'), toDateTime('2018-01-29 02:09:48', 'UTC'), toDateTime64('2018-01-29 02:09:48.123456', 6, 'UTC'), '2018-01-29', '2018-01-29 02:09:48', '2018-01-29 02:09:48.123456', 'qaz');
|
||||
INSERT INTO `tab` VALUES (toDate('2019-02-21'), toDateTime('2019-02-21 15:07:43', 'UTC'), toDateTime64('2019-02-21 15:07:43.123456', 6, 'UTC'), '2019-02-21', '2019-02-21 15:07:43', '2019-02-21 15:07:43.123456', 'qux');
|
||||
|
||||
SELECT toDayOfWeek(d), toDayOfWeek(dt), toDayOfWeek(dt64), toDayOfWeek(str_d), toDayOfWeek(str_dt), toDayOfWeek(str_dt64) FROM tab ORDER BY d;
|
||||
SELECT toWeek(d), toWeek(dt), toWeek(dt64), toWeek(str_d), toWeek(str_dt), toWeek(str_dt64) FROM tab ORDER BY d;
|
||||
SELECT toYearWeek(d), toYearWeek(dt), toYearWeek(dt64), toYearWeek(str_d), toYearWeek(str_dt), toYearWeek(str_dt64) FROM tab ORDER BY d;
|
||||
|
||||
SELECT toDayOfWeek(invalid) FROM `tab`; -- { serverError CANNOT_PARSE_DATETIME }
|
||||
SELECT toWeek(invalid) FROM `tab`; -- { serverError CANNOT_PARSE_DATETIME }
|
||||
SELECT toYearWeek(invalid) FROM `tab`; -- { serverError CANNOT_PARSE_DATETIME }
|
||||
|
||||
DROP TABLE tab;
|
Loading…
Reference in New Issue
Block a user