ClickHouse/src/Functions/CustomWeekTransforms.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

108 lines
3.8 KiB
C++
Raw Normal View History

2019-06-09 15:19:15 +00:00
#pragma once
2021-05-02 19:04:26 +00:00
#include <Columns/ColumnString.h>
2019-06-09 15:19:15 +00:00
#include <Columns/ColumnVector.h>
#include <Columns/ColumnsNumber.h>
#include <Common/DateLUTImpl.h>
#include <Common/Exception.h>
#include <Core/DecimalFunctions.h>
#include <DataTypes/DataTypeString.h>
2021-05-24 13:53:14 +00:00
#include <Functions/DateTimeTransforms.h>
2019-06-09 15:19:15 +00:00
#include <Functions/FunctionHelpers.h>
2021-05-17 07:30:42 +00:00
#include <Functions/IFunction.h>
#include <Functions/extractTimeZoneFromFunctionArguments.h>
#include <IO/ReadBufferFromString.h>
#include <IO/parseDateTimeBestEffort.h>
#include <base/types.h>
2019-06-09 15:19:15 +00:00
2021-05-02 19:04:26 +00:00
2019-06-09 15:19:15 +00:00
namespace DB
{
namespace ErrorCodes
{
extern const int ILLEGAL_COLUMN;
}
2021-05-24 13:53:14 +00:00
template <typename FromType, typename ToType, typename Transform, bool is_extended_result = false>
2021-05-24 13:53:14 +00:00
struct WeekTransformer
2019-06-09 15:19:15 +00:00
{
2021-05-24 13:53:14 +00:00
explicit WeekTransformer(Transform transform_)
: transform(std::move(transform_))
{}
template <typename FromVectorType, typename ToVectorType>
2023-10-13 09:26:36 +00:00
void vector(const FromVectorType & vec_from, ToVectorType & vec_to, UInt8 week_mode, const DateLUTImpl & time_zone) const
2019-06-09 15:19:15 +00:00
{
using ValueType = typename ToVectorType::value_type;
2019-06-09 15:19:15 +00:00
size_t size = vec_from.size();
vec_to.resize(size);
for (size_t i = 0; i < size; ++i)
{
if constexpr (is_extended_result)
vec_to[i] = static_cast<ValueType>(transform.executeExtendedResult(vec_from[i], week_mode, time_zone));
else
vec_to[i] = static_cast<ValueType>(transform.execute(vec_from[i], week_mode, time_zone));
}
2019-06-09 15:19:15 +00:00
}
private:
const Transform transform;
2019-06-09 15:19:15 +00:00
};
template <typename FromDataType, typename ToDataType, bool is_extended_result = false>
2019-06-09 15:19:15 +00:00
struct CustomWeekTransformImpl
{
template <typename Transform>
static ColumnPtr execute(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/, Transform transform = {})
2019-06-09 15:19:15 +00:00
{
const auto op = WeekTransformer<typename FromDataType::FieldType, typename ToDataType::FieldType, Transform, is_extended_result>{std::move(transform)};
2019-06-09 15:19:15 +00:00
2023-10-13 09:26:36 +00:00
static constexpr UInt8 default_week_mode = 0;
UInt8 week_mode = default_week_mode;
2019-06-09 15:19:15 +00:00
if (arguments.size() > 1)
{
2020-10-17 16:48:53 +00:00
if (const auto * week_mode_column = checkAndGetColumnConst<ColumnUInt8>(arguments[1].column.get()))
2019-06-09 15:19:15 +00:00
week_mode = week_mode_column->getValue<UInt8>();
}
2020-10-17 16:48:53 +00:00
const DateLUTImpl & time_zone = extractTimeZoneFromFunctionArguments(arguments, 2, 0);
const ColumnPtr source_col = arguments[0].column;
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()))
2019-06-09 15:19:15 +00:00
{
auto col_to = ToDataType::ColumnType::create();
op.vector(sources->getData(), col_to->getData(), week_mode, time_zone);
2020-10-17 16:48:53 +00:00
return col_to;
2019-06-09 15:19:15 +00:00
}
else
{
throw Exception(ErrorCodes::ILLEGAL_COLUMN,
"Illegal column {} of first argument of function {}",
arguments[0].column->getName(), Transform::name);
2019-06-09 15:19:15 +00:00
}
}
};
}