fix comments

This commit is contained in:
kevinyhzou 2024-11-13 11:49:31 +08:00
parent 7634e646e8
commit 4ea106712f
5 changed files with 71 additions and 88 deletions

View File

@ -35,7 +35,6 @@ namespace ErrorCodes
extern const int BAD_ARGUMENTS;
extern const int CANNOT_PARSE_DATETIME;
extern const int ILLEGAL_COLUMN;
extern const int LOGICAL_ERROR;
extern const int NOT_ENOUGH_SPACE;
extern const int NOT_IMPLEMENTED;
extern const int VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE;
@ -193,13 +192,13 @@ namespace
Int32 minute = 0; /// range [0, 59]
Int32 second = 0; /// range [0, 59]
Int32 microsecond = 0; /// range [0, 999999]
UInt32 scale = 0; /// Scale of DateTime64. When parse syntax is `Joda`, it range [0, 6]; When parse syntax is `MySQL`, it should be 6
UInt32 scale = 0; /// scale of the result DateTime64. Always 6 for ParseSytax == MySQL, [0, 6] for ParseSyntax == Joda.
bool is_am = true; /// If is_hour_of_half_day = true and is_am = false (i.e. pm) then add 12 hours to the result DateTime
bool hour_starts_at_1 = false; /// Whether the hour is clockhour
bool is_hour_of_half_day = false; /// Whether the hour is of half day
bool has_time_zone_offset = false; /// If true, time zone offset is explicitly specified.
bool has_time_zone_offset = false; /// If true, timezone offset is explicitly specified.
Int64 time_zone_offset = 0; /// Offset in seconds between current timezone to UTC.
void reset()
@ -630,10 +629,10 @@ namespace
{"time", static_cast<FunctionArgumentDescriptor::TypeValidator>(&isString), nullptr, "String"}};
if constexpr (return_type == ReturnType::DateTime64)
mandatory_args.push_back(
{"scale", static_cast<FunctionArgumentDescriptor::TypeValidator>(&isUInt8), &isColumnConst, "UInt8"});
{"scale", static_cast<FunctionArgumentDescriptor::TypeValidator>(&isUInt8), &isColumnConst, "const UInt8"});
FunctionArgumentDescriptors optional_args{
{"format", static_cast<FunctionArgumentDescriptor::TypeValidator>(&isString), nullptr, "String"},
{"format", static_cast<FunctionArgumentDescriptor::TypeValidator>(&isString), nullptr, "const String"},
{"timezone", static_cast<FunctionArgumentDescriptor::TypeValidator>(&isString), &isColumnConst, "const String"}
};
validateFunctionArguments(*this, arguments, mandatory_args, optional_args);
@ -648,7 +647,10 @@ namespace
if (const auto * col_scale = checkAndGetColumnConst<ColumnUInt8>(arguments[1].column.get()); col_scale != nullptr)
scale = col_scale->getValue<UInt8>();
else
throw Exception(ErrorCodes::LOGICAL_ERROR, "The scale argument is not Const(UInt8) type.");
throw Exception(
ErrorCodes::ILLEGAL_COLUMN,
"Illegal type in 2nd ('scale') argument of function {}. Must be constant UInt8.",
getName());
data_type = std::make_shared<DataTypeDateTime64>(scale, time_zone_name);
}
@ -660,12 +662,11 @@ namespace
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
{
DataTypePtr non_null_result_type;
DataTypePtr result_type_without_nullable;
if constexpr (error_handling == ErrorHandling::Null)
/// Remove Nullable wrapper. It will be added back later.
non_null_result_type = removeNullable(result_type);
result_type_without_nullable = removeNullable(result_type); /// Remove Nullable wrapper. It will be added back later.
else
non_null_result_type = result_type;
result_type_without_nullable = result_type;
if constexpr (return_type == ReturnType::DateTime)
{
@ -675,46 +676,44 @@ namespace
}
else
{
const auto * datatime64_type = checkAndGetDataType<DataTypeDateTime64>(non_null_result_type.get());
MutableColumnPtr col_res = ColumnDateTime64::create(input_rows_count, datatime64_type->getScale());
const auto * result_type_without_nullable_casted = checkAndGetDataType<DataTypeDateTime64>(result_type_without_nullable.get());
MutableColumnPtr col_res = ColumnDateTime64::create(input_rows_count, result_type_without_nullable_casted->getScale());
ColumnDateTime64 * col_datetime64 = assert_cast<ColumnDateTime64 *>(col_res.get());
return executeImpl2<DataTypeDateTime64::FieldType>(arguments, result_type, input_rows_count, col_res, col_datetime64->getData());
}
}
template<typename T>
ColumnPtr executeImpl2(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count,
ColumnPtr executeImpl2(
const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count,
MutableColumnPtr & col_res, PaddedPODArray<T> & res_data) const
{
const auto * col_str = checkAndGetColumn<ColumnString>(arguments[0].column.get());
if (!col_str)
throw Exception(
ErrorCodes::ILLEGAL_COLUMN,
"Illegal column {} of first ('str') argument of function {}. Must be string.",
arguments[0].column->getName(),
"Illegal type in 1st ('time') argument of function {}. Must be String.",
getName());
ColumnUInt8::MutablePtr col_null_map;
if constexpr (error_handling == ErrorHandling::Null)
col_null_map = ColumnUInt8::create(input_rows_count, 0);
Int64 multiplier = 0;
UInt32 scale = 0;
if constexpr (return_type == ReturnType::DateTime64)
{
const DataTypeDateTime64 * datatime64_type = checkAndGetDataType<DataTypeDateTime64>(removeNullable(result_type).get());
scale = datatime64_type->getScale();
const DataTypeDateTime64 * result_type_without_nullable_casted = checkAndGetDataType<DataTypeDateTime64>(removeNullable(result_type).get());
scale = result_type_without_nullable_casted->getScale();
multiplier = DecimalUtils::scaleMultiplier<DateTime64>(scale);
}
const String format = getFormat(arguments, scale);
std::vector<Instruction> instructions = parseFormat(format);
Int64OrError result = 0;
ColumnUInt8::MutablePtr col_null_map;
if constexpr (error_handling == ErrorHandling::Null)
col_null_map = ColumnUInt8::create(input_rows_count, 0);
const String format = getFormat(arguments, scale);
const std::vector<Instruction> instructions = parseFormat(format);
/// Check scale by counting how many 'S' characters exist in the format string when parse syntax is Joda and
/// return type is DateTime64.
if constexpr (return_type == ReturnType::DateTime64 && parse_syntax == ParseSyntax::Joda)
{
/// How many 'S' characters does the format string contain?
UInt32 s_count = 0;
for (const auto & instruction : instructions)
{
@ -730,14 +729,13 @@ namespace
++s_count;
}
}
/// If the number of 'S' characters in format string not euqals the scale, then throw an exception to report error.
/// The number of 'S' characters in the format string must be equal to the scale.
if (s_count != 0 && s_count != scale)
result = tl::unexpected(ErrorCodeAndMessage(ErrorCodes::BAD_ARGUMENTS,
"The number of 'S' characters in the input format string {} does not equal the given scale value {}.",
throw Exception(ErrorCodes::BAD_ARGUMENTS,
"The number of 'S' characters in the input format string {} is different than the scale {}.",
format,
std::to_string(scale)));
std::to_string(scale));
}
const auto & time_zone = getTimeZone(arguments);
/// Make datetime fit in a cache line.
alignas(64) DateTime<error_handling> datetime;
@ -750,59 +748,48 @@ namespace
Pos end = str_ref.data + str_ref.size;
bool error = false;
auto handle_error = [&]([[maybe_unused]] const auto & res) -> void
{
if constexpr (error_handling == ErrorHandling::Zero)
{
res_data[i] = 0;
error = true;
}
else if constexpr (error_handling == ErrorHandling::Null)
{
res_data[i] = 0;
col_null_map->getData()[i] = 1;
error = true;
}
else
{
static_assert(error_handling == ErrorHandling::Exception);
const ErrorCodeAndMessage & err = res.error();
throw Exception(err.error_code, "{}", err.error_message);
}
};
if (!result.has_value())
{
handle_error(result);
continue;
}
if constexpr (return_type == ReturnType::DateTime64)
{
if (auto res = datetime.setScale(static_cast<UInt8>(scale), parse_syntax); !res.has_value())
if (auto result = datetime.setScale(static_cast<UInt8>(scale), parse_syntax); !result.has_value())
{
handle_error(res);
continue;
const ErrorCodeAndMessage & err = result.error();
throw Exception(err.error_code, "Invalid scale value: {}, {}", std::to_string(scale), err.error_message);
}
}
for (const auto & instruction : instructions)
{
if (auto res = instruction.perform(cur, end, datetime) ; res.has_value())
if (auto result = instruction.perform(cur, end, datetime); result.has_value())
{
cur = *res;
cur = *result;
}
else
{
handle_error(res);
break;
if constexpr (error_handling == ErrorHandling::Zero)
{
res_data[i] = 0;
error = true;
}
else if constexpr (error_handling == ErrorHandling::Null)
{
res_data[i] = 0;
col_null_map->getData()[i] = 1;
error = true;
}
else
{
static_assert(error_handling == ErrorHandling::Exception);
const ErrorCodeAndMessage & err = result.error();
throw Exception(err.error_code, "{}", err.error_message);
}
}
}
if (error)
continue;
/// Ensure all input was consumed.
Int64OrError result = 0;
/// Ensure all input was consumed
if (cur < end)
{
result = tl::unexpected(ErrorCodeAndMessage(
@ -1410,7 +1397,7 @@ namespace
if (date.scale != 6)
RETURN_ERROR(
ErrorCodes::CANNOT_PARSE_DATETIME,
"Unable to parse fragment {} from {} because of the datetime scale {} is not 6",
"Unable to parse fragment {} from {} because the datetime scale {} is not 6",
fragment,
std::string_view(cur, end - cur),
std::to_string(date.scale))
@ -1835,6 +1822,7 @@ namespace
static PosOrError jodaTimezoneOffset(size_t repetitions, Pos cur, Pos end, const String & fragment, DateTime<error_handling> & date)
{
RETURN_ERROR_IF_FAILED(checkSpace(cur, end, 5, "jodaTimezoneOffset requires size >= 5", fragment))
Int32 sign;
if (*cur == '-')
sign = -1;
@ -1843,7 +1831,7 @@ namespace
else
RETURN_ERROR(
ErrorCodes::CANNOT_PARSE_DATETIME,
"Unable to parse fragment {} from {} because of unknown sign time zone offset: {}",
"Unable to parse fragment {} from {} because of unknown sign in time zone offset: {}",
fragment,
std::string_view(cur, end - cur),
std::string_view(cur, 1))
@ -1854,7 +1842,7 @@ namespace
if (hour < 0 || hour > 23)
RETURN_ERROR(
ErrorCodes::CANNOT_PARSE_DATETIME,
"Unable to parse fragment {} from {} because of the hour of datetime not in range [0, 23]: {}",
"Unable to parse fragment {} from {} because the hour of datetime not in range [0, 23]: {}",
fragment,
std::string_view(cur, end - cur),
std::string_view(cur, 1))
@ -1863,7 +1851,7 @@ namespace
if (minute < 0 || minute > 59)
RETURN_ERROR(
ErrorCodes::CANNOT_PARSE_DATETIME,
"Unable to parse fragment {} from {} because of the minute of datetime not in range [0, 59]: {}",
"Unable to parse fragment {} from {} because the minute of datetime not in range [0, 59]: {}",
fragment,
std::string_view(cur, end - cur),
std::string_view(cur, 1))
@ -2282,6 +2270,7 @@ namespace
if (arguments.size() <= index_of_format_string_arg)
{
/// No format string given. Use default format string.
String format;
if constexpr (parse_syntax == ParseSyntax::MySQL)
format = "%Y-%m-%d %H:%i:%s";
@ -2302,8 +2291,7 @@ namespace
if (!col_format)
throw Exception(
ErrorCodes::ILLEGAL_COLUMN,
"Illegal column {} of second ('format') argument of function {}. Must be constant string.",
arguments[index_of_format_string_arg].column->getName(),
"Illegal type in 'format' argument of function {}. Must be constant String.",
getName());
return col_format->getValue<String>();
}
@ -2316,13 +2304,12 @@ namespace
else if (return_type == ReturnType::DateTime64 && arguments.size() < 4)
return DateLUT::instance();
size_t timezone_arg_index = arguments.size() - 1;
const auto * col = checkAndGetColumnConst<ColumnString>(arguments[timezone_arg_index].column.get());
size_t index_of_timezone_arg = arguments.size() - 1;
const auto * col = checkAndGetColumnConst<ColumnString>(arguments[index_of_timezone_arg].column.get());
if (!col)
throw Exception(
ErrorCodes::ILLEGAL_COLUMN,
"Illegal column {} of ('timezone') argument of function {}. Must be constant String.",
arguments[timezone_arg_index].column->getName(),
"Illegal type in 'timezone' argument of function {}. Must be constant String.",
getName());
String time_zone = col->getValue<String>();
@ -2411,16 +2398,16 @@ REGISTER_FUNCTION(ParseDateTime)
factory.registerFunction<FunctionParseDateTimeOrZero>();
factory.registerFunction<FunctionParseDateTimeOrNull>();
factory.registerAlias("str_to_date", FunctionParseDateTimeOrNull::name, FunctionFactory::Case::Insensitive);
factory.registerFunction<FunctionParseDateTime64>();
factory.registerFunction<FunctionParseDateTime64OrZero>();
factory.registerFunction<FunctionParseDateTime64OrNull>();
factory.registerFunction<FunctionParseDateTimeInJodaSyntax>();
factory.registerFunction<FunctionParseDateTimeInJodaSyntaxOrZero>();
factory.registerFunction<FunctionParseDateTimeInJodaSyntaxOrNull>();
factory.registerFunction<FunctionParseDateTime64InJodaSyntax>();
factory.registerFunction<FunctionParseDateTime64InJodaSyntaxOrZero>();
factory.registerFunction<FunctionParseDateTime64InJodaSyntaxOrNull>();
factory.registerFunction<FunctionParseDateTime64>();
factory.registerFunction<FunctionParseDateTime64OrZero>();
factory.registerFunction<FunctionParseDateTime64OrNull>();
}

View File

@ -1,10 +1,8 @@
2024-10-09 10:30:10.123456 2024-10-09 10:30:10.123456
2024-10-09 10:30:10.123456
1970-01-01 08:00:00.000
2024-10-09 10:30:10.123456 2024-10-09 10:30:10.123456
2024-10-09 10:30:10.123456
1970-01-01 08:00:00.000000
\N
2024-10-09 10:30:10.123456 2024-10-09 10:30:10.123456
2024-10-09 10:30:10.123456
1970-01-01 08:00:00.000000

View File

@ -8,14 +8,14 @@ select parseDateTime64('2024-10-09 10:30:10.123456', 6, '%Y-%m-%d %H:%i:%s.%f',
select parseDateTime64('2024-10-09 10:30:10.123', 6, '%Y-%m-%d %H:%i:%s.%f'); -- { serverError NOT_ENOUGH_SPACE }
select parseDateTime64OrZero('2024-10-09 10:30:10.123456'); -- {serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH}
select parseDateTime64OrZero('2024-10-09 10:30:10', 3);
select parseDateTime64OrZero('2024-10-09 10:30:10', 3); -- { serverError CANNOT_PARSE_DATETIME }
select parseDateTime64OrZero('2024-10-09 10:30:10', -3); -- {serverError ILLEGAL_TYPE_OF_ARGUMENT}
select parseDateTime64OrZero('2024-10-09 10:30:10.123456', 6), parseDateTime64OrZero('2024-10-09 10:30:10.123456', 6, '%Y-%m-%d %H:%i:%s.%f');
select parseDateTime64OrZero('2024-10-09 10:30:10.123456', 6, '%Y-%m-%d %H:%i:%s.%f', 'Etc/GMT-7');
select parseDateTime64OrZero('2024-10-09 10:30:10.123456', 6, '%Y-%m-%d %H:%i:%s.%fffff');
select parseDateTime64OrNull('2024-10-09 10:30:10.123456'); -- {serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH}
select parseDateTime64OrNull('2024-10-09 10:30:10', 3);
select parseDateTime64OrNull('2024-10-09 10:30:10', 3); -- { serverError CANNOT_PARSE_DATETIME }
select parseDateTime64OrNull('2024-10-09 10:30:10', -3); -- {serverError ILLEGAL_TYPE_OF_ARGUMENT}
select parseDateTime64OrNull('2024-10-09 10:30:10.123456', 6), parseDateTime64OrZero('2024-10-09 10:30:10.123456', 6,'%Y-%m-%d %H:%i:%s.%f');
select parseDateTime64OrNull('2024-10-09 10:30:10.123456', 6, '%Y-%m-%d %H:%i:%s.%f', 'Etc/GMT-7');;

View File

@ -6,7 +6,6 @@
1970-01-01 08:00:00.000
2024-10-09 10:30:10.123 2024-10-09 10:30:10.000123
2024-10-09 10:30:10.123 2024-10-09 10:30:10.000123
1970-01-01 08:00:00.000
2024-10-10 02:42:10.123456
1970-01-01 08:00:00.000000
2024-10-09 23:30:10.123456
@ -15,7 +14,6 @@
\N
2024-10-09 10:30:10.123 2024-10-09 10:30:10.000123
2024-10-09 10:30:10.123 2024-10-09 10:30:10.000123
\N
2024-10-10 02:42:10.123456
\N
2024-10-09 23:30:10.123456

View File

@ -19,7 +19,7 @@ select parseDateTime64InJodaSyntaxOrZero('2024-10-09 10:30:10', -3); -- {serverE
select parseDateTime64InJodaSyntax('2024-10-09 10:30:10.123', 'yyyy-MM-dd HH:mm:ss.SSS'); -- {serverError ILLEGAL_TYPE_OF_ARGUMENT}
select parseDateTime64InJodaSyntaxOrZero('2024-10-09 10:30:10.123', 3), parseDateTime64InJodaSyntaxOrZero('2024-10-09 10:30:10.123', 6);
select parseDateTime64InJodaSyntaxOrZero('2024-10-09 10:30:10.123', 3, 'yyyy-MM-dd HH:mm:ss.SSS'), parseDateTime64InJodaSyntaxOrZero('2024-10-09 10:30:10.123', 6, 'yyyy-MM-dd HH:mm:ss.SSSSSS');
select parseDateTime64InJodaSyntaxOrZero('2024-10-09 10:30:10.123', 3, 'yyyy-MM-dd HH:mm:ss.SSSS');
select parseDateTime64InJodaSyntaxOrZero('2024-10-09 10:30:10.123', 3, 'yyyy-MM-dd HH:mm:ss.SSSS'); -- { serverError BAD_ARGUMENTS }
select parseDateTime64InJodaSyntaxOrZero('2024-10-09 10:30:10.123456-0812', 6, 'yyyy-MM-dd HH:mm:ss.SSSSSSZ');
select parseDateTime64InJodaSyntaxOrZero('2024-10-09 10:30:10.123456-08123', 6, 'yyyy-MM-dd HH:mm:ss.SSSSSSZZZ');
select parseDateTime64InJodaSyntaxOrZero('2024-10-09 10:30:10.123456EST', 6, 'yyyy-MM-dd HH:mm:ss.SSSSSSz');
@ -33,7 +33,7 @@ select parseDateTime64InJodaSyntaxOrNull('2024-10-09 10:30:10', -3); -- {serverE
select parseDateTime64InJodaSyntax('2024-10-09 10:30:10.123', 'yyyy-MM-dd HH:mm:ss.SSS'); -- {serverError ILLEGAL_TYPE_OF_ARGUMENT}
select parseDateTime64InJodaSyntaxOrNull('2024-10-09 10:30:10.123', 3), parseDateTime64InJodaSyntaxOrNull('2024-10-09 10:30:10.123', 6);
select parseDateTime64InJodaSyntaxOrNull('2024-10-09 10:30:10.123', 3, 'yyyy-MM-dd HH:mm:ss.SSS'), parseDateTime64InJodaSyntaxOrNull('2024-10-09 10:30:10.123', 6, 'yyyy-MM-dd HH:mm:ss.SSSSSS');
select parseDateTime64InJodaSyntaxOrNull('2024-10-09 10:30:10.123', 3, 'yyyy-MM-dd HH:mm:ss.SSSS');
select parseDateTime64InJodaSyntaxOrNull('2024-10-09 10:30:10.123', 3, 'yyyy-MM-dd HH:mm:ss.SSSS'); -- { serverError BAD_ARGUMENTS }
select parseDateTime64InJodaSyntaxOrNull('2024-10-09 10:30:10.123456-0812', 6, 'yyyy-MM-dd HH:mm:ss.SSSSSSZ');
select parseDateTime64InJodaSyntaxOrNull('2024-10-09 10:30:10.123456-08123', 6, 'yyyy-MM-dd HH:mm:ss.SSSSSSZZZ');
select parseDateTime64InJodaSyntaxOrNull('2024-10-09 10:30:10.123456EST', 6, 'yyyy-MM-dd HH:mm:ss.SSSSSSz');