[branch-2.1](datetime) Fix date floor functions overflow (#35477) (#42238)

pick https://github.com/apache/doris/pull/35477
This commit is contained in:
zclllhhjj
2024-10-22 15:54:53 +08:00
committed by GitHub
parent 9c4ce73dfa
commit 7eec0f8fbb
17 changed files with 363 additions and 219 deletions

View File

@ -20,9 +20,6 @@
#pragma once
#include <type_traits>
#include "vec/core/field.h"
#include "vec/data_types/data_type_number_base.h"
namespace doris::vectorized {

View File

@ -116,13 +116,15 @@ void DataTypeDateV2::cast_to_date_time_v2(const UInt32 from, UInt64& to) {
void DataTypeDateV2::cast_from_date(const Int64 from, UInt32& to) {
auto& to_value = (DateV2Value<DateV2ValueType>&)(to);
auto from_value = binary_cast<Int64, VecDateTimeValue>(from);
to_value.set_time(from_value.year(), from_value.month(), from_value.day(), 0, 0, 0, 0);
to_value.unchecked_set_time(from_value.year(), from_value.month(), from_value.day(), 0, 0, 0,
0);
}
void DataTypeDateV2::cast_from_date_time(const Int64 from, UInt32& to) {
auto& to_value = (DateV2Value<DateV2ValueType>&)(to);
auto from_value = binary_cast<Int64, VecDateTimeValue>(from);
to_value.set_time(from_value.year(), from_value.month(), from_value.day(), 0, 0, 0, 0);
to_value.unchecked_set_time(from_value.year(), from_value.month(), from_value.day(), 0, 0, 0,
0);
}
bool DataTypeDateTimeV2::equals(const IDataType& rhs) const {
@ -202,15 +204,15 @@ void DataTypeDateTimeV2::cast_to_date(const UInt64 from, Int64& to) {
void DataTypeDateTimeV2::cast_from_date(const Int64 from, UInt64& to) {
auto& to_value = (DateV2Value<DateTimeV2ValueType>&)(to);
auto from_value = binary_cast<Int64, VecDateTimeValue>(from);
to_value.set_time(from_value.year(), from_value.month(), from_value.day(), from_value.hour(),
from_value.minute(), from_value.second(), 0);
to_value.unchecked_set_time(from_value.year(), from_value.month(), from_value.day(),
from_value.hour(), from_value.minute(), from_value.second(), 0);
}
void DataTypeDateTimeV2::cast_from_date_time(const Int64 from, UInt64& to) {
auto& to_value = (DateV2Value<DateTimeV2ValueType>&)(to);
auto from_value = binary_cast<Int64, VecDateTimeValue>(from);
to_value.set_time(from_value.year(), from_value.month(), from_value.day(), from_value.hour(),
from_value.minute(), from_value.second(), 0);
to_value.unchecked_set_time(from_value.year(), from_value.month(), from_value.day(),
from_value.hour(), from_value.minute(), from_value.second(), 0);
}
void DataTypeDateTimeV2::cast_to_date_v2(const UInt64 from, UInt32& to) {

View File

@ -432,9 +432,9 @@ class TimeV2Converter : public ColumnTypeConverter {
for (int i = 0; i < rows; ++i) {
const auto& src_value = reinterpret_cast<const SrcCppType&>(src_data[i]);
auto& dst_value = reinterpret_cast<DstCppType&>(data[start_idx + i]);
dst_value.set_time(src_value.year(), src_value.month(), src_value.day(),
src_value.hour(), src_value.minute(), src_value.second(),
src_value.microsecond());
dst_value.unchecked_set_time(src_value.year(), src_value.month(), src_value.day(),
src_value.hour(), src_value.minute(), src_value.second(),
src_value.microsecond());
}
return Status::OK();

View File

@ -58,6 +58,11 @@ namespace doris::vectorized {
return is_nullable || !is_datev2 ? make_nullable(std::make_shared<TYPE>()) \
: std::make_shared<TYPE>();
#define SET_NULLMAP_IF_FALSE(EXPR) \
if (!EXPR) [[unlikely]] { \
null_map[i] = true; \
}
class Field;
class VExpr;

View File

@ -16,8 +16,6 @@
// under the License.
#include <glog/logging.h>
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <boost/iterator/iterator_facade.hpp>
@ -30,6 +28,7 @@
#include "common/status.h"
#include "util/binary_cast.hpp"
#include "util/datetype_cast.hpp"
#include "vec/aggregate_functions/aggregate_function.h"
#include "vec/columns/column.h"
#include "vec/columns/column_const.h"
@ -78,15 +77,14 @@ template <typename Impl, typename DateValueType, typename DeltaValueType, int Ar
class FunctionDateTimeFloorCeil : public IFunction {
public:
using ReturnDataType = std::conditional_t<
std::is_same_v<DateValueType, VecDateTimeValue>, DataTypeDateTime,
date_cast::IsV1<DateValueType>(), DataTypeDateTime,
std::conditional_t<std::is_same_v<DateValueType, DateV2Value<DateV2ValueType>>,
DataTypeDateV2, DataTypeDateTimeV2>>;
using NativeType = std::conditional_t<
std::is_same_v<DateValueType, VecDateTimeValue>, Int64,
std::conditional_t<std::is_same_v<DateValueType, DateV2Value<DateV2ValueType>>, UInt32,
UInt64>>;
using DeltaDataType =
std::conditional_t<std::is_same_v<DeltaValueType, Int32>, DataTypeInt32, DataTypeInt64>;
using DeltaDataType = DataTypeNumber<DeltaValueType>; // int32/64
static constexpr auto name = Impl::name;
static FunctionPtr create() { return std::make_shared<FunctionDateTimeFloorCeil>(); }
@ -153,18 +151,19 @@ public:
null_map->get_data().resize_fill(input_rows_count, false);
if constexpr (ArgNum == 1) {
Impl::template vector<NativeType>(sources->get_data(), col_to->get_data());
Impl::template vector<NativeType>(sources->get_data(), col_to->get_data(),
null_map->get_data());
} else if constexpr (ArgNum == 2) {
const IColumn& delta_column = *block.get_by_position(arguments[1]).column;
if (const auto* delta_const_column =
typeid_cast<const ColumnConst*>(&delta_column)) {
check_and_get_column<ColumnConst>(delta_column)) {
if (block.get_by_position(arguments[1]).type->get_type_id() !=
TypeIndex::Int32) {
// time_round(datetime, const(origin))
Impl::template vector_constant<NativeType>(
sources->get_data(),
delta_const_column->get_field().get<NativeType>(),
col_to->get_data());
col_to->get_data(), null_map->get_data());
} else {
// time_round(datetime,const(period))
Impl::template vector_constant_delta<NativeType, DeltaValueType>(
@ -176,7 +175,7 @@ public:
check_and_get_column<ColumnVector<NativeType>>(delta_column)) {
// time_round(datetime, origin)
Impl::vector_vector(sources->get_data(), delta_vec_column0->get_data(),
col_to->get_data());
col_to->get_data(), null_map->get_data());
} else {
const auto* delta_vec_column1 =
check_and_get_column<ColumnVector<DeltaValueType>>(delta_column);
@ -250,34 +249,42 @@ struct FloorCeilImpl {
static constexpr auto name = Impl::name;
template <typename NativeType>
static void vector(const PaddedPODArray<NativeType>& dates, PaddedPODArray<NativeType>& res) {
static void vector(const PaddedPODArray<NativeType>& dates, PaddedPODArray<NativeType>& res,
NullMap& null_map) {
// time_round(datetime)
for (int i = 0; i < dates.size(); ++i) {
if constexpr (std::is_same_v<NativeType, UInt32>) {
Impl::template time_round<UInt32, DateV2Value<DateV2ValueType>>(dates[i], res[i]);
SET_NULLMAP_IF_FALSE(
(Impl::template time_round<UInt32, DateV2Value<DateV2ValueType>>(dates[i],
res[i])));
} else if constexpr (std::is_same_v<NativeType, UInt64>) {
Impl::template time_round<UInt64, DateV2Value<DateTimeV2ValueType>>(dates[i],
res[i]);
SET_NULLMAP_IF_FALSE(
(Impl::template time_round<UInt64, DateV2Value<DateTimeV2ValueType>>(
dates[i], res[i])));
} else {
Impl::template time_round<Int64, VecDateTimeValue>(dates[i], res[i]);
SET_NULLMAP_IF_FALSE(
(Impl::template time_round<Int64, VecDateTimeValue>(dates[i], res[i])));
}
}
}
template <typename NativeType>
static void vector_constant(const PaddedPODArray<NativeType>& dates, NativeType origin_date,
PaddedPODArray<NativeType>& res) {
PaddedPODArray<NativeType>& res, NullMap& null_map) {
// time_round(datetime, const(origin))
for (int i = 0; i < dates.size(); ++i) {
if constexpr (std::is_same_v<NativeType, UInt32>) {
Impl::template time_round_with_constant_optimization<
UInt32, DateV2Value<DateV2ValueType>, 1>(dates[i], origin_date, res[i]);
SET_NULLMAP_IF_FALSE((Impl::template time_round_with_constant_optimization<
UInt32, DateV2Value<DateV2ValueType>, 1>(
dates[i], origin_date, res[i])));
} else if constexpr (std::is_same_v<NativeType, UInt64>) {
Impl::template time_round_with_constant_optimization<
UInt64, DateV2Value<DateTimeV2ValueType>, 1>(dates[i], origin_date, res[i]);
SET_NULLMAP_IF_FALSE((Impl::template time_round_with_constant_optimization<
UInt64, DateV2Value<DateTimeV2ValueType>, 1>(
dates[i], origin_date, res[i])));
} else {
Impl::template time_round_with_constant_optimization<Int64, VecDateTimeValue, 1>(
dates[i], origin_date, res[i]);
SET_NULLMAP_IF_FALSE((Impl::template time_round_with_constant_optimization<
Int64, VecDateTimeValue, 1>(dates[i], origin_date, res[i])));
}
}
}
@ -292,13 +299,16 @@ struct FloorCeilImpl {
}
for (int i = 0; i < dates.size(); ++i) {
if constexpr (std::is_same_v<NativeType, UInt32>) {
Impl::template time_round<UInt32, DateV2Value<DateV2ValueType>>(dates[i], period,
res[i]);
SET_NULLMAP_IF_FALSE(
(Impl::template time_round<UInt32, DateV2Value<DateV2ValueType>>(
dates[i], period, res[i])));
} else if constexpr (std::is_same_v<NativeType, UInt64>) {
Impl::template time_round<UInt64, DateV2Value<DateTimeV2ValueType>>(dates[i],
period, res[i]);
SET_NULLMAP_IF_FALSE(
(Impl::template time_round<UInt64, DateV2Value<DateTimeV2ValueType>>(
dates[i], period, res[i])));
} else {
Impl::template time_round<Int64, VecDateTimeValue>(dates[i], period, res[i]);
SET_NULLMAP_IF_FALSE((Impl::template time_round<Int64, VecDateTimeValue>(
dates[i], period, res[i])));
}
}
}
@ -306,20 +316,20 @@ struct FloorCeilImpl {
template <typename NativeType, typename DeltaType, UInt32 period>
static void vector_const_const_with_constant_optimization(
const PaddedPODArray<NativeType>& dates, NativeType origin_date,
PaddedPODArray<NativeType>& res) {
PaddedPODArray<NativeType>& res, NullMap& null_map) {
for (int i = 0; i < dates.size(); ++i) {
if constexpr (std::is_same_v<NativeType, UInt32>) {
Impl::template time_round_with_constant_optimization<
UInt32, DateV2Value<DateV2ValueType>, period>(dates[i], origin_date,
res[i]);
SET_NULLMAP_IF_FALSE((Impl::template time_round_with_constant_optimization<
UInt32, DateV2Value<DateV2ValueType>, period>(
dates[i], origin_date, res[i])));
} else if constexpr (std::is_same_v<NativeType, UInt64>) {
Impl::template time_round_with_constant_optimization<
UInt64, DateV2Value<DateTimeV2ValueType>, period>(dates[i], origin_date,
res[i]);
SET_NULLMAP_IF_FALSE((Impl::template time_round_with_constant_optimization<
UInt64, DateV2Value<DateTimeV2ValueType>, period>(
dates[i], origin_date, res[i])));
} else {
Impl::template time_round_with_constant_optimization<Int64, VecDateTimeValue,
period>(dates[i], origin_date,
res[i]);
SET_NULLMAP_IF_FALSE(
(Impl::template time_round_with_constant_optimization<
Int64, VecDateTimeValue, period>(dates[i], origin_date, res[i])));
}
}
}
@ -334,75 +344,77 @@ struct FloorCeilImpl {
switch (period) {
case 1: {
vector_const_const_with_constant_optimization<NativeType, DeltaType, 1>(
dates, origin_date, res);
dates, origin_date, res, null_map);
break;
}
case 2: {
vector_const_const_with_constant_optimization<NativeType, DeltaType, 2>(
dates, origin_date, res);
dates, origin_date, res, null_map);
break;
}
case 3: {
vector_const_const_with_constant_optimization<NativeType, DeltaType, 3>(
dates, origin_date, res);
dates, origin_date, res, null_map);
break;
}
case 4: {
vector_const_const_with_constant_optimization<NativeType, DeltaType, 4>(
dates, origin_date, res);
dates, origin_date, res, null_map);
break;
}
case 5: {
vector_const_const_with_constant_optimization<NativeType, DeltaType, 5>(
dates, origin_date, res);
dates, origin_date, res, null_map);
break;
}
case 6: {
vector_const_const_with_constant_optimization<NativeType, DeltaType, 6>(
dates, origin_date, res);
dates, origin_date, res, null_map);
break;
}
case 7: {
vector_const_const_with_constant_optimization<NativeType, DeltaType, 7>(
dates, origin_date, res);
dates, origin_date, res, null_map);
break;
}
case 8: {
vector_const_const_with_constant_optimization<NativeType, DeltaType, 8>(
dates, origin_date, res);
dates, origin_date, res, null_map);
break;
}
case 9: {
vector_const_const_with_constant_optimization<NativeType, DeltaType, 9>(
dates, origin_date, res);
dates, origin_date, res, null_map);
break;
}
case 10: {
vector_const_const_with_constant_optimization<NativeType, DeltaType, 10>(
dates, origin_date, res);
dates, origin_date, res, null_map);
break;
}
case 11: {
vector_const_const_with_constant_optimization<NativeType, DeltaType, 11>(
dates, origin_date, res);
dates, origin_date, res, null_map);
break;
}
case 12: {
vector_const_const_with_constant_optimization<NativeType, DeltaType, 12>(
dates, origin_date, res);
dates, origin_date, res, null_map);
break;
}
default:
for (int i = 0; i < dates.size(); ++i) {
if constexpr (std::is_same_v<NativeType, UInt32>) {
Impl::template time_round<UInt32, DateV2Value<DateV2ValueType>>(
dates[i], period, origin_date, res[i]);
SET_NULLMAP_IF_FALSE(
(Impl::template time_round<UInt32, DateV2Value<DateV2ValueType>>(
dates[i], period, origin_date, res[i])));
} else if constexpr (std::is_same_v<NativeType, UInt64>) {
Impl::template time_round<UInt64, DateV2Value<DateTimeV2ValueType>>(
dates[i], period, origin_date, res[i]);
SET_NULLMAP_IF_FALSE(
(Impl::template time_round<UInt64, DateV2Value<DateTimeV2ValueType>>(
dates[i], period, origin_date, res[i])));
} else {
Impl::template time_round<Int64, VecDateTimeValue>(dates[i], period,
origin_date, res[i]);
SET_NULLMAP_IF_FALSE((Impl::template time_round<Int64, VecDateTimeValue>(
dates[i], period, origin_date, res[i])));
}
}
}
@ -418,14 +430,16 @@ struct FloorCeilImpl {
}
for (int i = 0; i < dates.size(); ++i) {
if constexpr (std::is_same_v<NativeType, UInt32>) {
Impl::template time_round<UInt32, DateV2Value<DateV2ValueType>>(
dates[i], period, origin_dates[i], res[i]);
SET_NULLMAP_IF_FALSE(
(Impl::template time_round<UInt32, DateV2Value<DateV2ValueType>>(
dates[i], period, origin_dates[i], res[i])));
} else if constexpr (std::is_same_v<NativeType, UInt64>) {
Impl::template time_round<UInt64, DateV2Value<DateTimeV2ValueType>>(
dates[i], period, origin_dates[i], res[i]);
SET_NULLMAP_IF_FALSE(
(Impl::template time_round<UInt64, DateV2Value<DateTimeV2ValueType>>(
dates[i], period, origin_dates[i], res[i])));
} else {
Impl::template time_round<Int64, VecDateTimeValue>(dates[i], period,
origin_dates[i], res[i]);
SET_NULLMAP_IF_FALSE((Impl::template time_round<Int64, VecDateTimeValue>(
dates[i], period, origin_dates[i], res[i])));
}
}
}
@ -441,14 +455,16 @@ struct FloorCeilImpl {
continue;
}
if constexpr (std::is_same_v<NativeType, UInt32>) {
Impl::template time_round<UInt32, DateV2Value<DateV2ValueType>>(
dates[i], periods[i], origin_date, res[i]);
SET_NULLMAP_IF_FALSE(
(Impl::template time_round<UInt32, DateV2Value<DateV2ValueType>>(
dates[i], periods[i], origin_date, res[i])));
} else if constexpr (std::is_same_v<NativeType, UInt64>) {
Impl::template time_round<UInt64, DateV2Value<DateTimeV2ValueType>>(
dates[i], periods[i], origin_date, res[i]);
SET_NULLMAP_IF_FALSE(
(Impl::template time_round<UInt64, DateV2Value<DateTimeV2ValueType>>(
dates[i], periods[i], origin_date, res[i])));
} else {
Impl::template time_round<Int64, VecDateTimeValue>(dates[i], periods[i],
origin_date, res[i]);
SET_NULLMAP_IF_FALSE((Impl::template time_round<Int64, VecDateTimeValue>(
dates[i], periods[i], origin_date, res[i])));
}
}
}
@ -456,19 +472,22 @@ struct FloorCeilImpl {
template <typename NativeType>
static void vector_vector(const PaddedPODArray<NativeType>& dates,
const PaddedPODArray<NativeType>& origin_dates,
PaddedPODArray<NativeType>& res) {
PaddedPODArray<NativeType>& res, NullMap& null_map) {
// time_round(datetime, origin)
for (int i = 0; i < dates.size(); ++i) {
if constexpr (std::is_same_v<NativeType, UInt32>) {
Impl::template time_round_with_constant_optimization<
UInt32, DateV2Value<DateV2ValueType>, 1>(dates[i], origin_dates[i], res[i]);
SET_NULLMAP_IF_FALSE((Impl::template time_round_with_constant_optimization<
UInt32, DateV2Value<DateV2ValueType>, 1>(
dates[i], origin_dates[i], res[i])));
} else if constexpr (std::is_same_v<NativeType, UInt64>) {
Impl::template time_round_with_constant_optimization<
UInt64, DateV2Value<DateTimeV2ValueType>, 1>(dates[i], origin_dates[i],
res[i]);
SET_NULLMAP_IF_FALSE((Impl::template time_round_with_constant_optimization<
UInt64, DateV2Value<DateTimeV2ValueType>, 1>(
dates[i], origin_dates[i], res[i])));
} else {
Impl::template time_round_with_constant_optimization<Int64, VecDateTimeValue, 1>(
dates[i], origin_dates[i], res[i]);
SET_NULLMAP_IF_FALSE(
(Impl::template time_round_with_constant_optimization<Int64,
VecDateTimeValue, 1>(
dates[i], origin_dates[i], res[i])));
}
}
}
@ -484,13 +503,16 @@ struct FloorCeilImpl {
continue;
}
if constexpr (std::is_same_v<NativeType, UInt32>) {
Impl::template time_round<UInt32, DateV2Value<DateV2ValueType>>(dates[i],
periods[i], res[i]);
SET_NULLMAP_IF_FALSE(
(Impl::template time_round<UInt32, DateV2Value<DateV2ValueType>>(
dates[i], periods[i], res[i])));
} else if constexpr (std::is_same_v<NativeType, UInt64>) {
Impl::template time_round<UInt64, DateV2Value<DateTimeV2ValueType>>(
dates[i], periods[i], res[i]);
SET_NULLMAP_IF_FALSE(
(Impl::template time_round<UInt64, DateV2Value<DateTimeV2ValueType>>(
dates[i], periods[i], res[i])));
} else {
Impl::template time_round<Int64, VecDateTimeValue>(dates[i], periods[i], res[i]);
SET_NULLMAP_IF_FALSE((Impl::template time_round<Int64, VecDateTimeValue>(
dates[i], periods[i], res[i])));
}
}
}
@ -507,14 +529,16 @@ struct FloorCeilImpl {
continue;
}
if constexpr (std::is_same_v<NativeType, UInt32>) {
Impl::template time_round<UInt32, DateV2Value<DateV2ValueType>>(
dates[i], periods[i], origin_dates[i], res[i]);
SET_NULLMAP_IF_FALSE(
(Impl::template time_round<UInt32, DateV2Value<DateV2ValueType>>(
dates[i], periods[i], origin_dates[i], res[i])));
} else if constexpr (std::is_same_v<NativeType, UInt64>) {
Impl::template time_round<UInt64, DateV2Value<DateTimeV2ValueType>>(
dates[i], periods[i], origin_dates[i], res[i]);
SET_NULLMAP_IF_FALSE(
(Impl::template time_round<UInt64, DateV2Value<DateTimeV2ValueType>>(
dates[i], periods[i], origin_dates[i], res[i])));
} else {
Impl::template time_round<Int64, VecDateTimeValue>(dates[i], periods[i],
origin_dates[i], res[i]);
SET_NULLMAP_IF_FALSE((Impl::template time_round<Int64, VecDateTimeValue>(
dates[i], periods[i], origin_dates[i], res[i])));
}
}
}
@ -557,15 +581,15 @@ struct TimeRoundOpt {
static constexpr uint64_t MASK_SECOND_FLOOR =
0b1111111111111111111111111111111111111111111100000000000000000000;
// Optimize the performance of the datetimev2 type on the floor operation.
// Now supports unit month hour minute seconde
// Now supports unit month hour minute second. no need to check again when set value for ts
if constexpr (Impl::Unit == MONTH && !std::is_same_v<DateValueType, VecDateTimeValue>) {
int month = ts2.month() - 1;
int new_month = month / period * period;
if (new_month >= 12) {
new_month = new_month % 12;
}
ts1.set_time(ts2.year(), ts2.month(), 1, 0, 0, 0);
ts1.template set_time_unit<TimeUnit::MONTH>(new_month + 1);
ts1.unchecked_set_time(ts2.year(), ts2.month(), 1, 0, 0, 0);
ts1.template unchecked_set_time_unit<TimeUnit::MONTH>(new_month + 1);
}
if constexpr (Impl::Unit == HOUR && !std::is_same_v<DateValueType, VecDateTimeValue>) {
int hour = ts2.hour();
@ -574,7 +598,7 @@ struct TimeRoundOpt {
new_hour = new_hour % 24;
}
ts1.set_int_val(ts2.to_date_int_val() & MASK_HOUR_FLOOR);
ts1.template set_time_unit<TimeUnit::HOUR>(new_hour);
ts1.template unchecked_set_time_unit<TimeUnit::HOUR>(new_hour);
}
if constexpr (Impl::Unit == MINUTE &&
!std::is_same_v<DateValueType, VecDateTimeValue>) {
@ -584,7 +608,7 @@ struct TimeRoundOpt {
new_minute = new_minute % 60;
}
ts1.set_int_val(ts2.to_date_int_val() & MASK_MINUTE_FLOOR);
ts1.template set_time_unit<TimeUnit::MINUTE>(new_minute);
ts1.template unchecked_set_time_unit<TimeUnit::MINUTE>(new_minute);
}
if constexpr (Impl::Unit == SECOND &&
!std::is_same_v<DateValueType, VecDateTimeValue>) {
@ -594,20 +618,20 @@ struct TimeRoundOpt {
new_second = new_second % 60;
}
ts1.set_int_val(ts2.to_date_int_val() & MASK_SECOND_FLOOR);
ts1.template set_time_unit<TimeUnit::SECOND>(new_second);
ts1.template unchecked_set_time_unit<TimeUnit::SECOND>(new_second);
}
}
}
static void floor_opt_one_period(const DateValueType& ts2, DateValueType& ts1) {
if constexpr (Impl::Unit == YEAR) {
ts1.set_time(ts2.year(), 1, 1, 0, 0, 0);
ts1.unchecked_set_time(ts2.year(), 1, 1, 0, 0, 0);
}
if constexpr (Impl::Unit == MONTH) {
ts1.set_time(ts2.year(), ts2.month(), 1, 0, 0, 0);
ts1.unchecked_set_time(ts2.year(), ts2.month(), 1, 0, 0, 0);
}
if constexpr (Impl::Unit == DAY) {
ts1.set_time(ts2.year(), ts2.month(), ts2.day(), 0, 0, 0);
ts1.unchecked_set_time(ts2.year(), ts2.month(), ts2.day(), 0, 0, 0);
}
// only DateTimeV2ValueType type have hour minute second
@ -650,7 +674,7 @@ struct TimeRound {
static constexpr uint64_t MASK_YEAR_MONTH_DAY_HOUR_MINUTE_FOR_DATETIMEV2 = ((uint64_t)-1) >> 38;
template <typename DateValueType>
static void time_round(const DateValueType& ts2, const Int32 period, DateValueType& ts1) {
static bool time_round(const DateValueType& ts2, const Int32 period, DateValueType& ts1) {
int64_t diff;
int64_t trivial_part_ts1;
int64_t trivial_part_ts2;
@ -794,20 +818,21 @@ struct TimeRound {
: count);
bool is_neg = step < 0;
TimeInterval interval(Impl::Unit, is_neg ? -step : step, is_neg);
ts1.template date_add_interval<Impl::Unit, false>(interval);
return ts1.template date_add_interval<Impl::Unit>(interval);
}
template <typename DateValueType, Int32 period>
static void time_round_with_constant_optimization(const DateValueType& ts2,
static bool time_round_with_constant_optimization(const DateValueType& ts2,
DateValueType& ts1) {
time_round<DateValueType>(ts2, period, ts1);
return time_round<DateValueType>(ts2, period, ts1);
}
template <typename DateValueType>
static void time_round(const DateValueType& ts2, DateValueType& ts1) {
static bool time_round(const DateValueType& ts2, DateValueType& ts1) {
static_assert(Impl::Unit != WEEK);
if constexpr (TimeRoundOpt<Impl, DateValueType>::can_use_optimize(1)) {
TimeRoundOpt<Impl, DateValueType>::floor_opt_one_period(ts2, ts1);
return true;
} else {
if constexpr (std::is_same_v<DateValueType, VecDateTimeValue>) {
ts1.reset_zero_by_type(ts2.type());
@ -850,35 +875,36 @@ struct TimeRound {
}
}
TimeInterval interval(Impl::Unit, diff, 1);
ts1.template date_set_interval<Impl::Unit>(interval);
return ts1.template date_set_interval<Impl::Unit>(interval);
}
}
template <typename NativeType, typename DateValueType>
static void time_round(NativeType date, Int32 period, NativeType origin_date, NativeType& res) {
static bool time_round(NativeType date, Int32 period, NativeType origin_date, NativeType& res) {
res = origin_date;
auto ts2 = binary_cast<NativeType, DateValueType>(date);
auto& ts1 = (DateValueType&)(res);
TimeRound<Impl>::template time_round<DateValueType>(ts2, period, ts1);
return TimeRound<Impl>::template time_round<DateValueType>(ts2, period, ts1);
}
template <typename NativeType, typename DateValueType, Int32 period>
static void time_round_with_constant_optimization(NativeType date, NativeType origin_date,
static bool time_round_with_constant_optimization(NativeType date, NativeType origin_date,
NativeType& res) {
res = origin_date;
auto ts2 = binary_cast<NativeType, DateValueType>(date);
auto& ts1 = (DateValueType&)(res);
TimeRound<Impl>::template time_round_with_constant_optimization<DateValueType, period>(ts2,
ts1);
return TimeRound<Impl>::template time_round_with_constant_optimization<DateValueType,
period>(ts2, ts1);
}
template <typename NativeType, typename DateValueType>
static void time_round(NativeType date, Int32 period, NativeType& res) {
static bool time_round(NativeType date, Int32 period, NativeType& res) {
auto ts2 = binary_cast<NativeType, DateValueType>(date);
auto& ts1 = (DateValueType&)(res);
if (TimeRoundOpt<Impl, DateValueType>::can_use_optimize(period)) {
TimeRoundOpt<Impl, DateValueType>::floor_opt(ts2, ts1, period);
return true;
} else {
if constexpr (Impl::Unit != WEEK) {
ts1.from_olap_datetime(FIRST_DAY);
@ -887,20 +913,20 @@ struct TimeRound {
ts1.from_olap_datetime(FIRST_SUNDAY);
}
TimeRound<Impl>::template time_round<DateValueType>(ts2, period, ts1);
return TimeRound<Impl>::template time_round<DateValueType>(ts2, period, ts1);
}
}
template <typename NativeType, typename DateValueType>
static void time_round(NativeType date, NativeType& res) {
static bool time_round(NativeType date, NativeType& res) {
auto ts2 = binary_cast<NativeType, DateValueType>(date);
auto& ts1 = (DateValueType&)(res);
if constexpr (Impl::Unit != WEEK) {
TimeRound<Impl>::template time_round<DateValueType>(ts2, ts1);
return TimeRound<Impl>::template time_round<DateValueType>(ts2, ts1);
} else {
// Only week use the FIRST SUNDAY
ts1.from_olap_datetime(FIRST_SUNDAY);
TimeRound<Impl>::template time_round<DateValueType>(ts2, 1, ts1);
return TimeRound<Impl>::template time_round<DateValueType>(ts2, 1, ts1);
}
}
};

View File

@ -375,9 +375,10 @@ private:
static void _execute_inner_loop(const int& l, const int& r, PaddedPODArray<ReturnType>& res,
NullMap& null_map, size_t index) {
auto& res_val = *reinterpret_cast<DateValueType*>(&res[index]);
// l checked outside
if constexpr (std::is_same_v<DateValueType, VecDateTimeValue>) {
VecDateTimeValue ts_value = VecDateTimeValue();
ts_value.set_time(l, 1, 1, 0, 0, 0);
ts_value.unchecked_set_time(l, 1, 1, 0, 0, 0);
TimeInterval interval(DAY, r - 1, false);
res_val = ts_value;
@ -387,7 +388,7 @@ private:
}
res_val.cast_to_date();
} else {
res_val.set_time(l, 1, 1, 0, 0, 0, 0);
res_val.unchecked_set_time(l, 1, 1, 0, 0, 0, 0);
TimeInterval interval(DAY, r - 1, false);
if (!res_val.template date_add_interval<DAY>(interval)) {
null_map[index] = 1;
@ -1125,17 +1126,17 @@ struct LastDayImpl {
continue;
}
int day = get_last_month_day(ts_value.year(), ts_value.month());
// day is definitely legal
if constexpr (date_cast::IsV1<DateType>()) {
ts_value.set_time(ts_value.year(), ts_value.month(), day, 0, 0, 0);
ts_value.unchecked_set_time(ts_value.year(), ts_value.month(), day, 0, 0, 0);
ts_value.set_type(TIME_DATE);
res_data[i] = binary_cast<VecDateTimeValue, Int64>(ts_value);
} else if constexpr (std::is_same_v<DateType, DataTypeDateV2>) {
ts_value.template set_time_unit<TimeUnit::DAY>(day);
ts_value.template unchecked_set_time_unit<TimeUnit::DAY>(day);
res_data[i] = binary_cast<DateValueType, UInt32>(ts_value);
} else {
ts_value.template set_time_unit<TimeUnit::DAY>(day);
ts_value.set_time(ts_value.year(), ts_value.month(), day, 0, 0, 0, 0);
ts_value.template unchecked_set_time_unit<TimeUnit::DAY>(day);
ts_value.unchecked_set_time(ts_value.year(), ts_value.month(), day, 0, 0, 0, 0);
UInt64 cast_value = binary_cast<DateValueType, UInt64>(ts_value);
DataTypeDateTimeV2::cast_to_date_v2(cast_value, res_data[i]);
}
@ -1150,12 +1151,12 @@ struct LastDayImpl {
auto ts_value = binary_cast<NativeType, DateValueType>(cur_data);
DCHECK(ts_value.is_valid_date());
int day = get_last_month_day(ts_value.year(), ts_value.month());
ts_value.template set_time_unit<TimeUnit::DAY>(day);
ts_value.template unchecked_set_time_unit<TimeUnit::DAY>(day);
if constexpr (std::is_same_v<DateType, DataTypeDateV2>) {
res_data[i] = binary_cast<DateValueType, UInt32>(ts_value);
} else if constexpr (std::is_same_v<DateType, DataTypeDateTimeV2>) {
ts_value.set_time(ts_value.year(), ts_value.month(), day, 0, 0, 0, 0);
ts_value.unchecked_set_time(ts_value.year(), ts_value.month(), day, 0, 0, 0, 0);
UInt64 cast_value = binary_cast<DateValueType, UInt64>(ts_value);
DataTypeDateTimeV2::cast_to_date_v2(cast_value, res_data[i]);
}
@ -1239,7 +1240,7 @@ struct MondayImpl {
}
if constexpr (date_cast::IsV1<DateType>()) {
if (is_special_day(ts_value.year(), ts_value.month(), ts_value.day())) {
ts_value.set_time(ts_value.year(), ts_value.month(), 1, 0, 0, 0);
ts_value.unchecked_set_time(ts_value.year(), ts_value.month(), 1, 0, 0, 0);
ts_value.set_type(TIME_DATE);
res_data[i] = binary_cast<VecDateTimeValue, Int64>(ts_value);
continue;
@ -1255,7 +1256,7 @@ struct MondayImpl {
} else if constexpr (std::is_same_v<DateType, DataTypeDateV2>) {
if (is_special_day(ts_value.year(), ts_value.month(), ts_value.day())) {
ts_value.template set_time_unit<TimeUnit::DAY>(1);
ts_value.template unchecked_set_time_unit<TimeUnit::DAY>(1);
res_data[i] = binary_cast<DateValueType, UInt32>(ts_value);
continue;
}
@ -1268,7 +1269,7 @@ struct MondayImpl {
res_data[i] = binary_cast<DateValueType, UInt32>(ts_value);
} else {
if (is_special_day(ts_value.year(), ts_value.month(), ts_value.day())) {
ts_value.set_time(ts_value.year(), ts_value.month(), 1, 0, 0, 0, 0);
ts_value.unchecked_set_time(ts_value.year(), ts_value.month(), 1, 0, 0, 0, 0);
UInt64 cast_value = binary_cast<DateValueType, UInt64>(ts_value);
DataTypeDateTimeV2::cast_to_date_v2(cast_value, res_data[i]);
continue;
@ -1278,7 +1279,8 @@ struct MondayImpl {
int gap_of_monday = day_of_week - 1;
TimeInterval interval(DAY, gap_of_monday, true);
ts_value.template date_add_interval<DAY>(interval);
ts_value.set_time(ts_value.year(), ts_value.month(), ts_value.day(), 0, 0, 0, 0);
ts_value.unchecked_set_time(ts_value.year(), ts_value.month(), ts_value.day(), 0, 0,
0, 0);
UInt64 cast_value = binary_cast<DateValueType, UInt64>(ts_value);
DataTypeDateTimeV2::cast_to_date_v2(cast_value, res_data[i]);
}
@ -1295,7 +1297,7 @@ struct MondayImpl {
DCHECK(ts_value.is_valid_date());
if constexpr (std::is_same_v<DateType, DataTypeDateV2>) {
if (is_special_day(ts_value.year(), ts_value.month(), ts_value.day())) {
ts_value.template set_time_unit<TimeUnit::DAY>(1);
ts_value.template unchecked_set_time_unit<TimeUnit::DAY>(1);
res_data[i] = binary_cast<DateValueType, UInt32>(ts_value);
continue;
}
@ -1307,7 +1309,7 @@ struct MondayImpl {
res_data[i] = binary_cast<DateValueType, UInt32>(ts_value);
} else if constexpr (std::is_same_v<DateType, DataTypeDateTimeV2>) {
if (is_special_day(ts_value.year(), ts_value.month(), ts_value.day())) {
ts_value.set_time(ts_value.year(), ts_value.month(), 1, 0, 0, 0, 0);
ts_value.unchecked_set_time(ts_value.year(), ts_value.month(), 1, 0, 0, 0, 0);
UInt64 cast_value = binary_cast<DateValueType, UInt64>(ts_value);
DataTypeDateTimeV2::cast_to_date_v2(cast_value, res_data[i]);
continue;
@ -1317,7 +1319,8 @@ struct MondayImpl {
int gap_of_monday = day_of_week - 1;
TimeInterval interval(DAY, gap_of_monday, true);
ts_value.template date_add_interval<DAY>(interval);
ts_value.set_time(ts_value.year(), ts_value.month(), ts_value.day(), 0, 0, 0, 0);
ts_value.unchecked_set_time(ts_value.year(), ts_value.month(), ts_value.day(), 0, 0,
0, 0);
UInt64 cast_value = binary_cast<DateValueType, UInt64>(ts_value);
DataTypeDateTimeV2::cast_to_date_v2(cast_value, res_data[i]);
}

View File

@ -80,7 +80,9 @@ bool VecDateTimeValue::check_range(uint32_t year, uint32_t month, uint32_t day,
}
bool VecDateTimeValue::check_date(uint32_t year, uint32_t month, uint32_t day) {
if (month == 2 && day == 29 && doris::is_leap(year)) return false;
if (month == 2 && day == 29 && doris::is_leap(year)) {
return false;
}
if (year > 9999 || month == 0 || month > 12 || day > S_DAYS_IN_MONTH[month] || day == 0) {
return true;
}
@ -536,7 +538,7 @@ bool VecDateTimeValue::get_date_from_daynr(uint64_t daynr) {
if (check_range(year, month, day, 0, 0, 0, _type)) {
return false;
}
set_time(year, month, day, _hour, _minute, _second);
unchecked_set_time(year, month, day, _hour, _minute, _second);
return true;
}
@ -1810,8 +1812,8 @@ VecDateTimeValue VecDateTimeValue::local_time() {
return value;
}
void VecDateTimeValue::set_time(uint32_t year, uint32_t month, uint32_t day, uint32_t hour,
uint32_t minute, uint32_t second) {
void VecDateTimeValue::unchecked_set_time(uint32_t year, uint32_t month, uint32_t day,
uint32_t hour, uint32_t minute, uint32_t second) {
_year = year;
_month = month;
_day = day;
@ -1892,10 +1894,10 @@ bool VecDateTimeValue::datetime_trunc() {
template <typename T>
void VecDateTimeValue::create_from_date_v2(DateV2Value<T>& value, TimeType type) {
if constexpr (std::is_same_v<T, DateV2ValueType>) {
this->set_time(value.year(), value.month(), value.day(), 0, 0, 0);
this->unchecked_set_time(value.year(), value.month(), value.day(), 0, 0, 0);
} else {
this->set_time(value.year(), value.month(), value.day(), value.hour(), value.minute(),
value.second());
this->unchecked_set_time(value.year(), value.month(), value.day(), value.hour(),
value.minute(), value.second());
}
this->set_type(type);
this->_neg = 0;
@ -1946,7 +1948,9 @@ bool DateV2Value<T>::is_invalid(uint32_t year, uint32_t month, uint32_t day, uin
if (year > MAX_YEAR) {
return true;
}
if (month == 2 && day == 29 && doris::is_leap(year)) return false;
if (month == 2 && day == 29 && doris::is_leap(year)) {
return false;
}
if (month == 0 || month > 12 || day > S_DAYS_IN_MONTH[month] || day == 0) {
return true;
}
@ -2811,7 +2815,7 @@ bool date_day_offset_dict::get_dict_init() {
date_day_offset_dict::date_day_offset_dict() {
DateV2Value<DateV2ValueType> d;
// Init days before epoch.
d.set_time(1969, 12, 31, 0, 0, 0, 0);
d.unchecked_set_time(1969, 12, 31, 0, 0, 0, 0);
for (int i = 0; i < DAY_BEFORE_EPOCH; ++i) {
DATE_DAY_OFFSET_ITEMS[DAY_BEFORE_EPOCH - i - 1] = d;
DATE_DAY_OFFSET_DICT[d.year() - START_YEAR][d.month() - 1][d.day() - 1] =
@ -2819,7 +2823,7 @@ date_day_offset_dict::date_day_offset_dict() {
d -= 1;
}
// Init epoch day.
d.set_time(1970, 1, 1, 0, 0, 0, 0);
d.unchecked_set_time(1970, 1, 1, 0, 0, 0, 0);
DATE_DAY_OFFSET_ITEMS[DAY_BEFORE_EPOCH] = d;
DATE_DAY_OFFSET_DICT[d.year() - START_YEAR][d.month() - 1][d.day() - 1] =
calc_daynr(d.year(), d.month(), d.day());
@ -2851,7 +2855,7 @@ uint32_t DateV2Value<T>::set_date_uint32(uint32_t int_val) {
if (is_invalid(conv.dt.year(), conv.dt.month(), conv.dt.day(), 0, 0, 0, 0)) {
return 0;
}
this->set_time(conv.dt.year(), conv.dt.month(), conv.dt.day(), 0, 0, 0, 0);
this->unchecked_set_time(conv.dt.year(), conv.dt.month(), conv.dt.day(), 0, 0, 0, 0);
return int_val;
}
@ -2868,8 +2872,8 @@ uint64_t DateV2Value<T>::set_datetime_uint64(uint64_t int_val) {
conv.dt.second(), conv.dt.microsecond())) {
return 0;
}
this->set_time(conv.dt.year(), conv.dt.month(), conv.dt.day(), conv.dt.hour(), conv.dt.minute(),
conv.dt.second(), conv.dt.microsecond());
this->unchecked_set_time(conv.dt.year(), conv.dt.month(), conv.dt.day(), conv.dt.hour(),
conv.dt.minute(), conv.dt.second(), conv.dt.microsecond());
return int_val;
}
@ -2947,14 +2951,17 @@ bool DateV2Value<T>::get_date_from_daynr(uint64_t daynr) {
}
}
set_time(year, month, day, this->hour(), this->minute(), this->second(), this->microsecond());
unchecked_set_time(year, month, day, this->hour(), this->minute(), this->second(),
this->microsecond());
return true;
}
template <typename T>
template <TimeUnit unit, typename TO>
bool DateV2Value<T>::date_add_interval(const TimeInterval& interval, DateV2Value<TO>& to_value) {
if (!is_valid_date()) return false;
if (!is_valid_date()) {
return false;
}
int sign = interval.is_neg ? -1 : 1;
@ -2990,7 +2997,8 @@ bool DateV2Value<T>::date_add_interval(const TimeInterval& interval, DateV2Value
if (!to_value.get_date_from_daynr(day_nr)) {
return false;
}
to_value.set_time(seconds / 3600, (seconds / 60) % 60, seconds % 60, microseconds);
PROPAGATE_FALSE(to_value.check_range_and_set_time(
0, 0, 0, seconds / 3600, (seconds / 60) % 60, seconds % 60, microseconds, true));
} else if constexpr (unit == YEAR) {
// This only change year information
PROPAGATE_FALSE(to_value.template set_time_unit<TimeUnit::YEAR>(date_v2_value_.year_ +
@ -3024,7 +3032,9 @@ template <typename T>
template <TimeUnit unit, bool need_check>
bool DateV2Value<T>::date_add_interval(const TimeInterval& interval) {
if constexpr (need_check) {
if (!is_valid_date()) return false;
if (!is_valid_date()) {
return false;
}
}
int sign = interval.is_neg ? -1 : 1;
@ -3062,7 +3072,9 @@ bool DateV2Value<T>::date_add_interval(const TimeInterval& interval) {
return false;
}
if constexpr (is_datetime) {
this->set_time(seconds / 3600, (seconds / 60) % 60, seconds % 60, microseconds);
PROPAGATE_FALSE(this->check_range_and_set_time(0, 0, 0, seconds / 3600,
(seconds / 60) % 60, seconds % 60,
microseconds, true));
}
} else if constexpr (unit == YEAR) {
// This only change year information
@ -3111,14 +3123,15 @@ bool DateV2Value<T>::date_set_interval(const TimeInterval& interval) {
return false;
}
if constexpr (is_datetime) {
this->set_time(seconds / 3600, (seconds / 60) % 60, seconds % 60, 0);
PROPAGATE_FALSE(this->check_range_and_set_time(
0, 0, 0, seconds / 3600, (seconds / 60) % 60, seconds % 60, 0, true));
}
} else if constexpr (unit == YEAR) {
this->set_time(0, 1, 1, 0, 0, 0, 0);
this->unchecked_set_time(0, 1, 1, 0, 0, 0, 0);
PROPAGATE_FALSE(this->template set_time_unit<TimeUnit::YEAR>(interval.year));
} else if constexpr (unit == MONTH) {
// This will change month and year information, maybe date.
this->set_time(0, 1, 1, 0, 0, 0, 0);
this->unchecked_set_time(0, 1, 1, 0, 0, 0, 0);
int64_t months = 12 * interval.year + interval.month;
PROPAGATE_FALSE(this->template set_time_unit<TimeUnit::YEAR>(months / 12));
PROPAGATE_FALSE(this->template set_time_unit<TimeUnit::MONTH>((months % 12) + 1));
@ -3323,7 +3336,7 @@ void DateV2Value<T>::from_unixtime(int64_t timestamp, const cctz::time_zone& ctz
// there's no overflow check since it's hot path
set_time(tp.year(), tp.month(), tp.day(), tp.hour(), tp.minute(), tp.second(), 0);
unchecked_set_time(tp.year(), tp.month(), tp.day(), tp.hour(), tp.minute(), tp.second(), 0);
}
template <typename T>
@ -3347,8 +3360,8 @@ void DateV2Value<T>::from_unixtime(std::pair<int64_t, int64_t> timestamp,
const auto tp = cctz::convert(t, ctz);
set_time(tp.year(), tp.month(), tp.day(), tp.hour(), tp.minute(), tp.second(),
timestamp.second);
unchecked_set_time(tp.year(), tp.month(), tp.day(), tp.hour(), tp.minute(), tp.second(),
timestamp.second);
}
template <typename T>
@ -3376,8 +3389,8 @@ void DateV2Value<T>::from_unixtime(int64_t timestamp, int32_t nano_seconds,
scale = 6;
}
set_time(tp.year(), tp.month(), tp.day(), tp.hour(), tp.minute(), tp.second(),
nano_seconds / int_exp10(9 - scale) * int_exp10(6 - scale));
unchecked_set_time(tp.year(), tp.month(), tp.day(), tp.hour(), tp.minute(), tp.second(),
nano_seconds / int_exp10(9 - scale) * int_exp10(6 - scale));
}
template <typename T>
@ -3398,8 +3411,8 @@ const char* DateV2Value<T>::day_name() const {
}
template <typename T>
void DateV2Value<T>::set_time(uint16_t year, uint8_t month, uint8_t day, uint8_t hour,
uint8_t minute, uint8_t second, uint32_t microsecond) {
void DateV2Value<T>::unchecked_set_time(uint16_t year, uint8_t month, uint8_t day, uint8_t hour,
uint8_t minute, uint8_t second, uint32_t microsecond) {
date_v2_value_.year_ = year;
date_v2_value_.month_ = month;
date_v2_value_.day_ = day;
@ -3412,7 +3425,8 @@ void DateV2Value<T>::set_time(uint16_t year, uint8_t month, uint8_t day, uint8_t
}
template <typename T>
void DateV2Value<T>::set_time(uint8_t hour, uint8_t minute, uint8_t second, uint32_t microsecond) {
void DateV2Value<T>::unchecked_set_time(uint8_t hour, uint8_t minute, uint8_t second,
uint32_t microsecond) {
if constexpr (is_datetime) {
date_v2_value_.hour_ = hour;
date_v2_value_.minute_ = minute;

View File

@ -291,9 +291,6 @@ public:
template <typename T>
void create_from_date_v2(DateV2Value<T>&& value, TimeType type);
void set_time(uint32_t year, uint32_t month, uint32_t day, uint32_t hour, uint32_t minute,
uint32_t second);
// Converted from Olap Date or Datetime
bool from_olap_datetime(uint64_t datetime) {
_neg = 0;
@ -416,16 +413,20 @@ public:
// Will check its type
int64_t to_int64() const;
bool check_range_and_set_time(uint32_t year, uint32_t month, uint32_t day, uint32_t hour,
uint32_t minute, uint32_t second, uint16_t type) {
[[nodiscard]] bool check_range_and_set_time(uint32_t year, uint32_t month, uint32_t day,
uint32_t hour, uint32_t minute, uint32_t second,
uint16_t type) {
if (check_range(year, month, day, hour, minute, second, type)) {
return false;
}
set_time(year, month, day, hour, minute, second);
unchecked_set_time(year, month, day, hour, minute, second);
return true;
}
int32_t daynr() const { return calc_daynr(_year, _month, _day); }
void unchecked_set_time(uint32_t year, uint32_t month, uint32_t day, uint32_t hour,
uint32_t minute, uint32_t second);
int64_t daynr() const { return calc_daynr(_year, _month, _day); }
int year() const { return _year; }
int month() const { return _month; }
@ -782,11 +783,6 @@ public:
return datetime;
}
void set_time(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute,
uint8_t second, uint32_t microsecond = 0);
void set_time(uint8_t hour, uint8_t minute, uint8_t second, uint32_t microsecond);
void set_microsecond(uint32_t microsecond);
bool from_olap_date(uint64_t date) {
@ -876,21 +872,27 @@ public:
uint8_t minute, uint8_t second, uint32_t microsecond,
bool only_time_part = false);
bool check_range_and_set_time(uint16_t year, uint8_t month, uint8_t day, uint8_t hour,
uint8_t minute, uint8_t second, uint32_t microsecond,
bool only_time_part = false) {
[[nodiscard]] bool check_range_and_set_time(uint16_t year, uint8_t month, uint8_t day,
uint8_t hour, uint8_t minute, uint8_t second,
uint32_t microsecond, bool only_time_part = false) {
if (is_invalid(year, month, day, hour, minute, second, microsecond, only_time_part)) {
return false;
}
if (only_time_part) {
set_time(0, 0, 0, hour, minute, second, microsecond);
// not change date part
unchecked_set_time(hour, minute, second, microsecond);
} else {
set_time(year, month, day, hour, minute, second, microsecond);
unchecked_set_time(year, month, day, hour, minute, second, microsecond);
}
return true;
}
int32_t daynr() const {
void unchecked_set_time(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute,
uint8_t second, uint32_t microsecond = 0);
void unchecked_set_time(uint8_t hour, uint8_t minute, uint8_t second, uint32_t microsecond);
int64_t daynr() const {
return calc_daynr(date_v2_value_.year_, date_v2_value_.month_, date_v2_value_.day_);
}
@ -1174,9 +1176,8 @@ public:
bool get_date_from_daynr(uint64_t);
// should do check
template <TimeUnit unit>
bool set_time_unit(uint32_t val) {
[[nodiscard]] bool set_time_unit(uint32_t val) {
// is uint so need check upper bound only
if constexpr (unit == TimeUnit::YEAR) {
if (val > MAX_YEAR) [[unlikely]] {
@ -1202,6 +1203,8 @@ public:
return false;
}
date_v2_value_.hour_ = val;
} else {
DCHECK(false) << "shouldn't set for date";
}
} else if constexpr (unit == TimeUnit::MINUTE) {
if constexpr (is_datetime) {
@ -1209,6 +1212,8 @@ public:
return false;
}
date_v2_value_.minute_ = val;
} else {
DCHECK(false) << "shouldn't set for date";
}
} else if constexpr (unit == TimeUnit::SECOND) {
if constexpr (is_datetime) {
@ -1216,6 +1221,8 @@ public:
return false;
}
date_v2_value_.second_ = val;
} else {
DCHECK(false) << "shouldn't set for date";
}
} else if constexpr (unit == TimeUnit::MICROSECOND) {
if constexpr (is_datetime) {
@ -1223,10 +1230,49 @@ public:
return false;
}
date_v2_value_.microsecond_ = val;
} else {
DCHECK(false) << "shouldn't set for date";
}
}
return true;
}
template <TimeUnit unit>
void unchecked_set_time_unit(uint32_t val) {
// is uint so need check upper bound only
if constexpr (unit == TimeUnit::YEAR) {
date_v2_value_.year_ = val;
} else if constexpr (unit == TimeUnit::MONTH) {
date_v2_value_.month_ = val;
} else if constexpr (unit == TimeUnit::DAY) {
date_v2_value_.day_ = val;
} else if constexpr (unit == TimeUnit::HOUR) {
if constexpr (is_datetime) {
date_v2_value_.hour_ = val;
} else {
DCHECK(false) << "shouldn't set for date";
}
} else if constexpr (unit == TimeUnit::MINUTE) {
if constexpr (is_datetime) {
date_v2_value_.minute_ = val;
} else {
DCHECK(false) << "shouldn't set for date";
}
} else if constexpr (unit == TimeUnit::SECOND) {
if constexpr (is_datetime) {
date_v2_value_.second_ = val;
} else {
DCHECK(false) << "shouldn't set for date";
}
} else if constexpr (unit == TimeUnit::MICROSECOND) {
if constexpr (is_datetime) {
date_v2_value_.microsecond_ = val;
} else {
DCHECK(false) << "shouldn't set for date";
}
}
}
operator int64_t() const { return to_int64(); }
int64_t to_int64() const {

View File

@ -457,7 +457,7 @@ static void generate_data(vectorized::Block* block, int8_t k1, int16_t k2, int32
columns[2]->insert_data((const char*)&c3_int, sizeof(c3));
DateV2Value<DateV2ValueType> c4;
c4.set_time(2022, 6, 6, 0, 0, 0, 0);
c4.unchecked_set_time(2022, 6, 6, 0, 0, 0, 0);
uint32_t c4_int = c4.to_date_int_val();
columns[3]->insert_data((const char*)&c4_int, sizeof(c4));

View File

@ -195,7 +195,7 @@ static void generate_data(vectorized::Block* block, int8_t k1, int16_t k2, int32
columns[2]->insert_data((const char*)&c3_int, sizeof(c3));
DateV2Value<DateV2ValueType> c4;
c4.set_time(2022, 6, 6, 0, 0, 0, 0);
c4.unchecked_set_time(2022, 6, 6, 0, 0, 0, 0);
uint32_t c4_int = c4.to_date_int_val();
columns[3]->insert_data((const char*)&c4_int, sizeof(c4));

View File

@ -132,7 +132,7 @@ TEST_F(VSequenceMatchTest, testMatchSerialize) {
auto column_timestamp = ColumnVector<Int64>::create();
for (int i = 0; i < NUM_CONDS; i++) {
VecDateTimeValue time_value;
time_value.set_time(2022, 11, 2, 0, 0, i);
time_value.unchecked_set_time(2022, 11, 2, 0, 0, i);
column_timestamp->insert_data((char*)&time_value, 0);
}
@ -203,7 +203,7 @@ TEST_F(VSequenceMatchTest, testCountSerialize) {
auto column_timestamp = ColumnVector<Int64>::create();
for (int i = 0; i < NUM_CONDS; i++) {
VecDateTimeValue time_value;
time_value.set_time(2022, 11, 2, 0, 0, i);
time_value.unchecked_set_time(2022, 11, 2, 0, 0, i);
column_timestamp->insert_data((char*)&time_value, 0);
}
@ -268,7 +268,7 @@ TEST_F(VSequenceMatchTest, testMatchReverseSortedSerializeMerge) {
auto column_timestamp = ColumnVector<Int64>::create();
for (int i = 0; i < NUM_CONDS; i++) {
VecDateTimeValue time_value;
time_value.set_time(2022, 11, 2, 0, 0, NUM_CONDS - i);
time_value.unchecked_set_time(2022, 11, 2, 0, 0, NUM_CONDS - i);
column_timestamp->insert_data((char*)&time_value, 0);
}
@ -309,7 +309,7 @@ TEST_F(VSequenceMatchTest, testMatchReverseSortedSerializeMerge) {
auto column_timestamp2 = ColumnVector<Int64>::create();
for (int i = 0; i < NUM_CONDS; i++) {
VecDateTimeValue time_value;
time_value.set_time(2022, 11, 2, 0, 1, NUM_CONDS - i);
time_value.unchecked_set_time(2022, 11, 2, 0, 1, NUM_CONDS - i);
column_timestamp2->insert_data((char*)&time_value, 0);
}
@ -357,7 +357,7 @@ TEST_F(VSequenceMatchTest, testCountReverseSortedSerializeMerge) {
auto column_timestamp = ColumnVector<Int64>::create();
for (int i = 0; i < NUM_CONDS; i++) {
VecDateTimeValue time_value;
time_value.set_time(2022, 11, 2, 0, 0, NUM_CONDS - i);
time_value.unchecked_set_time(2022, 11, 2, 0, 0, NUM_CONDS - i);
column_timestamp->insert_data((char*)&time_value, 0);
}
@ -398,7 +398,7 @@ TEST_F(VSequenceMatchTest, testCountReverseSortedSerializeMerge) {
auto column_timestamp2 = ColumnVector<Int64>::create();
for (int i = 0; i < NUM_CONDS; i++) {
VecDateTimeValue time_value;
time_value.set_time(2022, 11, 2, 0, 1, NUM_CONDS - i);
time_value.unchecked_set_time(2022, 11, 2, 0, 1, NUM_CONDS - i);
column_timestamp2->insert_data((char*)&time_value, 0);
}

View File

@ -105,7 +105,7 @@ TEST_F(VWindowFunnelTest, testSerialize) {
auto column_timestamp = ColumnVector<Int64>::create();
for (int i = 0; i < NUM_CONDS; i++) {
VecDateTimeValue time_value;
time_value.set_time(2022, 2, 28, 0, 0, i);
time_value.unchecked_set_time(2022, 2, 28, 0, 0, i);
column_timestamp->insert_data((char*)&time_value, 0);
}
auto column_event1 = ColumnVector<UInt8>::create();
@ -178,7 +178,7 @@ TEST_F(VWindowFunnelTest, testMax4SortedNoMerge) {
auto column_timestamp = ColumnVector<Int64>::create();
for (int i = 0; i < NUM_CONDS; i++) {
VecDateTimeValue time_value;
time_value.set_time(2022, 2, 28, 0, 0, i);
time_value.unchecked_set_time(2022, 2, 28, 0, 0, i);
column_timestamp->insert_data((char*)&time_value, 0);
}
auto column_event1 = ColumnVector<UInt8>::create();
@ -239,7 +239,7 @@ TEST_F(VWindowFunnelTest, testMax4SortedMerge) {
auto column_timestamp = ColumnVector<Int64>::create();
for (int i = 0; i < NUM_CONDS; i++) {
VecDateTimeValue time_value;
time_value.set_time(2022, 2, 28, 0, 0, i);
time_value.unchecked_set_time(2022, 2, 28, 0, 0, i);
column_timestamp->insert_data((char*)&time_value, 0);
}
auto column_event1 = ColumnVector<UInt8>::create();
@ -306,7 +306,7 @@ TEST_F(VWindowFunnelTest, testMax4ReverseSortedNoMerge) {
auto column_timestamp = ColumnVector<Int64>::create();
for (int i = 0; i < NUM_CONDS; i++) {
VecDateTimeValue time_value;
time_value.set_time(2022, 2, 28, 0, 0, NUM_CONDS - i);
time_value.unchecked_set_time(2022, 2, 28, 0, 0, NUM_CONDS - i);
column_timestamp->insert_data((char*)&time_value, 0);
}
auto column_event1 = ColumnVector<UInt8>::create();
@ -368,7 +368,7 @@ TEST_F(VWindowFunnelTest, testMax4ReverseSortedMerge) {
auto column_timestamp = ColumnVector<Int64>::create();
for (int i = 0; i < NUM_CONDS; i++) {
VecDateTimeValue time_value;
time_value.set_time(2022, 2, 28, 0, 0, NUM_CONDS - i);
time_value.unchecked_set_time(2022, 2, 28, 0, 0, NUM_CONDS - i);
column_timestamp->insert_data((char*)&time_value, 0);
}
auto column_event1 = ColumnVector<UInt8>::create();

View File

@ -478,7 +478,7 @@ TEST(TEST_VEXPR, LITERALTEST) {
uint8_t second = 46;
uint32_t microsecond = 999999; // target scale is 4, so the microsecond will be rounded up
DateV2Value<DateTimeV2ValueType> datetime_v2;
datetime_v2.set_time(year, month, day, hour, minute, second, microsecond);
datetime_v2.unchecked_set_time(year, month, day, hour, minute, second, microsecond);
std::string date = datetime_v2.debug_string();
VLiteral literal(create_literal<TYPE_DATETIMEV2, std::string>(date, 4));

View File

@ -32,7 +32,7 @@ TEST(VDateTimeValueTest, date_v2_to_uint32_test) {
uint8_t day = 24;
DateV2Value<DateV2ValueType> date_v2;
date_v2.set_time(year, month, day, 0, 0, 0, 0);
date_v2.unchecked_set_time(year, month, day, 0, 0, 0, 0);
EXPECT_TRUE(date_v2.year() == year);
EXPECT_TRUE(date_v2.month() == month);
@ -53,7 +53,7 @@ TEST(VDateTimeValueTest, datetime_v2_to_uint64_test) {
uint32_t microsecond = 999999;
DateV2Value<DateTimeV2ValueType> datetime_v2;
datetime_v2.set_time(year, month, day, hour, minute, second, microsecond);
datetime_v2.unchecked_set_time(year, month, day, hour, minute, second, microsecond);
EXPECT_TRUE(datetime_v2.year() == year);
EXPECT_TRUE(datetime_v2.month() == month);
@ -411,7 +411,7 @@ TEST(VDateTimeValueTest, date_v2_to_string_test) {
{
DateV2Value<DateV2ValueType> date_v2;
date_v2.set_time(year, month, day, 0, 0, 0, 0);
date_v2.unchecked_set_time(year, month, day, 0, 0, 0, 0);
char buf[30];
int len = date_v2.to_buffer(buf);
@ -420,7 +420,7 @@ TEST(VDateTimeValueTest, date_v2_to_string_test) {
{
DateV2Value<DateTimeV2ValueType> date_v2;
date_v2.set_time(year, month, day, hour, minute, second, ms);
date_v2.unchecked_set_time(year, month, day, hour, minute, second, ms);
char buf[30];
int len = date_v2.to_buffer(buf);
@ -429,7 +429,7 @@ TEST(VDateTimeValueTest, date_v2_to_string_test) {
{
DateV2Value<DateTimeV2ValueType> date_v2;
date_v2.set_time(year, month, day, hour, minute, second, ms);
date_v2.unchecked_set_time(year, month, day, hour, minute, second, ms);
char buf[30];
int len = date_v2.to_buffer(buf, 3);
@ -438,7 +438,7 @@ TEST(VDateTimeValueTest, date_v2_to_string_test) {
{
DateV2Value<DateTimeV2ValueType> date_v2;
date_v2.set_time(year, month, day, hour, minute, second, ms);
date_v2.unchecked_set_time(year, month, day, hour, minute, second, ms);
char buf[30];
int len = date_v2.to_buffer(buf, 2);
@ -447,7 +447,7 @@ TEST(VDateTimeValueTest, date_v2_to_string_test) {
{
DateV2Value<DateTimeV2ValueType> date_v2;
date_v2.set_time(year, month, day, hour, minute, second, ms);
date_v2.unchecked_set_time(year, month, day, hour, minute, second, ms);
char buf[30];
int len = date_v2.to_buffer(buf, 6);
@ -456,7 +456,7 @@ TEST(VDateTimeValueTest, date_v2_to_string_test) {
{
DateV2Value<DateTimeV2ValueType> date_v2;
date_v2.set_time(year, month, day, hour, minute, second, 0);
date_v2.unchecked_set_time(year, month, day, hour, minute, second, 0);
char buf[30];
int len = date_v2.to_buffer(buf);

View File

@ -183,7 +183,7 @@ TEST_F(PartitionTransformersTest, test_date_bucket_transform) {
auto column = ColumnDateV2::create();
auto& date_v2_data = column->get_data();
DateV2Value<DateV2ValueType> value;
value.set_time(2017, 11, 16, 0, 0, 0, 0); // -653330422
value.unchecked_set_time(2017, 11, 16, 0, 0, 0, 0); // -653330422
date_v2_data.push_back(*reinterpret_cast<vectorized::UInt32*>(&value));
ColumnWithTypeAndName test_date(column->get_ptr(), std::make_shared<DataTypeDateV2>(),
"test_date");
@ -206,7 +206,7 @@ TEST_F(PartitionTransformersTest, test_timestamp_bucket_transform) {
auto column = ColumnDateTimeV2::create();
auto& datetime_v2_data = column->get_data();
DateV2Value<DateTimeV2ValueType> value;
value.set_time(2017, 11, 16, 22, 31, 8, 0); // -2047944441
value.unchecked_set_time(2017, 11, 16, 22, 31, 8, 0); // -2047944441
datetime_v2_data.push_back(*reinterpret_cast<vectorized::UInt64*>(&value));
ColumnWithTypeAndName test_timestamp(column->get_ptr(), std::make_shared<DataTypeDateTimeV2>(),
"test_timestamp");
@ -250,7 +250,7 @@ TEST_F(PartitionTransformersTest, test_date_year_transform) {
auto column = ColumnDateV2::create();
auto& date_v2_data = column->get_data();
DateV2Value<DateV2ValueType> value;
value.set_time(2017, 11, 16, 0, 0, 0, 0);
value.unchecked_set_time(2017, 11, 16, 0, 0, 0, 0);
date_v2_data.push_back(*reinterpret_cast<vectorized::UInt32*>(&value));
ColumnWithTypeAndName test_date(column->get_ptr(), std::make_shared<DataTypeDateV2>(),
"test_date");
@ -276,7 +276,7 @@ TEST_F(PartitionTransformersTest, test_timestamp_year_transform) {
auto column = ColumnDateTimeV2::create();
auto& datetime_v2_data = column->get_data();
DateV2Value<DateTimeV2ValueType> value;
value.set_time(2017, 11, 16, 22, 31, 8, 0);
value.unchecked_set_time(2017, 11, 16, 22, 31, 8, 0);
datetime_v2_data.push_back(*reinterpret_cast<vectorized::UInt64*>(&value));
ColumnWithTypeAndName test_timestamp(column->get_ptr(), std::make_shared<DataTypeDateTimeV2>(),
"test_timestamp");
@ -302,7 +302,7 @@ TEST_F(PartitionTransformersTest, test_date_month_transform) {
auto column = ColumnDateV2::create();
auto& date_v2_data = column->get_data();
DateV2Value<DateV2ValueType> value;
value.set_time(2017, 11, 16, 0, 0, 0, 0);
value.unchecked_set_time(2017, 11, 16, 0, 0, 0, 0);
date_v2_data.push_back(*reinterpret_cast<vectorized::UInt32*>(&value));
ColumnWithTypeAndName test_date(column->get_ptr(), std::make_shared<DataTypeDateV2>(),
"test_date");
@ -328,7 +328,7 @@ TEST_F(PartitionTransformersTest, test_timestamp_month_transform) {
auto column = ColumnDateTimeV2::create();
auto& datetime_v2_data = column->get_data();
DateV2Value<DateTimeV2ValueType> value;
value.set_time(2017, 11, 16, 22, 31, 8, 0);
value.unchecked_set_time(2017, 11, 16, 22, 31, 8, 0);
datetime_v2_data.push_back(*reinterpret_cast<vectorized::UInt64*>(&value));
ColumnWithTypeAndName test_timestamp(column->get_ptr(), std::make_shared<DataTypeDateTimeV2>(),
"test_timestamp");
@ -354,7 +354,7 @@ TEST_F(PartitionTransformersTest, test_date_day_transform) {
auto column = ColumnDateV2::create();
auto& date_v2_data = column->get_data();
DateV2Value<DateV2ValueType> value;
value.set_time(2017, 11, 16, 0, 0, 0, 0);
value.unchecked_set_time(2017, 11, 16, 0, 0, 0, 0);
date_v2_data.push_back(*reinterpret_cast<vectorized::UInt32*>(&value));
ColumnWithTypeAndName test_date(column->get_ptr(), std::make_shared<DataTypeDateV2>(),
"test_date");
@ -380,7 +380,7 @@ TEST_F(PartitionTransformersTest, test_timestamp_day_transform) {
auto column = ColumnDateTimeV2::create();
auto& datetime_v2_data = column->get_data();
DateV2Value<DateTimeV2ValueType> value;
value.set_time(2017, 11, 16, 22, 31, 8, 0);
value.unchecked_set_time(2017, 11, 16, 22, 31, 8, 0);
datetime_v2_data.push_back(*reinterpret_cast<vectorized::UInt64*>(&value));
ColumnWithTypeAndName test_timestamp(column->get_ptr(), std::make_shared<DataTypeDateTimeV2>(),
"test_timestamp");
@ -406,7 +406,7 @@ TEST_F(PartitionTransformersTest, test_timestamp_hour_transform) {
auto column = ColumnDateTimeV2::create();
auto& datetime_v2_data = column->get_data();
DateV2Value<DateTimeV2ValueType> value;
value.set_time(2017, 11, 16, 22, 31, 8, 0);
value.unchecked_set_time(2017, 11, 16, 22, 31, 8, 0);
datetime_v2_data.push_back(*reinterpret_cast<vectorized::UInt64*>(&value));
ColumnWithTypeAndName test_timestamp(column->get_ptr(), std::make_shared<DataTypeDateTimeV2>(),
"test_timestamp");

View File

@ -35,3 +35,39 @@
-- !sql12 --
2026-01-01T00:00
-- !x1 --
9999-12-31T23:55
-- !x2 --
0001-01-01T00:00
-- !x3 --
\N
-- !x4 --
1931-01-01T00:00
-- !x6 --
0001-01-01T00:00
-- !x7 --
\N
-- !x8 --
\N
-- !x9 --
\N
-- !x11 --
0001-08-01T00:00
-- !x12 --
0001-08-01T00:00
-- !x13 --
0002-03-01T00:00
-- !x14 --
9999-12-31T23:55

View File

@ -32,5 +32,20 @@ suite("test_date_floor_ceil") {
qt_sql9 """select date_ceil("2023-07-14 10:51:00",interval 5 hour); """
qt_sql10 """select date_ceil("2023-07-14 10:51:00",interval 5 day); """
qt_sql11 """select date_ceil("2023-07-14 10:51:00",interval 5 month); """
qt_sql12 """select date_ceil("2023-07-14 10:51:00",interval 5 year); """
qt_sql12 """select date_ceil("2023-07-14 10:51:00",interval 5 year); """
qt_x1 """ select date_floor('9999-12-31 23:59:59.999999', interval 5 minute); """
qt_x2 """ select date_floor('9999-12-31 23:59:59.999999', interval 33333 year); """
qt_x3 """ select date_floor('9999-12-31 23:59:59.999999', interval -10 year); """
qt_x4 """ select date_floor('1923-12-31 23:59:59.999999', interval -10 year); """
// qt_x5 """ select date_floor('0000-01-01 00:00:00', interval 7 minute); """//wrong
qt_x6 """ select date_floor('0001-01-01 00:00:00', interval 7 minute); """
qt_x7 """ select date_ceil('9999-12-31 23:59:59.999999', interval 5 minute); """
qt_x8 """ select date_ceil('9999-12-31 23:59:59.999999', interval 1 second); """
qt_x9 """ select date_ceil('9999-12-31 23:59:59.999999', interval 100 year); """
// qt_x10 """ select date_ceil('0000-01-01 23:59:59.999999', interval 7 month); """//wrong
qt_x11 """ select date_ceil('0001-01-01 23:59:59.999999', interval 7 month); """
qt_x12 """ select date_ceil('0001-09-01 23:59:59.999999', interval -7 month); """
qt_x13 """ select date_ceil('0002-02-01 23:59:59.999999', interval -7 month); """
qt_x14 """ select date_ceil('9999-12-31 23:54:59.999999', interval 5 minute); """
}