mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-26 01:22:04 +00:00
Merge pull request #68382 from Avogar/better-datetime-inference
Improve schema inference of date times
This commit is contained in:
commit
c4d9944a90
@ -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)
|
||||
|
@ -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) \
|
||||
|
@ -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",
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
c1 Nullable(DateTime64(9))
|
||||
c1 Nullable(DateTime)
|
||||
|
@ -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))
|
||||
|
10
tests/queries/0_stateless/02404_data.CSV
Normal file
10
tests/queries/0_stateless/02404_data.CSV
Normal 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"
|
|
11
tests/queries/0_stateless/02404_data.CSVWithNames
Normal file
11
tests/queries/0_stateless/02404_data.CSVWithNames
Normal 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"
|
10
tests/queries/0_stateless/02404_data.CustomSeparated
Normal file
10
tests/queries/0_stateless/02404_data.CustomSeparated
Normal 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
|
10
tests/queries/0_stateless/02404_data.JSONCompactEachRow
Normal file
10
tests/queries/0_stateless/02404_data.JSONCompactEachRow
Normal 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"]
|
10
tests/queries/0_stateless/02404_data.JSONEachRow
Normal file
10
tests/queries/0_stateless/02404_data.JSONEachRow
Normal 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"}
|
10
tests/queries/0_stateless/02404_data.TSKV
Normal file
10
tests/queries/0_stateless/02404_data.TSKV
Normal 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
|
10
tests/queries/0_stateless/02404_data.TSV
Normal file
10
tests/queries/0_stateless/02404_data.TSV
Normal 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
|
|
11
tests/queries/0_stateless/02404_data.TSVWithNames
Normal file
11
tests/queries/0_stateless/02404_data.TSVWithNames
Normal 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
|
1
tests/queries/0_stateless/02404_data.Values
Normal file
1
tests/queries/0_stateless/02404_data.Values
Normal 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')
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
253
tests/queries/0_stateless/03222_date_time_inference.reference
Normal file
253
tests/queries/0_stateless/03222_date_time_inference.reference
Normal 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
|
269
tests/queries/0_stateless/03222_date_time_inference.sql
Normal file
269
tests/queries/0_stateless/03222_date_time_inference.sql
Normal 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"}');
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user