fix, add test

This commit is contained in:
Alexander Tokmakov 2020-12-24 03:13:53 +03:00
parent 317df5f5d2
commit c49a6302fa
3 changed files with 65 additions and 10 deletions

View File

@ -977,8 +977,6 @@ struct ConvertThroughParsing
};
template <typename ToDataType, typename Name>
struct ConvertImpl<std::enable_if_t<!std::is_same_v<ToDataType, DataTypeString>, DataTypeString>, ToDataType, Name, ConvertDefaultBehaviorTag>
: ConvertThroughParsing<DataTypeString, ToDataType, Name, ConvertFromStringExceptionMode::Throw, ConvertFromStringParsingMode::Normal> {};
@ -1044,6 +1042,9 @@ template <>
struct ConvertImpl<DataTypeString, DataTypeUInt32, NameToUnixTimestamp, ConvertDefaultBehaviorTag>
: ConvertImpl<DataTypeString, DataTypeDateTime, NameToUnixTimestamp, ConvertDefaultBehaviorTag> {};
template <>
struct ConvertImpl<DataTypeString, DataTypeUInt32, NameToUnixTimestamp, ConvertReturnNullOnErrorTag>
: ConvertImpl<DataTypeString, DataTypeDateTime, NameToUnixTimestamp, ConvertReturnNullOnErrorTag> {};
/** If types are identical, just take reference to column.
*/
@ -1187,6 +1188,7 @@ public:
auto getter = [&] (const auto & args) { return getReturnTypeImplRemovedNullable(args); };
auto res = FunctionOverloadResolverAdaptor::getReturnTypeDefaultImplementationForNulls(arguments, getter);
to_nullable = res->isNullable();
checked_return_type = true;
return res;
}
@ -1268,17 +1270,16 @@ public:
}
}
bool useDefaultImplementationForNulls() const override { return to_nullable; } // FIXME
/// Function actually uses default implementation for nulls,
/// but we need to know if return type is Nullable or not,
/// so we use checked_return_type only to intercept the first call to getReturnTypeImpl(...).
bool useDefaultImplementationForNulls() const override { return checked_return_type; }
bool useDefaultImplementationForConstants() const override { return true; }
ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {1}; }
bool canBeExecutedOnDefaultArguments() const override { return false; }
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
{
return executeImplRemovedNullable(arguments, result_type, input_rows_count);
}
ColumnPtr executeImplRemovedNullable(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const
{
try
{
@ -1323,6 +1324,7 @@ public:
}
private:
mutable bool checked_return_type = false;
mutable bool to_nullable = false;
ColumnPtr executeInternal(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const
@ -1359,12 +1361,12 @@ private:
const ColumnWithTypeAndName & scale_column = arguments[1];
UInt32 scale = extractToDecimalScale(scale_column);
result_column = ConvertImpl<LeftDataType, RightDataType, Name>::execute(arguments, result_type, input_rows_count, scale);
result_column = ConvertImpl<LeftDataType, RightDataType, Name, SpecialTag>::execute(arguments, result_type, input_rows_count, scale);
}
else if constexpr (IsDataTypeDateOrDateTime<RightDataType> && std::is_same_v<LeftDataType, DataTypeDateTime64>)
{
const auto * dt64 = assert_cast<const DataTypeDateTime64 *>(arguments[0].type.get());
result_column = ConvertImpl<LeftDataType, RightDataType, Name>::execute(arguments, result_type, input_rows_count, dt64->getScale());
result_column = ConvertImpl<LeftDataType, RightDataType, Name, SpecialTag>::execute(arguments, result_type, input_rows_count, dt64->getScale());
}
else if constexpr (IsDataTypeDecimalOrNumber<LeftDataType> && IsDataTypeDecimalOrNumber<RightDataType>)
{
@ -1414,6 +1416,8 @@ private:
}
else
{
/// We should use ConvertFromStringExceptionMode::Null mode when converting from String (or FixedString)
/// to Nullable type, to avoid 'value is too short' error on attempt to parse empty string from NULL values.
if (to_nullable && WhichDataType(from_type).isStringOrFixedString())
done = callOnIndexAndDataType<ToDataType>(from_type->getTypeId(), call, ConvertReturnNullOnErrorTag{});
else

View File

@ -0,0 +1,38 @@
42
\N
0
\N
\N
42
\N
0
\N
256
2020-12-24
\N
1970-01-01
\N
1970-01-01
2020-12-24 01:02:03
\N
1970-01-01 03:00:00
\N
2020-12-24 01:02:03.00
\N
1970-01-01 03:00:00.00
1970-01-01 03:00:00.00
946721532
\N
\N
42.00
\N
\N
42.00000000
\N
3.14159000
42
\N
test
42\0\0\0\0\0\0
\N
test\0\0\0\0

View File

@ -0,0 +1,13 @@
select toUInt8(x) from values('x Nullable(String)', '42', NULL, '0', '', '256');
select toInt64(x) from values('x Nullable(String)', '42', NULL, '0', '', '256');
select toDate(x) from values('x Nullable(String)', '2020-12-24', NULL, '0000-00-00', '', '9999-01-01');
select toDateTime(x) from values('x Nullable(String)', '2020-12-24 01:02:03', NULL, '0000-00-00 00:00:00', '');
select toDateTime64(x, 2) from values('x Nullable(String)', '2020-12-24 01:02:03', NULL, '0000-00-00 00:00:00', '');
select toUnixTimestamp(x) from values ('x Nullable(String)', '2000-01-01 13:12:12', NULL, '');
select toDecimal32(x, 2) from values ('x Nullable(String)', '42', NULL, '3.14159');
select toDecimal64(x, 8) from values ('x Nullable(String)', '42', NULL, '3.14159');
select toString(x) from values ('x Nullable(String)', '42', NULL, 'test');
select toFixedString(x, 8) from values ('x Nullable(String)', '42', NULL, 'test');