Fix Date text parsing in optimistic path

1
This commit is contained in:
avogar 2023-11-14 18:54:55 +00:00
parent 99a69d98de
commit 38f200d969
3 changed files with 50 additions and 2 deletions

View File

@ -664,11 +664,20 @@ ReturnType readDateTextFallback(LocalDate & date, ReadBuffer & buf);
template <typename ReturnType = void>
inline ReturnType readDateTextImpl(LocalDate & date, ReadBuffer & buf)
{
static constexpr bool throw_exception = std::is_same_v<ReturnType, void>;
/// Optimistic path, when whole value is in buffer.
if (!buf.eof() && buf.position() + 10 <= buf.buffer().end())
{
char * pos = buf.position();
auto error = [&]
{
if constexpr (throw_exception)
throw Exception(ErrorCodes::CANNOT_PARSE_DATE, "Cannot parse date here: {}", String(buf.position(), 10));
return ReturnType(false);
};
/// YYYY-MM-DD
/// YYYY-MM-D
/// YYYY-M-DD
@ -677,6 +686,9 @@ inline ReturnType readDateTextImpl(LocalDate & date, ReadBuffer & buf)
/// The delimiters can be arbitrary characters, like YYYY/MM!DD, but obviously not digits.
if (!isNumericASCII(pos[0]) || !isNumericASCII(pos[1]) || !isNumericASCII(pos[2]) || !isNumericASCII(pos[3]))
return error();
UInt16 year = (pos[0] - '0') * 1000 + (pos[1] - '0') * 100 + (pos[2] - '0') * 10 + (pos[3] - '0');
UInt8 month;
UInt8 day;
@ -685,12 +697,18 @@ inline ReturnType readDateTextImpl(LocalDate & date, ReadBuffer & buf)
if (isNumericASCII(pos[-1]))
{
/// YYYYMMDD
if (!isNumericASCII(pos[0]) || !isNumericASCII(pos[1]) || !isNumericASCII(pos[2]))
return error();
month = (pos[-1] - '0') * 10 + (pos[0] - '0');
day = (pos[1] - '0') * 10 + (pos[2] - '0');
pos += 3;
}
else
{
if (!isNumericASCII(pos[0]))
return error();
month = pos[0] - '0';
if (isNumericASCII(pos[1]))
{
@ -700,8 +718,8 @@ inline ReturnType readDateTextImpl(LocalDate & date, ReadBuffer & buf)
else
pos += 2;
if (isNumericASCII(pos[-1]))
return ReturnType(false);
if (isNumericASCII(pos[-1]) || !isNumericASCII(pos[0]))
return error();
day = pos[0] - '0';
if (isNumericASCII(pos[1]))

View File

@ -0,0 +1,5 @@
2020-01-02 SomeString
2020-01-02 SomeString
2020-01-02 SomeString
2020-01-02 SomeString
2020-01-02 SomeString

View File

@ -0,0 +1,25 @@
select * from format(CSV, 'd Date, s String', 'abcdefgh,SomeString'); -- {serverError CANNOT_PARSE_DATE}
select * from format(CSV, 'd Date, s String', '2bcdefgh,SomeString'); -- {serverError CANNOT_PARSE_DATE}
select * from format(CSV, 'd Date, s String', '20cdefgh,SomeString'); -- {serverError CANNOT_PARSE_DATE}
select * from format(CSV, 'd Date, s String', '202defgh,SomeString'); -- {serverError CANNOT_PARSE_DATE}
select * from format(CSV, 'd Date, s String', '2020efgh,SomeString'); -- {serverError CANNOT_PARSE_DATE}
select * from format(CSV, 'd Date, s String', '20200fgh,SomeString'); -- {serverError CANNOT_PARSE_DATE}
select * from format(CSV, 'd Date, s String', '202001gh,SomeString'); -- {serverError CANNOT_PARSE_DATE}
select * from format(CSV, 'd Date, s String', '2020010h,SomeString'); -- {serverError CANNOT_PARSE_DATE}
select * from format(CSV, 'd Date, s String', '20200102,SomeString');
select * from format(CSV, 'd Date, s String', 'abcd-ef-gh,SomeString'); -- {serverError CANNOT_PARSE_DATE}
select * from format(CSV, 'd Date, s String', '2bcd-ef-gh,SomeString'); -- {serverError CANNOT_PARSE_DATE}
select * from format(CSV, 'd Date, s String', '20cd-ef-gh,SomeString'); -- {serverError CANNOT_PARSE_DATE}
select * from format(CSV, 'd Date, s String', '202d-ef-gh,SomeString'); -- {serverError CANNOT_PARSE_DATE}
select * from format(CSV, 'd Date, s String', '2020-ef-gh,SomeString'); -- {serverError CANNOT_PARSE_DATE}
select * from format(CSV, 'd Date, s String', '2020-f-gh,SomeString'); -- {serverError CANNOT_PARSE_DATE}
select * from format(CSV, 'd Date, s String', '2020-f-g,SomeString'); -- {serverError CANNOT_PARSE_DATE}
select * from format(CSV, 'd Date, s String', '2020-0f-gh,SomeString'); -- {serverError CANNOT_PARSE_DATE}
select * from format(CSV, 'd Date, s String', '2020-01-gh,SomeString'); -- {serverError CANNOT_PARSE_DATE}
select * from format(CSV, 'd Date, s String', '2020-01-h,SomeString'); -- {serverError CANNOT_PARSE_DATE}
select * from format(CSV, 'd Date, s String', '2020-1-gh,SomeString'); -- {serverError CANNOT_PARSE_DATE}
select * from format(CSV, 'd Date, s String', '2020-1-h,SomeString'); -- {serverError CANNOT_PARSE_DATE}
select * from format(CSV, 'd Date, s String', '2020-01-02,SomeString');
select * from format(CSV, 'd Date, s String', '2020-01-2,SomeString');
select * from format(CSV, 'd Date, s String', '2020-1-2,SomeString');
select * from format(CSV, 'd Date, s String', '2020-1-02,SomeString');