Merge pull request #68382 from Avogar/better-datetime-inference

Improve schema inference of date times
This commit is contained in:
Kruglov Pavel 2024-08-15 19:33:37 +00:00 committed by GitHub
commit c4d9944a90
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 968 additions and 157 deletions

View File

@ -359,13 +359,14 @@ DESC format(JSONEachRow, '{"int" : 42, "float" : 42.42, "string" : "Hello, World
Dates, DateTimes:
```sql
DESC format(JSONEachRow, '{"date" : "2022-01-01", "datetime" : "2022-01-01 00:00:00"}')
DESC format(JSONEachRow, '{"date" : "2022-01-01", "datetime" : "2022-01-01 00:00:00", "datetime64" : "2022-01-01 00:00:00.000"}')
```
```response
┌─name─────┬─type────────────────────┬─default_type─┬─default_expression─┬─comment─┬─codec_expression─┬─ttl_expression─┐
│ date │ Nullable(Date) │ │ │ │ │ │
│ datetime │ Nullable(DateTime64(9)) │ │ │ │ │ │
└──────────┴─────────────────────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘
┌─name───────┬─type────────────────────┬─default_type─┬─default_expression─┬─comment─┬─codec_expression─┬─ttl_expression─┐
│ date │ Nullable(Date) │ │ │ │ │ │
│ datetime │ Nullable(DateTime) │ │ │ │ │ │
│ datetime64 │ Nullable(DateTime64(9)) │ │ │ │ │ │
└────────────┴─────────────────────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘
```
Arrays:
@ -759,12 +760,13 @@ DESC format(CSV, 'Hello world!,World hello!')
Dates, DateTimes:
```sql
DESC format(CSV, '"2020-01-01","2020-01-01 00:00:00"')
DESC format(CSV, '"2020-01-01","2020-01-01 00:00:00","2022-01-01 00:00:00.000"')
```
```response
┌─name─┬─type────────────────────┬─default_type─┬─default_expression─┬─comment─┬─codec_expression─┬─ttl_expression─┐
│ c1 │ Nullable(Date) │ │ │ │ │ │
│ c2 │ Nullable(DateTime64(9)) │ │ │ │ │ │
│ c2 │ Nullable(DateTime) │ │ │ │ │ │
│ c3 │ Nullable(DateTime64(9)) │ │ │ │ │ │
└──────┴─────────────────────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘
```
@ -956,12 +958,13 @@ DESC format(TSKV, 'int=42 float=42.42 bool=true string=Hello,World!\n')
Dates, DateTimes:
```sql
DESC format(TSV, '2020-01-01 2020-01-01 00:00:00')
DESC format(TSV, '2020-01-01 2020-01-01 00:00:00 2022-01-01 00:00:00.000')
```
```response
┌─name─┬─type────────────────────┬─default_type─┬─default_expression─┬─comment─┬─codec_expression─┬─ttl_expression─┐
│ c1 │ Nullable(Date) │ │ │ │ │ │
│ c2 │ Nullable(DateTime64(9)) │ │ │ │ │ │
│ c2 │ Nullable(DateTime) │ │ │ │ │ │
│ c3 │ Nullable(DateTime64(9)) │ │ │ │ │ │
└──────┴─────────────────────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘
```
@ -1126,12 +1129,13 @@ DESC format(Values, $$(42, 42.42, true, 'Hello,World!')$$)
Dates, DateTimes:
```sql
DESC format(Values, $$('2020-01-01', '2020-01-01 00:00:00')$$)
```
DESC format(Values, $$('2020-01-01', '2020-01-01 00:00:00', '2022-01-01 00:00:00.000')$$)
```
```response
┌─name─┬─type────────────────────┬─default_type─┬─default_expression─┬─comment─┬─codec_expression─┬─ttl_expression─┐
│ c1 │ Nullable(Date) │ │ │ │ │ │
│ c2 │ Nullable(DateTime64(9)) │ │ │ │ │ │
│ c2 │ Nullable(DateTime) │ │ │ │ │ │
│ c3 │ Nullable(DateTime64(9)) │ │ │ │ │ │
└──────┴─────────────────────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘
```
@ -1504,8 +1508,8 @@ DESC format(JSONEachRow, $$
#### input_format_try_infer_datetimes
If enabled, ClickHouse will try to infer type `DateTime64` from string fields in schema inference for text formats.
If all fields from a column in sample data were successfully parsed as datetimes, the result type will be `DateTime64(9)`,
If enabled, ClickHouse will try to infer type `DateTime` or `DateTime64` from string fields in schema inference for text formats.
If all fields from a column in sample data were successfully parsed as datetimes, the result type will be `DateTime` or `DateTime64(9)` (if any datetime had fractional part),
if at least one field was not parsed as datetime, the result type will be `String`.
Enabled by default.
@ -1513,39 +1517,66 @@ Enabled by default.
**Examples**
```sql
SET input_format_try_infer_datetimes = 0
SET input_format_try_infer_datetimes = 0;
DESC format(JSONEachRow, $$
{"datetime" : "2021-01-01 00:00:00.000"}
{"datetime" : "2022-01-01 00:00:00.000"}
{"datetime" : "2021-01-01 00:00:00", "datetime64" : "2021-01-01 00:00:00.000"}
{"datetime" : "2022-01-01 00:00:00", "datetime64" : "2022-01-01 00:00:00.000"}
$$)
```
```response
┌─name─────┬─type─────────────┬─default_type─┬─default_expression─┬─comment─┬─codec_expression─┬─ttl_expression─┐
│ datetime │ Nullable(String) │ │ │ │ │ │
└──────────┴──────────────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘
┌─name───────┬─type─────────────┬─default_type─┬─default_expression─┬─comment─┬─codec_expression─┬─ttl_expression─┐
│ datetime │ Nullable(String) │ │ │ │ │ │
│ datetime64 │ Nullable(String) │ │ │ │ │ │
└────────────┴──────────────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘
```
```sql
SET input_format_try_infer_datetimes = 1
SET input_format_try_infer_datetimes = 1;
DESC format(JSONEachRow, $$
{"datetime" : "2021-01-01 00:00:00.000"}
{"datetime" : "2022-01-01 00:00:00.000"}
{"datetime" : "2021-01-01 00:00:00", "datetime64" : "2021-01-01 00:00:00.000"}
{"datetime" : "2022-01-01 00:00:00", "datetime64" : "2022-01-01 00:00:00.000"}
$$)
```
```response
┌─name─────┬─type────────────────────┬─default_type─┬─default_expression─┬─comment─┬─codec_expression─┬─ttl_expression─┐
│ datetime │ Nullable(DateTime64(9)) │ │ │ │ │ │
└──────────┴─────────────────────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘
┌─name───────┬─type────────────────────┬─default_type─┬─default_expression─┬─comment─┬─codec_expression─┬─ttl_expression─┐
│ datetime │ Nullable(DateTime) │ │ │ │ │ │
│ datetime64 │ Nullable(DateTime64(9)) │ │ │ │ │ │
└────────────┴─────────────────────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘
```
```sql
DESC format(JSONEachRow, $$
{"datetime" : "2021-01-01 00:00:00.000"}
{"datetime" : "unknown"}
{"datetime" : "2021-01-01 00:00:00", "datetime64" : "2021-01-01 00:00:00.000"}
{"datetime" : "unknown", "datetime64" : "unknown"}
$$)
```
```response
┌─name─────┬─type─────────────┬─default_type─┬─default_expression─┬─comment─┬─codec_expression─┬─ttl_expression─┐
│ datetime │ Nullable(String) │ │ │ │ │ │
└──────────┴──────────────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘
┌─name───────┬─type─────────────┬─default_type─┬─default_expression─┬─comment─┬─codec_expression─┬─ttl_expression─┐
│ datetime │ Nullable(String) │ │ │ │ │ │
│ datetime64 │ Nullable(String) │ │ │ │ │ │
└────────────┴──────────────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘
```
#### input_format_try_infer_datetimes_only_datetime64
If enabled, ClickHouse will always infer `DateTime64(9)` when `input_format_try_infer_datetimes` is enabled even if datetime values don't contain fractional part.
Disabled by default.
**Examples**
```sql
SET input_format_try_infer_datetimes = 1;
SET input_format_try_infer_datetimes_only_datetime64 = 1;
DESC format(JSONEachRow, $$
{"datetime" : "2021-01-01 00:00:00", "datetime64" : "2021-01-01 00:00:00.000"}
{"datetime" : "2022-01-01 00:00:00", "datetime64" : "2022-01-01 00:00:00.000"}
$$)
```
```text
┌─name───────┬─type────────────────────┬─default_type─┬─default_expression─┬─comment─┬─codec_expression─┬─ttl_expression─┐
│ datetime │ Nullable(DateTime64(9)) │ │ │ │ │ │
│ datetime64 │ Nullable(DateTime64(9)) │ │ │ │ │ │
└────────────┴─────────────────────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘
```
Note: Parsing datetimes during schema inference respect setting [date_time_input_format](/docs/en/operations/settings/settings-formats.md#date_time_input_format)

View File

@ -1137,6 +1137,7 @@ class IColumn;
M(Bool, input_format_try_infer_integers, true, "Try to infer integers instead of floats while schema inference in text formats", 0) \
M(Bool, input_format_try_infer_dates, true, "Try to infer dates from string fields while schema inference in text formats", 0) \
M(Bool, input_format_try_infer_datetimes, true, "Try to infer datetimes from string fields while schema inference in text formats", 0) \
M(Bool, input_format_try_infer_datetimes_only_datetime64, false, "When input_format_try_infer_datetimes is enabled, infer only DateTime64 but not DateTime types", 0) \
M(Bool, input_format_try_infer_exponent_floats, false, "Try to infer floats in exponential notation while schema inference in text formats (except JSON, where exponent numbers are always inferred)", 0) \
M(Bool, output_format_markdown_escape_special_characters, false, "Escape special characters in Markdown", 0) \
M(Bool, input_format_protobuf_flatten_google_wrappers, false, "Enable Google wrappers for regular non-nested columns, e.g. google.protobuf.StringValue 'str' for String column 'str'. For Nullable columns empty wrappers are recognized as defaults, and missing as nulls", 0) \

View File

@ -90,6 +90,7 @@ static std::initializer_list<std::pair<ClickHouseVersion, SettingsChangesHistory
{"optimize_functions_to_subcolumns", false, true, "Enabled settings by default"},
{"join_output_by_rowlist_perkey_rows_threshold", 0, 5, "The lower limit of per-key average rows in the right table to determine whether to output by row list in hash join."},
{"allow_experimental_vector_similarity_index", false, false, "Added new setting to allow experimental vector similarity indexes"},
{"input_format_try_infer_datetimes_only_datetime64", true, false, "Allow to infer DateTime instead of DateTime64 in data formats"}
}
},
{"24.7",

View File

@ -419,10 +419,11 @@ String getAdditionalFormatInfoByEscapingRule(const FormatSettings & settings, Fo
String result = getAdditionalFormatInfoForAllRowBasedFormats(settings);
/// First, settings that are common for all text formats:
result += fmt::format(
", try_infer_integers={}, try_infer_dates={}, try_infer_datetimes={}",
", try_infer_integers={}, try_infer_dates={}, try_infer_datetimes={}, try_infer_datetimes_only_datetime64={}",
settings.try_infer_integers,
settings.try_infer_dates,
settings.try_infer_datetimes);
settings.try_infer_datetimes,
settings.try_infer_datetimes_only_datetime64);
/// Second, format-specific settings:
switch (escaping_rule)

View File

@ -266,6 +266,7 @@ FormatSettings getFormatSettings(const ContextPtr & context, const Settings & se
format_settings.try_infer_integers = settings.input_format_try_infer_integers;
format_settings.try_infer_dates = settings.input_format_try_infer_dates;
format_settings.try_infer_datetimes = settings.input_format_try_infer_datetimes;
format_settings.try_infer_datetimes_only_datetime64 = settings.input_format_try_infer_datetimes_only_datetime64;
format_settings.try_infer_exponent_floats = settings.input_format_try_infer_exponent_floats;
format_settings.markdown.escape_special_characters = settings.output_format_markdown_escape_special_characters;
format_settings.bson.output_string_as_string = settings.output_format_bson_string_as_string;

View File

@ -46,6 +46,7 @@ struct FormatSettings
bool try_infer_integers = true;
bool try_infer_dates = true;
bool try_infer_datetimes = true;
bool try_infer_datetimes_only_datetime64 = false;
bool try_infer_exponent_floats = false;
enum class DateTimeInputFormat : uint8_t

View File

@ -306,37 +306,45 @@ namespace
type_indexes.erase(TypeIndex::UInt64);
}
/// If we have only Date and DateTime types, convert Date to DateTime,
/// otherwise, convert all Date and DateTime to String.
/// If we have only date/datetimes types (Date/DateTime/DateTime64), convert all of them to the common type,
/// otherwise, convert all Date, DateTime and DateTime64 to String.
void transformDatesAndDateTimes(DataTypes & data_types, TypeIndexesSet & type_indexes)
{
bool have_dates = type_indexes.contains(TypeIndex::Date);
bool have_datetimes = type_indexes.contains(TypeIndex::DateTime64);
bool all_dates_or_datetimes = (type_indexes.size() == (static_cast<size_t>(have_dates) + static_cast<size_t>(have_datetimes)));
bool have_datetimes = type_indexes.contains(TypeIndex::DateTime);
bool have_datetimes64 = type_indexes.contains(TypeIndex::DateTime64);
bool all_dates_or_datetimes = (type_indexes.size() == (static_cast<size_t>(have_dates) + static_cast<size_t>(have_datetimes) + static_cast<size_t>(have_datetimes64)));
if (!all_dates_or_datetimes && (have_dates || have_datetimes))
if (!all_dates_or_datetimes && (have_dates || have_datetimes || have_datetimes64))
{
for (auto & type : data_types)
{
if (isDate(type) || isDateTime64(type))
if (isDate(type) || isDateTime(type) || isDateTime64(type))
type = std::make_shared<DataTypeString>();
}
type_indexes.erase(TypeIndex::Date);
type_indexes.erase(TypeIndex::DateTime);
type_indexes.erase(TypeIndex::DateTime64);
type_indexes.insert(TypeIndex::String);
return;
}
if (have_dates && have_datetimes)
for (auto & type : data_types)
{
for (auto & type : data_types)
if (isDate(type) && (have_datetimes || have_datetimes64))
{
if (isDate(type))
if (have_datetimes64)
type = std::make_shared<DataTypeDateTime64>(9);
else
type = std::make_shared<DataTypeDateTime>();
type_indexes.erase(TypeIndex::Date);
}
else if (isDateTime(type) && have_datetimes64)
{
type = std::make_shared<DataTypeDateTime64>(9);
type_indexes.erase(TypeIndex::DateTime);
}
type_indexes.erase(TypeIndex::Date);
}
}
@ -697,55 +705,87 @@ namespace
bool tryInferDate(std::string_view field)
{
if (field.empty())
/// Minimum length of Date text representation is 8 (YYYY-M-D) and maximum is 10 (YYYY-MM-DD)
if (field.size() < 8 || field.size() > 10)
return false;
ReadBufferFromString buf(field);
Float64 tmp_float;
/// Check if it's just a number, and if so, don't try to infer Date from it,
/// because we can interpret this number as a Date (for example 20000101 will be 2000-01-01)
/// and it will lead to inferring Date instead of simple Int64/UInt64 in some cases.
if (tryReadFloatText(tmp_float, buf) && buf.eof())
return false;
buf.seek(0, SEEK_SET); /// Return position to the beginning
DayNum tmp;
return tryReadDateText(tmp, buf) && buf.eof();
}
bool tryInferDateTime(std::string_view field, const FormatSettings & settings)
{
if (field.empty())
if (std::all_of(field.begin(), field.end(), isNumericASCII))
return false;
ReadBufferFromString buf(field);
Float64 tmp_float;
DayNum tmp;
return tryReadDateText(tmp, buf, DateLUT::instance(), /*allowed_delimiters=*/"-/:") && buf.eof();
}
DataTypePtr tryInferDateTimeOrDateTime64(std::string_view field, const FormatSettings & settings)
{
/// Don't try to infer DateTime if string is too long.
/// It's difficult to say what is the real maximum length of
/// DateTime we can parse using BestEffort approach.
/// 50 symbols is more or less valid limit for date times that makes sense.
if (field.empty() || field.size() > 50)
return nullptr;
/// Check that we have at least one digit, don't infer datetime form strings like "Apr"/"May"/etc.
if (!std::any_of(field.begin(), field.end(), isNumericASCII))
return nullptr;
/// Check if it's just a number, and if so, don't try to infer DateTime from it,
/// because we can interpret this number as a timestamp and it will lead to
/// inferring DateTime instead of simple Int64/Float64 in some cases.
/// inferring DateTime instead of simple Int64 in some cases.
if (std::all_of(field.begin(), field.end(), isNumericASCII))
return nullptr;
ReadBufferFromString buf(field);
Float64 tmp_float;
/// Check if it's a float value, and if so, don't try to infer DateTime from it,
/// because it will lead to inferring DateTime instead of simple Float64 in some cases.
if (tryReadFloatText(tmp_float, buf) && buf.eof())
return false;
return nullptr;
buf.seek(0, SEEK_SET); /// Return position to the beginning
if (!settings.try_infer_datetimes_only_datetime64)
{
time_t tmp;
switch (settings.date_time_input_format)
{
case FormatSettings::DateTimeInputFormat::Basic:
if (tryReadDateTimeText(tmp, buf, DateLUT::instance(), /*allowed_date_delimiters=*/"-/:", /*allowed_time_delimiters=*/":") && buf.eof())
return std::make_shared<DataTypeDateTime>();
break;
case FormatSettings::DateTimeInputFormat::BestEffort:
if (tryParseDateTimeBestEffortStrict(tmp, buf, DateLUT::instance(), DateLUT::instance("UTC"), /*allowed_date_delimiters=*/"-/:") && buf.eof())
return std::make_shared<DataTypeDateTime>();
break;
case FormatSettings::DateTimeInputFormat::BestEffortUS:
if (tryParseDateTimeBestEffortUSStrict(tmp, buf, DateLUT::instance(), DateLUT::instance("UTC"), /*allowed_date_delimiters=*/"-/:") && buf.eof())
return std::make_shared<DataTypeDateTime>();
break;
}
}
buf.seek(0, SEEK_SET); /// Return position to the beginning
DateTime64 tmp;
switch (settings.date_time_input_format)
{
case FormatSettings::DateTimeInputFormat::Basic:
if (tryReadDateTime64Text(tmp, 9, buf) && buf.eof())
return true;
if (tryReadDateTime64Text(tmp, 9, buf, DateLUT::instance(), /*allowed_date_delimiters=*/"-/:", /*allowed_time_delimiters=*/":") && buf.eof())
return std::make_shared<DataTypeDateTime64>(9);
break;
case FormatSettings::DateTimeInputFormat::BestEffort:
if (tryParseDateTime64BestEffort(tmp, 9, buf, DateLUT::instance(), DateLUT::instance("UTC")) && buf.eof())
return true;
if (tryParseDateTime64BestEffortStrict(tmp, 9, buf, DateLUT::instance(), DateLUT::instance("UTC"), /*allowed_date_delimiters=*/"-/:") && buf.eof())
return std::make_shared<DataTypeDateTime64>(9);
break;
case FormatSettings::DateTimeInputFormat::BestEffortUS:
if (tryParseDateTime64BestEffortUS(tmp, 9, buf, DateLUT::instance(), DateLUT::instance("UTC")) && buf.eof())
return true;
if (tryParseDateTime64BestEffortUSStrict(tmp, 9, buf, DateLUT::instance(), DateLUT::instance("UTC"), /*allowed_date_delimiters=*/"-/:") && buf.eof())
return std::make_shared<DataTypeDateTime64>(9);
break;
}
return false;
return nullptr;
}
template <bool is_json>
@ -1439,8 +1479,11 @@ DataTypePtr tryInferDateOrDateTimeFromString(std::string_view field, const Forma
if (settings.try_infer_dates && tryInferDate(field))
return std::make_shared<DataTypeDate>();
if (settings.try_infer_datetimes && tryInferDateTime(field, settings))
return std::make_shared<DataTypeDateTime64>(9);
if (settings.try_infer_datetimes)
{
if (auto type = tryInferDateTimeOrDateTime64(field, settings))
return type;
}
return nullptr;
}

View File

@ -1271,7 +1271,7 @@ template void readJSONArrayInto<PaddedPODArray<UInt8>, void>(PaddedPODArray<UInt
template bool readJSONArrayInto<PaddedPODArray<UInt8>, bool>(PaddedPODArray<UInt8> & s, ReadBuffer & buf);
template <typename ReturnType>
ReturnType readDateTextFallback(LocalDate & date, ReadBuffer & buf)
ReturnType readDateTextFallback(LocalDate & date, ReadBuffer & buf, const char * allowed_delimiters)
{
static constexpr bool throw_exception = std::is_same_v<ReturnType, void>;
@ -1318,6 +1318,9 @@ ReturnType readDateTextFallback(LocalDate & date, ReadBuffer & buf)
}
else
{
if (!isSymbolIn(*buf.position(), allowed_delimiters))
return error();
++buf.position();
if (!append_digit(month))
@ -1325,7 +1328,11 @@ ReturnType readDateTextFallback(LocalDate & date, ReadBuffer & buf)
append_digit(month);
if (!buf.eof() && !isNumericASCII(*buf.position()))
{
if (!isSymbolIn(*buf.position(), allowed_delimiters))
return error();
++buf.position();
}
else
return error();
@ -1338,12 +1345,12 @@ ReturnType readDateTextFallback(LocalDate & date, ReadBuffer & buf)
return ReturnType(true);
}
template void readDateTextFallback<void>(LocalDate &, ReadBuffer &);
template bool readDateTextFallback<bool>(LocalDate &, ReadBuffer &);
template void readDateTextFallback<void>(LocalDate &, ReadBuffer &, const char * allowed_delimiters);
template bool readDateTextFallback<bool>(LocalDate &, ReadBuffer &, const char * allowed_delimiters);
template <typename ReturnType, bool dt64_mode>
ReturnType readDateTimeTextFallback(time_t & datetime, ReadBuffer & buf, const DateLUTImpl & date_lut)
ReturnType readDateTimeTextFallback(time_t & datetime, ReadBuffer & buf, const DateLUTImpl & date_lut, const char * allowed_date_delimiters, const char * allowed_time_delimiters)
{
static constexpr bool throw_exception = std::is_same_v<ReturnType, void>;
@ -1413,6 +1420,9 @@ ReturnType readDateTimeTextFallback(time_t & datetime, ReadBuffer & buf, const D
if (!isNumericASCII(s[0]) || !isNumericASCII(s[1]) || !isNumericASCII(s[2]) || !isNumericASCII(s[3])
|| !isNumericASCII(s[5]) || !isNumericASCII(s[6]) || !isNumericASCII(s[8]) || !isNumericASCII(s[9]))
return false;
if (!isSymbolIn(s[4], allowed_date_delimiters) || !isSymbolIn(s[7], allowed_date_delimiters))
return false;
}
UInt16 year = (s[0] - '0') * 1000 + (s[1] - '0') * 100 + (s[2] - '0') * 10 + (s[3] - '0');
@ -1443,6 +1453,9 @@ ReturnType readDateTimeTextFallback(time_t & datetime, ReadBuffer & buf, const D
if (!isNumericASCII(s[0]) || !isNumericASCII(s[1]) || !isNumericASCII(s[3]) || !isNumericASCII(s[4])
|| !isNumericASCII(s[6]) || !isNumericASCII(s[7]))
return false;
if (!isSymbolIn(s[2], allowed_time_delimiters) || !isSymbolIn(s[5], allowed_time_delimiters))
return false;
}
hour = (s[0] - '0') * 10 + (s[1] - '0');
@ -1488,10 +1501,10 @@ ReturnType readDateTimeTextFallback(time_t & datetime, ReadBuffer & buf, const D
return ReturnType(true);
}
template void readDateTimeTextFallback<void, false>(time_t &, ReadBuffer &, const DateLUTImpl &);
template void readDateTimeTextFallback<void, true>(time_t &, ReadBuffer &, const DateLUTImpl &);
template bool readDateTimeTextFallback<bool, false>(time_t &, ReadBuffer &, const DateLUTImpl &);
template bool readDateTimeTextFallback<bool, true>(time_t &, ReadBuffer &, const DateLUTImpl &);
template void readDateTimeTextFallback<void, false>(time_t &, ReadBuffer &, const DateLUTImpl &, const char *, const char *);
template void readDateTimeTextFallback<void, true>(time_t &, ReadBuffer &, const DateLUTImpl &, const char *, const char *);
template bool readDateTimeTextFallback<bool, false>(time_t &, ReadBuffer &, const DateLUTImpl &, const char *, const char *);
template bool readDateTimeTextFallback<bool, true>(time_t &, ReadBuffer &, const DateLUTImpl &, const char *, const char *);
template <typename ReturnType>

View File

@ -703,13 +703,28 @@ struct NullOutput
};
template <typename ReturnType>
ReturnType readDateTextFallback(LocalDate & date, ReadBuffer & buf);
ReturnType readDateTextFallback(LocalDate & date, ReadBuffer & buf, const char * allowed_delimiters);
inline bool isSymbolIn(char symbol, const char * symbols)
{
if (symbols == nullptr)
return true;
const char * pos = symbols;
while (*pos)
{
if (*pos == symbol)
return true;
++pos;
}
return false;
}
/// In YYYY-MM-DD format.
/// For convenience, Month and Day parts can have single digit instead of two digits.
/// Any separators other than '-' are supported.
template <typename ReturnType = void>
inline ReturnType readDateTextImpl(LocalDate & date, ReadBuffer & buf)
inline ReturnType readDateTextImpl(LocalDate & date, ReadBuffer & buf, const char * allowed_delimiters = nullptr)
{
static constexpr bool throw_exception = std::is_same_v<ReturnType, void>;
@ -753,6 +768,9 @@ inline ReturnType readDateTextImpl(LocalDate & date, ReadBuffer & buf)
}
else
{
if (!isSymbolIn(pos[-1], allowed_delimiters))
return error();
if (!isNumericASCII(pos[0]))
return error();
@ -768,6 +786,9 @@ inline ReturnType readDateTextImpl(LocalDate & date, ReadBuffer & buf)
if (isNumericASCII(pos[-1]) || !isNumericASCII(pos[0]))
return error();
if (!isSymbolIn(pos[-1], allowed_delimiters))
return error();
day = pos[0] - '0';
if (isNumericASCII(pos[1]))
{
@ -783,7 +804,7 @@ inline ReturnType readDateTextImpl(LocalDate & date, ReadBuffer & buf)
return ReturnType(true);
}
else
return readDateTextFallback<ReturnType>(date, buf);
return readDateTextFallback<ReturnType>(date, buf, allowed_delimiters);
}
inline void convertToDayNum(DayNum & date, ExtendedDayNum & from)
@ -797,15 +818,15 @@ inline void convertToDayNum(DayNum & date, ExtendedDayNum & from)
}
template <typename ReturnType = void>
inline ReturnType readDateTextImpl(DayNum & date, ReadBuffer & buf, const DateLUTImpl & date_lut)
inline ReturnType readDateTextImpl(DayNum & date, ReadBuffer & buf, const DateLUTImpl & date_lut, const char * allowed_delimiters = nullptr)
{
static constexpr bool throw_exception = std::is_same_v<ReturnType, void>;
LocalDate local_date;
if constexpr (throw_exception)
readDateTextImpl<ReturnType>(local_date, buf);
else if (!readDateTextImpl<ReturnType>(local_date, buf))
readDateTextImpl<ReturnType>(local_date, buf, allowed_delimiters);
else if (!readDateTextImpl<ReturnType>(local_date, buf, allowed_delimiters))
return false;
ExtendedDayNum ret = date_lut.makeDayNum(local_date.year(), local_date.month(), local_date.day());
@ -814,15 +835,15 @@ inline ReturnType readDateTextImpl(DayNum & date, ReadBuffer & buf, const DateLU
}
template <typename ReturnType = void>
inline ReturnType readDateTextImpl(ExtendedDayNum & date, ReadBuffer & buf, const DateLUTImpl & date_lut)
inline ReturnType readDateTextImpl(ExtendedDayNum & date, ReadBuffer & buf, const DateLUTImpl & date_lut, const char * allowed_delimiters = nullptr)
{
static constexpr bool throw_exception = std::is_same_v<ReturnType, void>;
LocalDate local_date;
if constexpr (throw_exception)
readDateTextImpl<ReturnType>(local_date, buf);
else if (!readDateTextImpl<ReturnType>(local_date, buf))
readDateTextImpl<ReturnType>(local_date, buf, allowed_delimiters);
else if (!readDateTextImpl<ReturnType>(local_date, buf, allowed_delimiters))
return false;
/// When the parameter is out of rule or out of range, Date32 uses 1925-01-01 as the default value (-DateLUT::instance().getDayNumOffsetEpoch(), -16436) and Date uses 1970-01-01.
@ -846,19 +867,19 @@ inline void readDateText(ExtendedDayNum & date, ReadBuffer & buf, const DateLUTI
readDateTextImpl<void>(date, buf, date_lut);
}
inline bool tryReadDateText(LocalDate & date, ReadBuffer & buf)
inline bool tryReadDateText(LocalDate & date, ReadBuffer & buf, const char * allowed_delimiters = nullptr)
{
return readDateTextImpl<bool>(date, buf);
return readDateTextImpl<bool>(date, buf, allowed_delimiters);
}
inline bool tryReadDateText(DayNum & date, ReadBuffer & buf, const DateLUTImpl & time_zone = DateLUT::instance())
inline bool tryReadDateText(DayNum & date, ReadBuffer & buf, const DateLUTImpl & time_zone = DateLUT::instance(), const char * allowed_delimiters = nullptr)
{
return readDateTextImpl<bool>(date, buf, time_zone);
return readDateTextImpl<bool>(date, buf, time_zone, allowed_delimiters);
}
inline bool tryReadDateText(ExtendedDayNum & date, ReadBuffer & buf, const DateLUTImpl & time_zone = DateLUT::instance())
inline bool tryReadDateText(ExtendedDayNum & date, ReadBuffer & buf, const DateLUTImpl & time_zone = DateLUT::instance(), const char * allowed_delimiters = nullptr)
{
return readDateTextImpl<bool>(date, buf, time_zone);
return readDateTextImpl<bool>(date, buf, time_zone, allowed_delimiters);
}
UUID parseUUID(std::span<const UInt8> src);
@ -975,13 +996,13 @@ inline T parseFromString(std::string_view str)
template <typename ReturnType = void, bool dt64_mode = false>
ReturnType readDateTimeTextFallback(time_t & datetime, ReadBuffer & buf, const DateLUTImpl & date_lut);
ReturnType readDateTimeTextFallback(time_t & datetime, ReadBuffer & buf, const DateLUTImpl & date_lut, const char * allowed_date_delimiters = nullptr, const char * allowed_time_delimiters = nullptr);
/** In YYYY-MM-DD hh:mm:ss or YYYY-MM-DD format, according to specified time zone.
* As an exception, also supported parsing of unix timestamp in form of decimal number.
*/
template <typename ReturnType = void, bool dt64_mode = false>
inline ReturnType readDateTimeTextImpl(time_t & datetime, ReadBuffer & buf, const DateLUTImpl & date_lut)
inline ReturnType readDateTimeTextImpl(time_t & datetime, ReadBuffer & buf, const DateLUTImpl & date_lut, const char * allowed_date_delimiters = nullptr, const char * allowed_time_delimiters = nullptr)
{
static constexpr bool throw_exception = std::is_same_v<ReturnType, void>;
@ -1014,6 +1035,9 @@ inline ReturnType readDateTimeTextImpl(time_t & datetime, ReadBuffer & buf, cons
if (!isNumericASCII(s[0]) || !isNumericASCII(s[1]) || !isNumericASCII(s[2]) || !isNumericASCII(s[3])
|| !isNumericASCII(s[5]) || !isNumericASCII(s[6]) || !isNumericASCII(s[8]) || !isNumericASCII(s[9]))
return ReturnType(false);
if (!isSymbolIn(s[4], allowed_date_delimiters) || !isSymbolIn(s[7], allowed_date_delimiters))
return ReturnType(false);
}
UInt16 year = (s[0] - '0') * 1000 + (s[1] - '0') * 100 + (s[2] - '0') * 10 + (s[3] - '0');
@ -1033,6 +1057,9 @@ inline ReturnType readDateTimeTextImpl(time_t & datetime, ReadBuffer & buf, cons
if (!isNumericASCII(s[11]) || !isNumericASCII(s[12]) || !isNumericASCII(s[14]) || !isNumericASCII(s[15])
|| !isNumericASCII(s[17]) || !isNumericASCII(s[18]))
return ReturnType(false);
if (!isSymbolIn(s[13], allowed_time_delimiters) || !isSymbolIn(s[16], allowed_time_delimiters))
return ReturnType(false);
}
hour = (s[11] - '0') * 10 + (s[12] - '0');
@ -1057,11 +1084,11 @@ inline ReturnType readDateTimeTextImpl(time_t & datetime, ReadBuffer & buf, cons
return readIntTextImpl<time_t, ReturnType, ReadIntTextCheckOverflow::CHECK_OVERFLOW>(datetime, buf);
}
else
return readDateTimeTextFallback<ReturnType, dt64_mode>(datetime, buf, date_lut);
return readDateTimeTextFallback<ReturnType, dt64_mode>(datetime, buf, date_lut, allowed_date_delimiters, allowed_time_delimiters);
}
template <typename ReturnType>
inline ReturnType readDateTimeTextImpl(DateTime64 & datetime64, UInt32 scale, ReadBuffer & buf, const DateLUTImpl & date_lut)
inline ReturnType readDateTimeTextImpl(DateTime64 & datetime64, UInt32 scale, ReadBuffer & buf, const DateLUTImpl & date_lut, const char * allowed_date_delimiters = nullptr, const char * allowed_time_delimiters = nullptr)
{
static constexpr bool throw_exception = std::is_same_v<ReturnType, void>;
@ -1075,7 +1102,7 @@ inline ReturnType readDateTimeTextImpl(DateTime64 & datetime64, UInt32 scale, Re
{
try
{
readDateTimeTextImpl<ReturnType, true>(whole, buf, date_lut);
readDateTimeTextImpl<ReturnType, true>(whole, buf, date_lut, allowed_date_delimiters, allowed_time_delimiters);
}
catch (const DB::Exception &)
{
@ -1085,7 +1112,7 @@ inline ReturnType readDateTimeTextImpl(DateTime64 & datetime64, UInt32 scale, Re
}
else
{
auto ok = readDateTimeTextImpl<ReturnType, true>(whole, buf, date_lut);
auto ok = readDateTimeTextImpl<ReturnType, true>(whole, buf, date_lut, allowed_date_delimiters, allowed_time_delimiters);
if (!ok && (buf.eof() || *buf.position() != '.'))
return ReturnType(false);
}
@ -1168,14 +1195,14 @@ inline void readDateTime64Text(DateTime64 & datetime64, UInt32 scale, ReadBuffer
readDateTimeTextImpl<void>(datetime64, scale, buf, date_lut);
}
inline bool tryReadDateTimeText(time_t & datetime, ReadBuffer & buf, const DateLUTImpl & time_zone = DateLUT::instance())
inline bool tryReadDateTimeText(time_t & datetime, ReadBuffer & buf, const DateLUTImpl & time_zone = DateLUT::instance(), const char * allowed_date_delimiters = nullptr, const char * allowed_time_delimiters = nullptr)
{
return readDateTimeTextImpl<bool>(datetime, buf, time_zone);
return readDateTimeTextImpl<bool>(datetime, buf, time_zone, allowed_date_delimiters, allowed_time_delimiters);
}
inline bool tryReadDateTime64Text(DateTime64 & datetime64, UInt32 scale, ReadBuffer & buf, const DateLUTImpl & date_lut = DateLUT::instance())
inline bool tryReadDateTime64Text(DateTime64 & datetime64, UInt32 scale, ReadBuffer & buf, const DateLUTImpl & date_lut = DateLUT::instance(), const char * allowed_date_delimiters = nullptr, const char * allowed_time_delimiters = nullptr)
{
return readDateTimeTextImpl<bool>(datetime64, scale, buf, date_lut);
return readDateTimeTextImpl<bool>(datetime64, scale, buf, date_lut, allowed_date_delimiters, allowed_time_delimiters);
}
inline void readDateTimeText(LocalDateTime & datetime, ReadBuffer & buf)

View File

@ -82,13 +82,14 @@ struct DateTimeSubsecondPart
UInt8 digits;
};
template <typename ReturnType, bool is_us_style>
template <typename ReturnType, bool is_us_style, bool strict = false, bool is_64 = false>
ReturnType parseDateTimeBestEffortImpl(
time_t & res,
ReadBuffer & in,
const DateLUTImpl & local_time_zone,
const DateLUTImpl & utc_time_zone,
DateTimeSubsecondPart * fractional)
DateTimeSubsecondPart * fractional,
const char * allowed_date_delimiters = nullptr)
{
auto on_error = [&]<typename... FmtArgs>(int error_code [[maybe_unused]],
FormatStringHelper<FmtArgs...> fmt_string [[maybe_unused]],
@ -170,22 +171,36 @@ ReturnType parseDateTimeBestEffortImpl(
fractional->digits = 3;
readDecimalNumber<3>(fractional->value, digits + 10);
}
else if constexpr (strict)
{
/// Fractional part is not allowed.
return on_error(ErrorCodes::CANNOT_PARSE_DATETIME, "Cannot read DateTime: unexpected fractional part");
}
return ReturnType(true);
}
else if (num_digits == 10 && !year && !has_time)
{
if (strict && month)
return on_error(ErrorCodes::CANNOT_PARSE_DATETIME, "Cannot read DateTime: month component is duplicated");
/// This is unix timestamp.
readDecimalNumber<10>(res, digits);
return ReturnType(true);
}
else if (num_digits == 9 && !year && !has_time)
{
if (strict && month)
return on_error(ErrorCodes::CANNOT_PARSE_DATETIME, "Cannot read DateTime: month component is duplicated");
/// This is unix timestamp.
readDecimalNumber<9>(res, digits);
return ReturnType(true);
}
else if (num_digits == 14 && !year && !has_time)
{
if (strict && month)
return on_error(ErrorCodes::CANNOT_PARSE_DATETIME, "Cannot read DateTime: month component is duplicated");
/// This is YYYYMMDDhhmmss
readDecimalNumber<4>(year, digits);
readDecimalNumber<2>(month, digits + 4);
@ -197,6 +212,9 @@ ReturnType parseDateTimeBestEffortImpl(
}
else if (num_digits == 8 && !year)
{
if (strict && month)
return on_error(ErrorCodes::CANNOT_PARSE_DATETIME, "Cannot read DateTime: month component is duplicated");
/// This is YYYYMMDD
readDecimalNumber<4>(year, digits);
readDecimalNumber<2>(month, digits + 4);
@ -272,6 +290,9 @@ ReturnType parseDateTimeBestEffortImpl(
else
return on_error(ErrorCodes::CANNOT_PARSE_DATETIME, "Cannot read DateTime: unexpected number of decimal digits after year and month: {}", num_digits);
}
if (!isSymbolIn(delimiter_after_year, allowed_date_delimiters))
return on_error(ErrorCodes::CANNOT_PARSE_DATETIME, "Cannot read DateTime: '{}' delimiter between date parts is not allowed", delimiter_after_year);
}
}
else if (num_digits == 2 || num_digits == 1)
@ -403,9 +424,16 @@ ReturnType parseDateTimeBestEffortImpl(
else
{
if (day_of_month)
{
if (strict && hour)
return on_error(ErrorCodes::CANNOT_PARSE_DATETIME, "Cannot read DateTime: hour component is duplicated");
hour = hour_or_day_of_month_or_month;
}
else
{
day_of_month = hour_or_day_of_month_or_month;
}
}
}
else if (num_digits != 0)
@ -446,6 +474,11 @@ ReturnType parseDateTimeBestEffortImpl(
fractional->digits = num_digits;
readDecimalNumber(fractional->value, num_digits, digits);
}
else if (strict)
{
/// Fractional part is not allowed.
return on_error(ErrorCodes::CANNOT_PARSE_DATETIME, "Cannot read DateTime: unexpected fractional part");
}
}
else if (c == '+' || c == '-')
{
@ -582,12 +615,24 @@ ReturnType parseDateTimeBestEffortImpl(
return on_error(ErrorCodes::CANNOT_PARSE_DATETIME, "Cannot read DateTime: neither Date nor Time was parsed successfully");
if (!day_of_month)
{
if constexpr (strict)
return on_error(ErrorCodes::CANNOT_PARSE_DATETIME, "Cannot read DateTime: day of month is required");
day_of_month = 1;
}
if (!month)
{
if constexpr (strict)
return on_error(ErrorCodes::CANNOT_PARSE_DATETIME, "Cannot read DateTime: month is required");
month = 1;
}
if (!year)
{
if constexpr (strict)
return on_error(ErrorCodes::CANNOT_PARSE_DATETIME, "Cannot read DateTime: year is required");
/// If year is not specified, it will be the current year if the date is unknown or not greater than today,
/// otherwise it will be the previous year.
/// This convoluted logic is needed to parse the syslog format, which looks as follows: "Mar 3 01:33:48".
@ -641,6 +686,20 @@ ReturnType parseDateTimeBestEffortImpl(
}
};
if constexpr (strict)
{
if constexpr (is_64)
{
if (year < 1900)
return on_error(ErrorCodes::CANNOT_PARSE_DATETIME, "Cannot read DateTime64: year {} is less than minimum supported year 1900", year);
}
else
{
if (year < 1970)
return on_error(ErrorCodes::CANNOT_PARSE_DATETIME, "Cannot read DateTime: year {} is less than minimum supported year 1970", year);
}
}
if (has_time_zone_offset)
{
res = utc_time_zone.makeDateTime(year, month, day_of_month, hour, minute, second);
@ -654,20 +713,20 @@ ReturnType parseDateTimeBestEffortImpl(
return ReturnType(true);
}
template <typename ReturnType, bool is_us_style>
ReturnType parseDateTime64BestEffortImpl(DateTime64 & res, UInt32 scale, ReadBuffer & in, const DateLUTImpl & local_time_zone, const DateLUTImpl & utc_time_zone)
template <typename ReturnType, bool is_us_style, bool strict = false>
ReturnType parseDateTime64BestEffortImpl(DateTime64 & res, UInt32 scale, ReadBuffer & in, const DateLUTImpl & local_time_zone, const DateLUTImpl & utc_time_zone, const char * allowed_date_delimiters = nullptr)
{
time_t whole;
DateTimeSubsecondPart subsecond = {0, 0}; // needs to be explicitly initialized sine it could be missing from input string
if constexpr (std::is_same_v<ReturnType, bool>)
{
if (!parseDateTimeBestEffortImpl<bool, is_us_style>(whole, in, local_time_zone, utc_time_zone, &subsecond))
if (!parseDateTimeBestEffortImpl<bool, is_us_style, strict, true>(whole, in, local_time_zone, utc_time_zone, &subsecond, allowed_date_delimiters))
return false;
}
else
{
parseDateTimeBestEffortImpl<ReturnType, is_us_style>(whole, in, local_time_zone, utc_time_zone, &subsecond);
parseDateTimeBestEffortImpl<ReturnType, is_us_style, strict, true>(whole, in, local_time_zone, utc_time_zone, &subsecond, allowed_date_delimiters);
}
@ -730,4 +789,24 @@ bool tryParseDateTime64BestEffortUS(DateTime64 & res, UInt32 scale, ReadBuffer &
return parseDateTime64BestEffortImpl<bool, true>(res, scale, in, local_time_zone, utc_time_zone);
}
bool tryParseDateTimeBestEffortStrict(time_t & res, ReadBuffer & in, const DateLUTImpl & local_time_zone, const DateLUTImpl & utc_time_zone, const char * allowed_date_delimiters)
{
return parseDateTimeBestEffortImpl<bool, false, true>(res, in, local_time_zone, utc_time_zone, nullptr, allowed_date_delimiters);
}
bool tryParseDateTimeBestEffortUSStrict(time_t & res, ReadBuffer & in, const DateLUTImpl & local_time_zone, const DateLUTImpl & utc_time_zone, const char * allowed_date_delimiters)
{
return parseDateTimeBestEffortImpl<bool, true, true>(res, in, local_time_zone, utc_time_zone, nullptr, allowed_date_delimiters);
}
bool tryParseDateTime64BestEffortStrict(DateTime64 & res, UInt32 scale, ReadBuffer & in, const DateLUTImpl & local_time_zone, const DateLUTImpl & utc_time_zone, const char * allowed_date_delimiters)
{
return parseDateTime64BestEffortImpl<bool, false, true>(res, scale, in, local_time_zone, utc_time_zone, allowed_date_delimiters);
}
bool tryParseDateTime64BestEffortUSStrict(DateTime64 & res, UInt32 scale, ReadBuffer & in, const DateLUTImpl & local_time_zone, const DateLUTImpl & utc_time_zone, const char * allowed_date_delimiters)
{
return parseDateTime64BestEffortImpl<bool, true, true>(res, scale, in, local_time_zone, utc_time_zone, allowed_date_delimiters);
}
}

View File

@ -63,4 +63,12 @@ void parseDateTime64BestEffort(DateTime64 & res, UInt32 scale, ReadBuffer & in,
bool tryParseDateTime64BestEffort(DateTime64 & res, UInt32 scale, ReadBuffer & in, const DateLUTImpl & local_time_zone, const DateLUTImpl & utc_time_zone);
void parseDateTime64BestEffortUS(DateTime64 & res, UInt32 scale, ReadBuffer & in, const DateLUTImpl & local_time_zone, const DateLUTImpl & utc_time_zone);
bool tryParseDateTime64BestEffortUS(DateTime64 & res, UInt32 scale, ReadBuffer & in, const DateLUTImpl & local_time_zone, const DateLUTImpl & utc_time_zone);
/// More strict version of best effort parsing. Requires day, month and year to be present, checks for allowed
/// delimiters between date components, makes additional correctness checks. Used in schema inference if date times.
bool tryParseDateTimeBestEffortStrict(time_t & res, ReadBuffer & in, const DateLUTImpl & local_time_zone, const DateLUTImpl & utc_time_zone, const char * allowed_date_delimiters);
bool tryParseDateTimeBestEffortUSStrict(time_t & res, ReadBuffer & in, const DateLUTImpl & local_time_zone, const DateLUTImpl & utc_time_zone, const char * allowed_date_delimiters);
bool tryParseDateTime64BestEffortStrict(DateTime64 & res, UInt32 scale, ReadBuffer & in, const DateLUTImpl & local_time_zone, const DateLUTImpl & utc_time_zone, const char * allowed_date_delimiters);
bool tryParseDateTime64BestEffortUSStrict(DateTime64 & res, UInt32 scale, ReadBuffer & in, const DateLUTImpl & local_time_zone, const DateLUTImpl & utc_time_zone, const char * allowed_date_delimiters);
}

View File

@ -1 +1 @@
c1 Nullable(DateTime64(9))
c1 Nullable(DateTime)

View File

@ -1,29 +1,29 @@
JSONEachRow
x Nullable(Date)
x Nullable(DateTime64(9))
x Nullable(DateTime64(9))
x Nullable(DateTime)
x Array(Nullable(Date))
x Array(Nullable(DateTime64(9)))
x Array(Nullable(DateTime64(9)))
x Tuple(\n date1 Nullable(DateTime64(9)),\n date2 Nullable(Date))
x Array(Nullable(DateTime64(9)))
x Array(Nullable(DateTime64(9)))
x Nullable(DateTime64(9))
x Array(Nullable(DateTime))
x Array(Nullable(DateTime))
x Tuple(\n date1 Nullable(DateTime),\n date2 Nullable(Date))
x Array(Nullable(DateTime))
x Array(Nullable(DateTime))
x Nullable(DateTime)
x Array(Nullable(String))
x Nullable(String)
x Array(Nullable(String))
x Tuple(\n key1 Array(Array(Nullable(DateTime64(9)))),\n key2 Array(Array(Nullable(String))))
x Tuple(\n key1 Array(Array(Nullable(DateTime))),\n key2 Array(Array(Nullable(String))))
CSV
c1 Nullable(Date)
c1 Nullable(DateTime64(9))
c1 Nullable(DateTime64(9))
c1 Nullable(DateTime)
c1 Array(Nullable(Date))
c1 Array(Nullable(DateTime64(9)))
c1 Array(Nullable(DateTime64(9)))
c1 Map(String, Nullable(DateTime64(9)))
c1 Array(Nullable(DateTime64(9)))
c1 Array(Nullable(DateTime64(9)))
c1 Nullable(DateTime64(9))
c1 Array(Nullable(DateTime))
c1 Array(Nullable(DateTime))
c1 Map(String, Nullable(DateTime))
c1 Array(Nullable(DateTime))
c1 Array(Nullable(DateTime))
c1 Nullable(DateTime)
c1 Array(Nullable(String))
c1 Nullable(String)
c1 Array(Nullable(String))
@ -31,14 +31,14 @@ c1 Map(String, Array(Array(Nullable(String))))
TSV
c1 Nullable(Date)
c1 Nullable(DateTime64(9))
c1 Nullable(DateTime64(9))
c1 Nullable(DateTime)
c1 Array(Nullable(Date))
c1 Array(Nullable(DateTime64(9)))
c1 Array(Nullable(DateTime64(9)))
c1 Map(String, Nullable(DateTime64(9)))
c1 Array(Nullable(DateTime64(9)))
c1 Array(Nullable(DateTime64(9)))
c1 Nullable(DateTime64(9))
c1 Array(Nullable(DateTime))
c1 Array(Nullable(DateTime))
c1 Map(String, Nullable(DateTime))
c1 Array(Nullable(DateTime))
c1 Array(Nullable(DateTime))
c1 Nullable(DateTime)
c1 Array(Nullable(String))
c1 Nullable(String)
c1 Array(Nullable(String))
@ -46,14 +46,14 @@ c1 Map(String, Array(Array(Nullable(String))))
Values
c1 Nullable(Date)
c1 Nullable(DateTime64(9))
c1 Nullable(DateTime64(9))
c1 Nullable(DateTime)
c1 Array(Nullable(Date))
c1 Array(Nullable(DateTime64(9)))
c1 Array(Nullable(DateTime64(9)))
c1 Map(String, Nullable(DateTime64(9)))
c1 Array(Nullable(DateTime64(9)))
c1 Array(Nullable(DateTime64(9)))
c1 Nullable(DateTime64(9))
c1 Array(Nullable(DateTime))
c1 Array(Nullable(DateTime))
c1 Map(String, Nullable(DateTime))
c1 Array(Nullable(DateTime))
c1 Array(Nullable(DateTime))
c1 Nullable(DateTime)
c1 Array(Nullable(String))
c1 Nullable(String)
c1 Array(Nullable(String))

View File

@ -0,0 +1,10 @@
0,"1970-01-01"
1,"1970-01-02"
2,"1970-01-03"
3,"1970-01-04"
4,"1970-01-05"
5,"1970-01-06"
6,"1970-01-07"
7,"1970-01-08"
8,"1970-01-09"
9,"1970-01-10"
1 0 1970-01-01
2 1 1970-01-02
3 2 1970-01-03
4 3 1970-01-04
5 4 1970-01-05
6 5 1970-01-06
7 6 1970-01-07
8 7 1970-01-08
9 8 1970-01-09
10 9 1970-01-10

View File

@ -0,0 +1,11 @@
"number","toDate(number)"
0,"1970-01-01"
1,"1970-01-02"
2,"1970-01-03"
3,"1970-01-04"
4,"1970-01-05"
5,"1970-01-06"
6,"1970-01-07"
7,"1970-01-08"
8,"1970-01-09"
9,"1970-01-10"

View File

@ -0,0 +1,10 @@
0 1970-01-01
1 1970-01-02
2 1970-01-03
3 1970-01-04
4 1970-01-05
5 1970-01-06
6 1970-01-07
7 1970-01-08
8 1970-01-09
9 1970-01-10

View File

@ -0,0 +1,10 @@
["0", "1970-01-01"]
["1", "1970-01-02"]
["2", "1970-01-03"]
["3", "1970-01-04"]
["4", "1970-01-05"]
["5", "1970-01-06"]
["6", "1970-01-07"]
["7", "1970-01-08"]
["8", "1970-01-09"]
["9", "1970-01-10"]

View File

@ -0,0 +1,10 @@
{"number":"0","toDate(number)":"1970-01-01"}
{"number":"1","toDate(number)":"1970-01-02"}
{"number":"2","toDate(number)":"1970-01-03"}
{"number":"3","toDate(number)":"1970-01-04"}
{"number":"4","toDate(number)":"1970-01-05"}
{"number":"5","toDate(number)":"1970-01-06"}
{"number":"6","toDate(number)":"1970-01-07"}
{"number":"7","toDate(number)":"1970-01-08"}
{"number":"8","toDate(number)":"1970-01-09"}
{"number":"9","toDate(number)":"1970-01-10"}

View File

@ -0,0 +1,10 @@
number=0 toDate(number)=1970-01-01
number=1 toDate(number)=1970-01-02
number=2 toDate(number)=1970-01-03
number=3 toDate(number)=1970-01-04
number=4 toDate(number)=1970-01-05
number=5 toDate(number)=1970-01-06
number=6 toDate(number)=1970-01-07
number=7 toDate(number)=1970-01-08
number=8 toDate(number)=1970-01-09
number=9 toDate(number)=1970-01-10

View File

@ -0,0 +1,10 @@
0 1970-01-01
1 1970-01-02
2 1970-01-03
3 1970-01-04
4 1970-01-05
5 1970-01-06
6 1970-01-07
7 1970-01-08
8 1970-01-09
9 1970-01-10
1 0 1970-01-01
2 1 1970-01-02
3 2 1970-01-03
4 3 1970-01-04
5 4 1970-01-05
6 5 1970-01-06
7 6 1970-01-07
8 7 1970-01-08
9 8 1970-01-09
10 9 1970-01-10

View File

@ -0,0 +1,11 @@
number toDate(number)
0 1970-01-01
1 1970-01-02
2 1970-01-03
3 1970-01-04
4 1970-01-05
5 1970-01-06
6 1970-01-07
7 1970-01-08
8 1970-01-09
9 1970-01-10

View File

@ -0,0 +1 @@
(0,'1970-01-01'),(1,'1970-01-02'),(2,'1970-01-03'),(3,'1970-01-04'),(4,'1970-01-05'),(5,'1970-01-06'),(6,'1970-01-07'),(7,'1970-01-08'),(8,'1970-01-09'),(9,'1970-01-10')

View File

@ -4,7 +4,7 @@ c2 Nullable(Date)
c1 Nullable(Float64)
c2 Nullable(Date)
c1 Nullable(Int64)
c2 Nullable(DateTime64(9))
c2 Nullable(DateTime)
c1 UInt8
c2 Nullable(Date)
4
@ -14,7 +14,7 @@ toDate(number) Nullable(Date)
number Nullable(Float64)
toDate(number) Nullable(Date)
number Nullable(Int64)
toDate(number) Nullable(DateTime64(9))
toDate(number) Nullable(DateTime)
number Nullable(Int64)
toDate(number) Nullable(Date)
4
@ -24,7 +24,7 @@ c2 Nullable(Date)
c1 Nullable(Float64)
c2 Nullable(Date)
c1 Nullable(Int64)
c2 Nullable(DateTime64(9))
c2 Nullable(DateTime)
c1 UInt8
c2 Nullable(Date)
4
@ -34,7 +34,7 @@ toDate(number) Nullable(Date)
number Nullable(Float64)
toDate(number) Nullable(Date)
number Nullable(Int64)
toDate(number) Nullable(DateTime64(9))
toDate(number) Nullable(DateTime)
number Nullable(Int64)
toDate(number) Nullable(Date)
4
@ -44,7 +44,7 @@ toDate(number) Nullable(Date)
number Nullable(Float64)
toDate(number) Nullable(Date)
number Nullable(Int64)
toDate(number) Nullable(DateTime64(9))
toDate(number) Nullable(DateTime)
number Nullable(Int64)
toDate(number) Nullable(Date)
4
@ -54,7 +54,7 @@ c2 Nullable(Date)
c1 Nullable(Float64)
c2 Nullable(Date)
c1 Nullable(Int64)
c2 Nullable(DateTime64(9))
c2 Nullable(DateTime)
c1 UInt8
c2 Nullable(Date)
4
@ -64,7 +64,7 @@ toDate(number) Nullable(Date)
number Nullable(Float64)
toDate(number) Nullable(Date)
number Nullable(Int64)
toDate(number) Nullable(DateTime64(9))
toDate(number) Nullable(DateTime)
number Nullable(Int64)
toDate(number) Nullable(Date)
4
@ -74,7 +74,7 @@ c2 Nullable(Date)
c1 Nullable(Float64)
c2 Nullable(Date)
c1 Nullable(Int64)
c2 Nullable(DateTime64(9))
c2 Nullable(DateTime)
c1 UInt8
c2 Nullable(Date)
4
@ -84,7 +84,7 @@ c2 Nullable(Date)
c1 Nullable(Float64)
c2 Nullable(Date)
c1 Nullable(Int64)
c2 Nullable(DateTime64(9))
c2 Nullable(DateTime)
c1 UInt8
c2 Nullable(Date)
4

View File

@ -4,7 +4,7 @@ JSON
{"d":"str","dynamicType(d)":"String"}
{"d":["1","2","3"],"dynamicType(d)":"Array(Int64)"}
{"d":"2020-01-01","dynamicType(d)":"Date"}
{"d":"2020-01-01 10:00:00.000000000","dynamicType(d)":"DateTime64(9)"}
{"d":"2020-01-01 10:00:00","dynamicType(d)":"DateTime"}
{"d":{"a":"42","b":"str"},"dynamicType(d)":"Tuple(a Int64, b String)"}
{"d":{"a":"43"},"dynamicType(d)":"Tuple(a Int64)"}
{"d":{"a":"44","c":["1","2","3"]},"dynamicType(d)":"Tuple(a Int64, c Array(Int64))"}
@ -22,7 +22,7 @@ CSV
"str","String"
"[1,2,3]","Array(Int64)"
"2020-01-01","Date"
"2020-01-01 10:00:00.000000000","DateTime64(9)"
"2020-01-01 10:00:00","DateTime"
"[1, 'str', [1, 2, 3]]","String"
\N,"None"
true,"Bool"
@ -32,24 +32,24 @@ TSV
str String
[1,2,3] Array(Int64)
2020-01-01 Date
2020-01-01 10:00:00.000000000 DateTime64(9)
2020-01-01 10:00:00 DateTime
[1, \'str\', [1, 2, 3]] String
\N None
true Bool
Values
(42,'Int64'),(42.42,'Float64'),('str','String'),([1,2,3],'Array(Int64)'),('2020-01-01','Date'),('2020-01-01 10:00:00.000000000','DateTime64(9)'),(NULL,'None'),(true,'Bool')
(42,'Int64'),(42.42,'Float64'),('str','String'),([1,2,3],'Array(Int64)'),('2020-01-01','Date'),('2020-01-01 10:00:00','DateTime'),(NULL,'None'),(true,'Bool')
Cast using parsing
42 Int64
42.42 Float64
[1,2,3] Array(Int64)
2020-01-01 Date
2020-01-01 10:00:00.000000000 DateTime64(9)
2020-01-01 10:00:00 DateTime
NULL String
true Bool
42 Int64 false
42.42 Float64 false
[1,2,3] Array(Int64) false
2020-01-01 Date true
2020-01-01 10:00:00.000000000 DateTime64(9) true
2020-01-01 10:00:00 DateTime true
NULL String true
true Bool true

View File

@ -12,7 +12,7 @@ Hello String
[1,2,3] Array(Nullable(Int64))
['str1','str2','str3'] Array(Nullable(String))
[[[1],[2,3,4]],[[5,6],[7]]] Array(Array(Array(Nullable(Int64))))
['2020-01-01 00:00:00.000000000','2020-01-01 00:00:00.000000000'] Array(Nullable(DateTime64(9)))
['2020-01-01 00:00:00','2020-01-01 00:00:00'] Array(Nullable(DateTime))
['2020-01-01','2020-01-01 date'] Array(Nullable(String))
['2020-01-01','2020-01-01 00:00:00','str'] Array(Nullable(String))
['2020-01-01','2020-01-01 00:00:00','42'] Array(Nullable(String))

View File

@ -1,2 +1,2 @@
x Nullable(Int64)
schema_inference_hints=, max_rows_to_read_for_schema_inference=25000, max_bytes_to_read_for_schema_inference=1000, schema_inference_make_columns_nullable=true, try_infer_integers=true, try_infer_dates=true, try_infer_datetimes=true, try_infer_numbers_from_strings=false, read_bools_as_numbers=true, read_bools_as_strings=true, read_objects_as_strings=true, read_numbers_as_strings=true, read_arrays_as_strings=true, try_infer_objects_as_tuples=true, infer_incomplete_types_as_strings=true, try_infer_objects=false, use_string_type_for_ambiguous_paths_in_named_tuples_inference_from_objects=false
schema_inference_hints=, max_rows_to_read_for_schema_inference=25000, max_bytes_to_read_for_schema_inference=1000, schema_inference_make_columns_nullable=true, try_infer_integers=true, try_infer_dates=true, try_infer_datetimes=true, try_infer_datetimes_only_datetime64=false, try_infer_numbers_from_strings=false, read_bools_as_numbers=true, read_bools_as_strings=true, read_objects_as_strings=true, read_numbers_as_strings=true, read_arrays_as_strings=true, try_infer_objects_as_tuples=true, infer_incomplete_types_as_strings=true, try_infer_objects=false, use_string_type_for_ambiguous_paths_in_named_tuples_inference_from_objects=false

View File

@ -0,0 +1,253 @@
Date
2020-01-01 Date
2020-01-01 Date
2020-01-01 Date
2020-01-01 Date
2020-01-01 Date
2020-01-01 Date
2020-01-01 Date
2020-01-01 Date
2020-01-01 Date
2020-01-01 Date
2020-01-01 Date
2020-01-01 Date
String
2020_01_01 String
2020_1_01 String
2020_01_1 String
2020_1_1 String
2020a01a01 String
2020a1a01 String
2020a01a1 String
2020a1a1 String
20200101 String
DateTime
2020-01-02 18:42:42 DateTime
2020-01-02 18:42:42 DateTime
2020-01-02 18:42:42 DateTime
String
2020_01_01 42:42:42 String
2020a01a01 42:42:42 String
2020-01-01 42.42.42 String
2020-01-01 42 42 42 String
2020-01-01 42a42a42 String
DateTime64
2020-01-02 18:42:42.424200000 DateTime64(9)
2020-01-02 18:42:42.424200000 DateTime64(9)
2020-01-02 18:42:42.424200000 DateTime64(9)
String
2020_01_01 42:42:42.4242 String
2020a01a01 42:42:42.4242 String
2020-01-01 42.42.42.4242 String
2020-01-01 42 42 42.4242 String
2020-01-01 42a42a42.4242 String
DateTime/DateTime64 best effort
2000-01-01 00:00:00 DateTime
2000-01-01 01:00:00 DateTime
2000-01-01 01:00:00.000000000 DateTime64(9)
2017-01-01 22:02:03 DateTime
2017-01-01 22:02:03.000000000 DateTime64(9)
2017-01-01 21:02:03 DateTime
2017-01-01 21:02:03.000000000 DateTime64(9)
2017-01-01 22:02:03 DateTime
2017-01-01 22:02:03.000000000 DateTime64(9)
2017-01-02 01:02:03 DateTime
2017-01-02 01:02:03.000000000 DateTime64(9)
1970-01-02 01:02:03 DateTime
1970-01-02 01:02:03.000000000 DateTime64(9)
1970-01-02 01:02:03 DateTime
1970-01-02 01:02:03.000000000 DateTime64(9)
2018-02-11 03:40:50 DateTime
2018-02-11 03:40:50.000000000 DateTime64(9)
2000-04-17 01:02:03 DateTime
2000-04-17 01:02:03.000000000 DateTime64(9)
1970-01-02 01:00:00 DateTime
1970-01-02 01:00:00.000000000 DateTime64(9)
1970-01-02 01:02:03 DateTime
1970-01-02 01:02:03.000000000 DateTime64(9)
1970-01-02 01:02:03 DateTime
1970-01-02 01:02:03.000000000 DateTime64(9)
2015-12-31 20:00:00 DateTime
2015-12-31 20:00:00 DateTime
2016-01-01 00:00:00 DateTime
2016-01-01 00:00:00 DateTime
2017-01-01 22:02:03 DateTime
2017-01-01 22:02:03.000000000 DateTime64(9)
2017-01-02 03:04:05 DateTime
2017-01-02 03:04:05.000000000 DateTime64(9)
2017-01-02 03:04:05 DateTime
2017-01-02 03:04:05.000000000 DateTime64(9)
2017-01-02 03:04:05 DateTime
2017-01-02 03:04:05.000000000 DateTime64(9)
2017-01-02 03:04:05 DateTime
2017-01-02 03:04:05.000000000 DateTime64(9)
2017-01-02 04:04:05 DateTime
2017-01-02 04:04:05.000000000 DateTime64(9)
2017-01-02 02:34:05 DateTime
2017-01-02 02:34:05.000000000 DateTime64(9)
2017-01-02 00:04:05 DateTime
2017-01-02 00:04:05.000000000 DateTime64(9)
2017-01-02 02:04:05 DateTime
2017-01-02 02:04:05.000000000 DateTime64(9)
2017-01-02 00:04:05 DateTime
2017-01-02 00:04:05.000000000 DateTime64(9)
2017-01-01 18:04:05 DateTime
2017-01-01 18:04:05.000000000 DateTime64(9)
2017-01-02 03:04:05 DateTime
2017-01-02 03:04:05.000000000 DateTime64(9)
2017-01-01 23:04:05 DateTime
2017-01-01 23:04:05.000000000 DateTime64(9)
2017-02-01 23:04:05 DateTime
2017-02-01 23:04:05.000000000 DateTime64(9)
2017-06-01 23:04:05 DateTime
2017-06-01 23:04:05.000000000 DateTime64(9)
2017-01-02 00:04:05 DateTime
2017-01-02 00:04:05.000000000 DateTime64(9)
2017-01-02 03:04:05 DateTime
2017-01-02 03:04:05.000000000 DateTime64(9)
2017-01-02 03:04:05 DateTime
2017-01-02 03:04:05.000000000 DateTime64(9)
2017-01-02 04:04:05 DateTime
2017-01-02 04:04:05.000000000 DateTime64(9)
2017-01-02 04:04:05 DateTime
2017-01-02 04:04:05.000000000 DateTime64(9)
2017-01-02 02:04:05 DateTime
2017-01-02 02:04:05.000000000 DateTime64(9)
2017-01-02 03:04:05 DateTime
2017-01-02 03:04:05.000000000 DateTime64(9)
2017-04-01 11:22:33 DateTime
2017-04-01 11:22:33.000000000 DateTime64(9)
2017-04-01 22:02:03 DateTime
2017-04-01 22:02:03.000000000 DateTime64(9)
2017-04-01 22:02:03 DateTime
2017-04-01 22:02:03.000000000 DateTime64(9)
2017-04-02 01:02:03 DateTime
2017-04-02 01:02:03.000000000 DateTime64(9)
2017-04-02 11:22:33 DateTime
2017-04-02 11:22:33.000000000 DateTime64(9)
2017-04-02 01:02:03 DateTime
2017-04-02 01:02:03.000000000 DateTime64(9)
2017-04-02 01:22:33 DateTime
2017-04-02 01:22:33.000000000 DateTime64(9)
2017-04-02 01:02:03 DateTime
2017-04-02 01:02:03.000000000 DateTime64(9)
2017-04-02 01:02:33 DateTime
2017-04-02 01:02:33.000000000 DateTime64(9)
2017-04-01 22:02:03 DateTime
2017-04-01 22:02:03.000000000 DateTime64(9)
2017-04-02 01:02:03 DateTime
2017-04-02 01:02:03.000000000 DateTime64(9)
2017-04-01 22:02:03 DateTime
2017-04-01 22:02:03.000000000 DateTime64(9)
2017-04-01 21:02:03 DateTime
2017-04-01 21:02:03.000000000 DateTime64(9)
2017-04-02 01:02:03 DateTime
2017-04-02 01:02:03.000000000 DateTime64(9)
2017-01-01 22:02:03 DateTime
2017-01-01 22:02:03.000000000 DateTime64(9)
2017-04-25 01:02:03 DateTime
2017-04-25 01:02:03.000000000 DateTime64(9)
2017-04-25 01:02:03 DateTime
2017-04-25 01:02:03.000000000 DateTime64(9)
2017-01-25 01:02:03 DateTime
2017-01-25 01:02:03.000000000 DateTime64(9)
2017-01-24 22:02:03 DateTime
2017-01-24 22:02:03.000000000 DateTime64(9)
2017-01-25 13:02:03 DateTime
2017-01-25 13:02:03.000000000 DateTime64(9)
2017-01-25 01:02:03 DateTime
2017-01-25 01:02:03.000000000 DateTime64(9)
2017-01-25 01:02:03 DateTime
2017-01-25 01:02:03.000000000 DateTime64(9)
2017-01-24 22:02:03 DateTime
2017-01-24 22:02:03.000000000 DateTime64(9)
2017-01-24 22:02:03 DateTime
2017-01-24 22:02:03.000000000 DateTime64(9)
2017-01-25 10:02:03 DateTime
2017-01-25 10:02:03.000000000 DateTime64(9)
2017-01-25 10:02:03 DateTime
2017-01-25 10:02:03.000000000 DateTime64(9)
2017-01-25 10:02:03 DateTime
2017-01-25 10:02:03.000000000 DateTime64(9)
2017-01-25 09:32:03 DateTime
2017-01-25 09:32:03.000000000 DateTime64(9)
2017-01-25 01:02:03 DateTime
2017-01-25 01:02:03.000000000 DateTime64(9)
2017-01-25 13:02:03 DateTime
2017-01-25 13:02:03.000000000 DateTime64(9)
2017-01-25 13:02:03 DateTime
2017-01-25 13:02:03.000000000 DateTime64(9)
2017-01-25 10:02:03 DateTime
2017-01-25 10:02:03.000000000 DateTime64(9)
2018-02-11 03:40:50 DateTime
2018-02-11 03:40:50.000000000 DateTime64(9)
2018-02-11 03:40:50 DateTime
2018-02-11 03:40:50.000000000 DateTime64(9)
String
2 String
20 String
200 String
2000 String
20000 String
200001 String
2000010 String
20000101 String
200001010 String
2000010101 String
20000101010 String
200001010101 String
2000010101010 String
20000101010101 String
2.1 String
20.1 String
200.1 String
2000.1 String
20000.1 String
200001.1 String
2000010.1 String
20000101.1 String
200001010.1 String
2000010101.1 String
20000101010.1 String
200001010101.1 String
2000010101010.1 String
20000101010101.1 String
Mar String
Mar1 String
Mar 1 String
Mar01 String
Mar 01 String
Mar2020 String
Mar 2020 String
Mar012020 String
Mar 012020 String
Mar01012020 String
Mar 01012020 String
Mar0101202001 String
Mar 0101202001 String
Mar010120200101 String
Mar 010120200101 String
Mar01012020010101 String
Mar 01012020010101 String
Mar01012020010101.000 String
Mar 0101202001010101.000 String
2000 01 01 01:00:00 String
2000 01 01 01:00:00.000 String
2000a01a01 01:00:00 String
2000a01a01 01:00:00.000 String
2000-01-01 01 00 00 String
2000-01-01 01 00 00.000 String
2000-01-01 01-00-00 String
2000-01-01 01-00-00.000 String
2000-01-01 01a00a00 String
2000-01-01 01a00a00.000 String
2000-01 01:00:00 String
2000-01 01:00:00.000 String
2000 01 String
2000-01 String
Mar 2000 00:00:00 String
Mar 2000 00:00:00.000 String
2000 00:00:00 String
2000 00:00:00.000 String
Mar 2000-01-01 00:00:00 String
Mar 2000-01-01 00:00:00.000 String

View File

@ -0,0 +1,269 @@
set input_format_try_infer_datetimes = 1;
set input_format_try_infer_dates = 1;
set schema_inference_make_columns_nullable = 0;
set input_format_json_try_infer_numbers_from_strings = 0;
set session_timezone = 'UTC';
select 'Date';
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020:01:01"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020:1:01"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020:01:1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020:1:1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020-01-01"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020-1-01"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020-01-1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020-1-1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020/01/01"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020/1/01"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020/01/1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020/1/1"}');
select 'String';
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020_01_01"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020_1_01"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020_01_1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020_1_1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020a01a01"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020a1a01"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020a01a1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020a1a1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "20200101"}');
select 'DateTime';
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020:01:01 42:42:42"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020/01/01 42:42:42"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020-01-01 42:42:42"}');
select 'String';
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020_01_01 42:42:42"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020a01a01 42:42:42"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020-01-01 42.42.42"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020-01-01 42 42 42"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020-01-01 42a42a42"}');
select 'DateTime64';
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020:01:01 42:42:42.4242"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020/01/01 42:42:42.4242"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020-01-01 42:42:42.4242"}');
select 'String';
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020_01_01 42:42:42.4242"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020a01a01 42:42:42.4242"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020-01-01 42.42.42.4242"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020-01-01 42 42 42.4242"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2020-01-01 42a42a42.4242"}');
set date_time_input_format='best_effort';
select 'DateTime/DateTime64 best effort';
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000-01-01 00:00:00"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000-01-01 01:00:00"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000-01-01 01:00:00.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "02/01/17 010203 MSK"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "02/01/17 010203.000 MSK"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "02/01/17 010203 MSK+0100"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "02/01/17 010203.000 MSK+0100"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "02/01/17 010203 UTC+0300"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "02/01/17 010203.000 UTC+0300"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "02/01/17 010203Z"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "02/01/17 010203.000Z"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "02/01/1970 010203Z"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "02/01/1970 010203.000Z"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "02/01/70 010203Z"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "02/01/70 010203.000Z"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "11 Feb 2018 06:40:50 +0300"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "11 Feb 2018 06:40:50.000 +0300"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "17 Apr 2000 2 1:2:3"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "17 Apr 2000 2 1:2:3.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "19700102 01:00:00"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "19700102 01:00:00.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "19700102010203Z"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "19700102010203Z.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "1970/01/02 010203Z"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "1970/01/02 010203.000Z"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2016-01-01MSD"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2016-01-01 MSD"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2016-01-01UTC"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2016-01-01Z"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "201701 02 010203 UTC+0300"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "201701 02 010203.000 UTC+0300"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05+0"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05.000+0"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05+00"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05.000+00"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05+0000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05.000+0000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05 -0100"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05.000 -0100"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05+030"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05.000+030"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05+0300"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05.000+0300"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05+1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05.000+1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05+300"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05.000+300"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05+900"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05.000+900"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05GMT"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05.000GMT"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05 MSD"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05.000 MSD"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05 MSD Feb"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05.000 MSD Feb"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05 MSD Jun"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05.000 MSD Jun"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05 MSK"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02 03:04:05.000 MSK"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02T03:04:05"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02T03:04:05.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02T03:04:05+00"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02T03:04:05.000+00"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02T03:04:05 -0100"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02T03:04:05.000 -0100"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02T03:04:05-0100"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02T03:04:05.000-0100"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02T03:04:05+0100"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02T03:04:05.000+0100"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02T03:04:05Z"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017-01-02T03:04:05.000Z"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 01 11:22:33"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 01 11:22:33.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 010203 UTC+0300"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 010203.000 UTC+0300"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 01:2:3 UTC+0300"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 01:2:3.000 UTC+0300"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 1:02:3"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 1:02:3.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 11:22:33"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 11:22:33.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 1:2:03"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 1:2:03.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 1:22:33"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 1:22:33.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 1:2:3"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 1:2:3.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 1:2:33"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 1:2:33.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 1:2:3 MSK"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 1:2:3.000 MSK"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 1:2:3 UTC+0000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 1:2:3.000 UTC+0000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 1:2:3 UTC+0300"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 1:2:3.000 UTC+0300"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 1:2:3 UTC+0400"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 02 1:2:3.000 UTC+0400"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 2 1:2:3"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Apr 2 1:2:3.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Jan 02 010203 UTC+0300"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2017 Jan 02 010203.000 UTC+0300"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Apr 2017 01:02:03"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Apr 2017 01:02:03.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Apr 2017 1:2:3"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Apr 2017 1:2:3.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3 MSK"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3.000 MSK"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3 PM"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3.000 PM"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3Z"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3.000Z"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3 Z"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3.000 Z"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3 Z +0300"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3.000 Z +0300"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3 Z+03:00"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3.000 Z+03:00"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3 Z +03:00 PM"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3.000 Z +03:00 PM"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3 Z +0300 PM"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3.000 Z +0300 PM"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3 Z+03:00 PM"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3.000 Z+03:00 PM"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3 Z +03:30 PM"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3.000 Z +03:30 PM"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3Z Mon"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3.000Z Mon"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3 Z PM"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3.000 Z PM"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3Z PM"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3.000Z PM"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3 Z PM +03:00"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "25 Jan 2017 1:2:3.000 Z PM +03:00"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Sun 11 Feb 2018 06:40:50 +0300"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Sun 11 Feb 2018 06:40:50.000 +0300"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Sun, 11 Feb 2018 06:40:50 +0300"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Sun, 11 Feb 2018 06:40:50.000 +0300"}');
select 'String';
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "20"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "200"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "20000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "200001"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000010"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "20000101"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "200001010"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000010101"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "20000101010"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "200001010101"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000010101010"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "20000101010101"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2.1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "20.1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "200.1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000.1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "20000.1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "200001.1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000010.1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "20000101.1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "200001010.1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000010101.1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "20000101010.1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "200001010101.1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000010101010.1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "20000101010101.1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Mar"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Mar1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Mar 1"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Mar01"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Mar 01"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Mar2020"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Mar 2020"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Mar012020"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Mar 012020"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Mar01012020"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Mar 01012020"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Mar0101202001"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Mar 0101202001"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Mar010120200101"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Mar 010120200101"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Mar01012020010101"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Mar 01012020010101"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Mar01012020010101.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Mar 0101202001010101.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000 01 01 01:00:00"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000 01 01 01:00:00.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000a01a01 01:00:00"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000a01a01 01:00:00.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000-01-01 01 00 00"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000-01-01 01 00 00.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000-01-01 01-00-00"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000-01-01 01-00-00.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000-01-01 01a00a00"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000-01-01 01a00a00.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000-01 01:00:00"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000-01 01:00:00.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000 01"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000-01"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Mar 2000 00:00:00"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Mar 2000 00:00:00.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000 00:00:00"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "2000 00:00:00.000"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Mar 2000-01-01 00:00:00"}');
select x, toTypeName(x) from format(JSONEachRow, '{"x" : "Mar 2000-01-01 00:00:00.000"}');