mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-23 08:02:02 +00:00
Merge branch 'master' into fix-flaky-s3-queue-test
This commit is contained in:
commit
8984ba9c7e
@ -14,3 +14,8 @@ services:
|
||||
LDAP_PORT_NUMBER: ${LDAP_INTERNAL_PORT:-1389}
|
||||
ports:
|
||||
- ${LDAP_EXTERNAL_PORT:-1389}:${LDAP_INTERNAL_PORT:-1389}
|
||||
healthcheck:
|
||||
test: "ldapsearch -x -b dc=example,dc=org cn > /dev/null"
|
||||
interval: 10s
|
||||
retries: 10
|
||||
timeout: 2s
|
||||
|
@ -84,5 +84,5 @@ SELECT * FROM WatchLog;
|
||||
|
||||
**See Also**
|
||||
|
||||
- [Virtual columns](../../../engines/table-engines/special/index.md#table_engines-virtual_columns)
|
||||
- [Virtual columns](../../../engines/table-engines/index.md#table_engines-virtual_columns)
|
||||
- [merge](../../../sql-reference/table-functions/merge.md) table function
|
||||
|
@ -4155,6 +4155,18 @@ Possible values:
|
||||
|
||||
Default value: `0`.
|
||||
|
||||
## date_time_overflow_behavior {#date_time_overflow_behavior}
|
||||
|
||||
Defines the behavior when [Date](../../sql-reference/data-types/date.md), [Date32](../../sql-reference/data-types/date32.md), [DateTime](../../sql-reference/data-types/datetime.md), [DateTime64](../../sql-reference/data-types/datetime64.md) or integers are converted into Date, Date32, DateTime or DateTime64 but the value cannot be represented in the result type.
|
||||
|
||||
Possible values:
|
||||
|
||||
- `ignore` — Silently ignore overflows. The result is random.
|
||||
- `throw` — Throw an exception in case of conversion overflow.
|
||||
- `saturate` — Silently saturate the result. If the value is smaller than the smallest value that can be represented by the target type, the result is chosen as the smallest representable value. If the value is bigger than the largest value that can be represented by the target type, the result is chosen as the largest representable value.
|
||||
|
||||
Default value: `ignore`.
|
||||
|
||||
## optimize_move_to_prewhere {#optimize_move_to_prewhere}
|
||||
|
||||
Enables or disables automatic [PREWHERE](../../sql-reference/statements/select/prewhere.md) optimization in [SELECT](../../sql-reference/statements/select/index.md) queries.
|
||||
|
@ -402,7 +402,7 @@ Before version 21.11 the order of arguments was wrong, i.e. JSON_QUERY(path, jso
|
||||
|
||||
Parses a JSON and extract a value as JSON scalar.
|
||||
|
||||
If the value does not exist, an empty string will be returned by default, and by SET `function_return_type_allow_nullable` = `true`, `NULL` will be returned. If the value is complex type (such as: struct, array, map), an empty string will be returned by default, and by SET `function_json_value_return_type_allow_complex` = `true`, the complex value will be returned.
|
||||
If the value does not exist, an empty string will be returned by default, and by SET `function_json_value_return_type_allow_nullable` = `true`, `NULL` will be returned. If the value is complex type (such as: struct, array, map), an empty string will be returned by default, and by SET `function_json_value_return_type_allow_complex` = `true`, the complex value will be returned.
|
||||
|
||||
Example:
|
||||
|
||||
@ -411,7 +411,7 @@ SELECT JSON_VALUE('{"hello":"world"}', '$.hello');
|
||||
SELECT JSON_VALUE('{"array":[[0, 1, 2, 3, 4, 5], [0, -1, -2, -3, -4, -5]]}', '$.array[*][0 to 2, 4]');
|
||||
SELECT JSON_VALUE('{"hello":2}', '$.hello');
|
||||
SELECT toTypeName(JSON_VALUE('{"hello":2}', '$.hello'));
|
||||
select JSON_VALUE('{"hello":"world"}', '$.b') settings function_return_type_allow_nullable=true;
|
||||
select JSON_VALUE('{"hello":"world"}', '$.b') settings function_json_value_return_type_allow_nullable=true;
|
||||
select JSON_VALUE('{"hello":{"world":"!"}}', '$.hello') settings function_json_value_return_type_allow_complex=true;
|
||||
```
|
||||
|
||||
|
@ -2794,3 +2794,71 @@ message Root
|
||||
uint32 column2 = 2;
|
||||
}
|
||||
```
|
||||
|
||||
## formatQuery
|
||||
|
||||
Returns a formatted, possibly multi-line, version of the given SQL query.
|
||||
|
||||
**Syntax**
|
||||
|
||||
```sql
|
||||
formatQuery(query)
|
||||
```
|
||||
|
||||
**Arguments**
|
||||
|
||||
- `query` - The SQL query to be formatted. [String](../../sql-reference/data-types/string.md)
|
||||
|
||||
**Returned value**
|
||||
|
||||
- The formatted query. [String](../../sql-reference/data-types/string.md).
|
||||
|
||||
**Example**
|
||||
|
||||
```sql
|
||||
SELECT formatQuery('select a, b FRom tab WHERE a > 3 and b < 3');
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```result
|
||||
┌─formatQuery('select a, b FRom tab WHERE a > 3 and b < 3')─┐
|
||||
│ SELECT
|
||||
a,
|
||||
b
|
||||
FROM tab
|
||||
WHERE (a > 3) AND (b < 3) │
|
||||
└───────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## formatQuerySingleLine
|
||||
|
||||
Like formatQuery() but the returned formatted string contains no line breaks.
|
||||
|
||||
**Syntax**
|
||||
|
||||
```sql
|
||||
formatQuerySingleLine(query)
|
||||
```
|
||||
|
||||
**Arguments**
|
||||
|
||||
- `query` - The SQL query to be formatted. [String](../../sql-reference/data-types/string.md)
|
||||
|
||||
**Returned value**
|
||||
|
||||
- The formatted query. [String](../../sql-reference/data-types/string.md).
|
||||
|
||||
**Example**
|
||||
|
||||
```sql
|
||||
SELECT formatQuerySingleLine('select a, b FRom tab WHERE a > 3 and b < 3');
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```result
|
||||
┌─formatQuerySingleLine('select a, b FRom tab WHERE a > 3 and b < 3')─┐
|
||||
│ SELECT a, b FROM tab WHERE (a > 3) AND (b < 3) │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
@ -1982,12 +1982,12 @@ Result:
|
||||
|
||||
## snowflakeToDateTime
|
||||
|
||||
Extracts time from [Snowflake ID](https://en.wikipedia.org/wiki/Snowflake_ID) as [DateTime](/docs/en/sql-reference/data-types/datetime.md) format.
|
||||
Extracts the timestamp component of a [Snowflake ID](https://en.wikipedia.org/wiki/Snowflake_ID) in [DateTime](/docs/en/sql-reference/data-types/datetime.md) format.
|
||||
|
||||
**Syntax**
|
||||
|
||||
``` sql
|
||||
snowflakeToDateTime(value [, time_zone])
|
||||
snowflakeToDateTime(value[, time_zone])
|
||||
```
|
||||
|
||||
**Parameters**
|
||||
@ -1997,7 +1997,7 @@ snowflakeToDateTime(value [, time_zone])
|
||||
|
||||
**Returned value**
|
||||
|
||||
- Input value converted to the [DateTime](/docs/en/sql-reference/data-types/datetime.md) data type.
|
||||
- The timestamp component of `value` as a [DateTime](/docs/en/sql-reference/data-types/datetime.md) value.
|
||||
|
||||
**Example**
|
||||
|
||||
@ -2018,12 +2018,12 @@ Result:
|
||||
|
||||
## snowflakeToDateTime64
|
||||
|
||||
Extracts time from [Snowflake ID](https://en.wikipedia.org/wiki/Snowflake_ID) as [DateTime64](/docs/en/sql-reference/data-types/datetime64.md) format.
|
||||
Extracts the timestamp component of a [Snowflake ID](https://en.wikipedia.org/wiki/Snowflake_ID) in [DateTime64](/docs/en/sql-reference/data-types/datetime64.md) format.
|
||||
|
||||
**Syntax**
|
||||
|
||||
``` sql
|
||||
snowflakeToDateTime64(value [, time_zone])
|
||||
snowflakeToDateTime64(value[, time_zone])
|
||||
```
|
||||
|
||||
**Parameters**
|
||||
@ -2033,7 +2033,7 @@ snowflakeToDateTime64(value [, time_zone])
|
||||
|
||||
**Returned value**
|
||||
|
||||
- Input value converted to the [DateTime64](/docs/en/sql-reference/data-types/datetime64.md) data type.
|
||||
- The timestamp component of `value` as a [DateTime64](/docs/en/sql-reference/data-types/datetime64.md) with scale = 3, i.e. millisecond precision.
|
||||
|
||||
**Example**
|
||||
|
||||
@ -2054,7 +2054,7 @@ Result:
|
||||
|
||||
## dateTimeToSnowflake
|
||||
|
||||
Converts [DateTime](/docs/en/sql-reference/data-types/datetime.md) value to the first [Snowflake ID](https://en.wikipedia.org/wiki/Snowflake_ID) at the giving time.
|
||||
Converts a [DateTime](/docs/en/sql-reference/data-types/datetime.md) value to the first [Snowflake ID](https://en.wikipedia.org/wiki/Snowflake_ID) at the giving time.
|
||||
|
||||
**Syntax**
|
||||
|
||||
@ -2064,7 +2064,7 @@ dateTimeToSnowflake(value)
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `value` — Date and time. [DateTime](/docs/en/sql-reference/data-types/datetime.md).
|
||||
- `value` — Date with time. [DateTime](/docs/en/sql-reference/data-types/datetime.md).
|
||||
|
||||
**Returned value**
|
||||
|
||||
@ -2088,7 +2088,7 @@ Result:
|
||||
|
||||
## dateTime64ToSnowflake
|
||||
|
||||
Convert [DateTime64](/docs/en/sql-reference/data-types/datetime64.md) to the first [Snowflake ID](https://en.wikipedia.org/wiki/Snowflake_ID) at the giving time.
|
||||
Convert a [DateTime64](/docs/en/sql-reference/data-types/datetime64.md) to the first [Snowflake ID](https://en.wikipedia.org/wiki/Snowflake_ID) at the giving time.
|
||||
|
||||
**Syntax**
|
||||
|
||||
@ -2098,7 +2098,7 @@ dateTime64ToSnowflake(value)
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `value` — Date and time. [DateTime64](/docs/en/sql-reference/data-types/datetime64.md).
|
||||
- `value` — Date with time. [DateTime64](/docs/en/sql-reference/data-types/datetime64.md).
|
||||
|
||||
**Returned value**
|
||||
|
||||
|
@ -3838,6 +3838,18 @@ SELECT * FROM positional_arguments ORDER BY 2,3;
|
||||
|
||||
Значение по умолчанию: `0`.
|
||||
|
||||
## date_time_overflow_behavior {#date_time_overflow_behavior}
|
||||
|
||||
Задаёт поведение при преобразовании [Date](../../sql-reference/data-types/date.md), [Date32](../../sql-reference/data-types/date32.md), [DateTime](../../sql-reference/data-types/datetime.md), [DateTime64](../../sql-reference/data-types/datetime64.md), а также численных типов данных к Date, Date32, DateTime, DateTime64 в случае, если результат выходит за пределы диапазона значений необходимого типа.
|
||||
|
||||
Возможные значения:
|
||||
|
||||
- `ignore` — Молча игнорирует переполнение. В таком случае, результатом будет случайное значение.
|
||||
- `throw` — Выкинуть исключение при переполнении.
|
||||
- `saturate` — Молча округлить до ближайшего (то есть наибольшего или наименьшего) значения из диапазона значений результата.
|
||||
|
||||
Значение по умолчанию: `ignore`.
|
||||
|
||||
## optimize_move_to_prewhere {#optimize_move_to_prewhere}
|
||||
|
||||
Включает или отключает автоматическую оптимизацию [PREWHERE](../../sql-reference/statements/select/prewhere.md) в запросах [SELECT](../../sql-reference/statements/select/index.md).
|
||||
|
@ -681,6 +681,7 @@ class IColumn;
|
||||
M(Bool, query_plan_aggregation_in_order, true, "Use query plan for aggregation-in-order optimisation", 0) \
|
||||
M(Bool, query_plan_remove_redundant_sorting, true, "Remove redundant sorting in query plan. For example, sorting steps related to ORDER BY clauses in subqueries", 0) \
|
||||
M(Bool, query_plan_remove_redundant_distinct, true, "Remove redundant Distinct step in query plan", 0) \
|
||||
M(Bool, query_plan_enable_multithreading_after_window_functions, true, "Enable multithreading after evaluating window functions to allow parallel stream processing", 0) \
|
||||
M(UInt64, regexp_max_matches_per_row, 1000, "Max matches of any single regexp per row, used to safeguard 'extractAllGroupsHorizontal' against consuming too much memory with greedy RE.", 0) \
|
||||
\
|
||||
M(UInt64, limit, 0, "Limit on read rows from the most 'end' result for select query, default 0 means no limit length", 0) \
|
||||
@ -813,7 +814,7 @@ class IColumn;
|
||||
M(Bool, create_table_empty_primary_key_by_default, false, "Allow to create *MergeTree tables with empty primary key when ORDER BY and PRIMARY KEY not specified", 0) \
|
||||
|
||||
// End of COMMON_SETTINGS
|
||||
// Please add settings related to formats into the FORMAT_FACTORY_SETTINGS, move obsolete settings to OBSOLETE_SETTINGS and obsolete format settings to OBSOLETE_FORMAT_SETTINGS.
|
||||
// Please add settings related to formats into the FORMAT_FACTORY_SETTINGS, move obsolete settings to OBSOLETE_SETTINGS and obsolete format settings to OBSOLETE_FORMAT_SETTINGS.
|
||||
|
||||
#define MAKE_OBSOLETE(M, TYPE, NAME, DEFAULT) \
|
||||
M(TYPE, NAME, DEFAULT, "Obsolete setting, does nothing.", BaseSettingsHelpers::Flags::OBSOLETE)
|
||||
@ -1077,6 +1078,8 @@ class IColumn;
|
||||
\
|
||||
M(Bool, dictionary_use_async_executor, false, "Execute a pipeline for reading dictionary source in several threads. It's supported only by dictionaries with local CLICKHOUSE source.", 0) \
|
||||
M(Bool, precise_float_parsing, false, "Prefer more precise (but slower) float parsing algorithm", 0) \
|
||||
M(DateTimeOverflowBehavior, date_time_overflow_behavior, "ignore", "Overflow mode for Date, Date32, DateTime, DateTime64 types. Possible values: 'ignore', 'throw', 'saturate'.", 0) \
|
||||
|
||||
|
||||
// End of FORMAT_FACTORY_SETTINGS
|
||||
// Please add settings non-related to formats into the COMMON_SETTINGS above.
|
||||
|
@ -190,4 +190,9 @@ IMPLEMENT_SETTING_ENUM(ExternalCommandStderrReaction, ErrorCodes::BAD_ARGUMENTS,
|
||||
{"log_last", ExternalCommandStderrReaction::LOG_LAST},
|
||||
{"throw", ExternalCommandStderrReaction::THROW}})
|
||||
|
||||
IMPLEMENT_SETTING_ENUM(DateTimeOverflowBehavior, ErrorCodes::BAD_ARGUMENTS,
|
||||
{{"throw", FormatSettings::DateTimeOverflowBehavior::Throw},
|
||||
{"ignore", FormatSettings::DateTimeOverflowBehavior::Ignore},
|
||||
{"saturate", FormatSettings::DateTimeOverflowBehavior::Saturate}})
|
||||
|
||||
}
|
||||
|
@ -242,4 +242,6 @@ DECLARE_SETTING_ENUM(S3QueueAction)
|
||||
|
||||
DECLARE_SETTING_ENUM(ExternalCommandStderrReaction)
|
||||
|
||||
DECLARE_SETTING_ENUM_WITH_RENAME(DateTimeOverflowBehavior, FormatSettings::DateTimeOverflowBehavior)
|
||||
|
||||
}
|
||||
|
@ -452,10 +452,25 @@ inline bool isObject(const T & data_type) { return WhichDataType(data_type).isOb
|
||||
template <typename T>
|
||||
inline bool isUInt8(const T & data_type) { return WhichDataType(data_type).isUInt8(); }
|
||||
template <typename T>
|
||||
inline bool isUInt16(const T & data_type) { return WhichDataType(data_type).isUInt16(); }
|
||||
template <typename T>
|
||||
inline bool isUInt32(const T & data_type) { return WhichDataType(data_type).isUInt32(); }
|
||||
template <typename T>
|
||||
inline bool isUInt64(const T & data_type) { return WhichDataType(data_type).isUInt64(); }
|
||||
template <typename T>
|
||||
inline bool isUnsignedInteger(const T & data_type) { return WhichDataType(data_type).isUInt(); }
|
||||
|
||||
template <typename T>
|
||||
inline bool isInt8(const T & data_type) { return WhichDataType(data_type).isInt8(); }
|
||||
template <typename T>
|
||||
inline bool isInt16(const T & data_type) { return WhichDataType(data_type).isInt16(); }
|
||||
template <typename T>
|
||||
inline bool isInt32(const T & data_type) { return WhichDataType(data_type).isInt32(); }
|
||||
template <typename T>
|
||||
inline bool isInt64(const T & data_type) { return WhichDataType(data_type).isInt64(); }
|
||||
template <typename T>
|
||||
inline bool isInt(const T & data_type) { return WhichDataType(data_type).isInt(); }
|
||||
|
||||
template <typename T>
|
||||
inline bool isInteger(const T & data_type)
|
||||
{
|
||||
|
@ -621,7 +621,8 @@ void DatabaseReplicated::checkQueryValid(const ASTPtr & query, ContextPtr query_
|
||||
|
||||
if (auto * create = query->as<ASTCreateQuery>())
|
||||
{
|
||||
bool replicated_table = create->storage && create->storage->engine && startsWith(create->storage->engine->name, "Replicated");
|
||||
bool replicated_table = create->storage && create->storage->engine &&
|
||||
(startsWith(create->storage->engine->name, "Replicated") || startsWith(create->storage->engine->name, "Shared"));
|
||||
if (!replicated_table || !create->storage->engine->arguments)
|
||||
return;
|
||||
|
||||
@ -761,8 +762,9 @@ BlockIO DatabaseReplicated::tryEnqueueReplicatedDDL(const ASTPtr & query, Contex
|
||||
static UUID getTableUUIDIfReplicated(const String & metadata, ContextPtr context)
|
||||
{
|
||||
bool looks_like_replicated = metadata.find("Replicated") != std::string::npos;
|
||||
bool looks_like_shared = metadata.find("Shared") != std::string::npos;
|
||||
bool looks_like_merge_tree = metadata.find("MergeTree") != std::string::npos;
|
||||
if (!looks_like_replicated || !looks_like_merge_tree)
|
||||
if (!(looks_like_replicated || looks_like_shared) || !looks_like_merge_tree)
|
||||
return UUIDHelpers::Nil;
|
||||
|
||||
ParserCreateQuery parser;
|
||||
@ -772,7 +774,8 @@ static UUID getTableUUIDIfReplicated(const String & metadata, ContextPtr context
|
||||
const ASTCreateQuery & create = query->as<const ASTCreateQuery &>();
|
||||
if (!create.storage || !create.storage->engine)
|
||||
return UUIDHelpers::Nil;
|
||||
if (!startsWith(create.storage->engine->name, "Replicated") || !endsWith(create.storage->engine->name, "MergeTree"))
|
||||
if (!(startsWith(create.storage->engine->name, "Replicated") || startsWith(create.storage->engine->name, "Shared"))
|
||||
|| !endsWith(create.storage->engine->name, "MergeTree"))
|
||||
return UUIDHelpers::Nil;
|
||||
chassert(create.uuid != UUIDHelpers::Nil);
|
||||
return create.uuid;
|
||||
|
@ -227,6 +227,7 @@ FormatSettings getFormatSettings(ContextPtr context, const Settings & settings)
|
||||
format_settings.native.allow_types_conversion = settings.input_format_native_allow_types_conversion;
|
||||
format_settings.max_parser_depth = context->getSettingsRef().max_parser_depth;
|
||||
format_settings.client_protocol_version = context->getClientProtocolVersion();
|
||||
format_settings.date_time_overflow_behavior = settings.date_time_overflow_behavior;
|
||||
|
||||
/// Validate avro_schema_registry_url with RemoteHostFilter when non-empty and in Server context
|
||||
if (format_settings.schema.is_server)
|
||||
|
@ -88,6 +88,15 @@ struct FormatSettings
|
||||
IntervalOutputFormat output_format = IntervalOutputFormat::Numeric;
|
||||
} interval;
|
||||
|
||||
enum class DateTimeOverflowBehavior
|
||||
{
|
||||
Ignore,
|
||||
Throw,
|
||||
Saturate
|
||||
};
|
||||
|
||||
DateTimeOverflowBehavior date_time_overflow_behavior = DateTimeOverflowBehavior::Ignore;
|
||||
|
||||
bool input_format_ipv4_default_on_conversion_error = false;
|
||||
bool input_format_ipv6_default_on_conversion_error = false;
|
||||
|
||||
|
@ -22,5 +22,4 @@ void throwDate32IsNotSupported(const char * name)
|
||||
{
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type Date32 of argument for function {}", name);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,12 +23,15 @@ namespace DB
|
||||
static constexpr auto microsecond_multiplier = 1000000;
|
||||
static constexpr auto millisecond_multiplier = 1000;
|
||||
|
||||
static constexpr FormatSettings::DateTimeOverflowBehavior default_date_time_overflow_behavior = FormatSettings::DateTimeOverflowBehavior::Ignore;
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int CANNOT_CONVERT_TYPE;
|
||||
extern const int DECIMAL_OVERFLOW;
|
||||
extern const int ILLEGAL_COLUMN;
|
||||
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
|
||||
extern const int VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE;
|
||||
}
|
||||
|
||||
/** Transformations.
|
||||
@ -44,6 +47,12 @@ namespace ErrorCodes
|
||||
* factor-transformation F is "round to the nearest month" (2015-02-03 -> 2015-02-01).
|
||||
*/
|
||||
|
||||
constexpr time_t MAX_DATETIME64_TIMESTAMP = 10413791999LL; // 1900-01-01 00:00:00 UTC
|
||||
constexpr time_t MIN_DATETIME64_TIMESTAMP = -2208988800LL; // 2299-12-31 23:59:59 UTC
|
||||
constexpr time_t MAX_DATETIME_TIMESTAMP = 0xFFFFFFFF;
|
||||
constexpr time_t MAX_DATE_TIMESTAMP = 5662310399; // 2149-06-06 23:59:59 UTC
|
||||
constexpr time_t MAX_DATETIME_DAY_NUM = 49710; // 2106-02-07
|
||||
|
||||
[[noreturn]] void throwDateIsNotSupported(const char * name);
|
||||
[[noreturn]] void throwDateTimeIsNotSupported(const char * name);
|
||||
[[noreturn]] void throwDate32IsNotSupported(const char * name);
|
||||
@ -57,25 +66,51 @@ struct ZeroTransform
|
||||
static UInt16 execute(UInt16, const DateLUTImpl &) { return 0; }
|
||||
};
|
||||
|
||||
template <FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior = default_date_time_overflow_behavior>
|
||||
struct ToDateImpl
|
||||
{
|
||||
static constexpr auto name = "toDate";
|
||||
|
||||
static UInt16 execute(const DecimalUtils::DecimalComponents<DateTime64> & t, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return static_cast<UInt16>(time_zone.toDayNum(t.whole));
|
||||
return execute(t.whole, time_zone);
|
||||
}
|
||||
|
||||
static UInt16 execute(Int64 t, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return UInt16(time_zone.toDayNum(t));
|
||||
if constexpr (date_time_overflow_behavior == FormatSettings::DateTimeOverflowBehavior::Saturate)
|
||||
{
|
||||
if (t < 0)
|
||||
t = 0;
|
||||
else if (t > MAX_DATE_TIMESTAMP)
|
||||
t = MAX_DATE_TIMESTAMP;
|
||||
}
|
||||
else if constexpr (date_time_overflow_behavior == FormatSettings::DateTimeOverflowBehavior::Throw)
|
||||
{
|
||||
if (t < 0 || t > MAX_DATE_TIMESTAMP) [[unlikely]]
|
||||
throw Exception(ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE, "Value {} is out of bounds of type Date", t);
|
||||
}
|
||||
return static_cast<UInt16>(time_zone.toDayNum(t));
|
||||
}
|
||||
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return UInt16(time_zone.toDayNum(t));
|
||||
return UInt16(time_zone.toDayNum(t)); /// never causes overflow by design
|
||||
}
|
||||
static UInt16 execute(Int32, const DateLUTImpl &)
|
||||
static UInt16 execute(Int32 t, const DateLUTImpl &)
|
||||
{
|
||||
throwDateIsNotSupported(name);
|
||||
if constexpr (date_time_overflow_behavior == FormatSettings::DateTimeOverflowBehavior::Saturate)
|
||||
{
|
||||
if (t < 0)
|
||||
return UInt16(0);
|
||||
else if (t > DATE_LUT_MAX_DAY_NUM)
|
||||
return UInt16(DATE_LUT_MAX_DAY_NUM);
|
||||
}
|
||||
else if constexpr (date_time_overflow_behavior == FormatSettings::DateTimeOverflowBehavior::Throw)
|
||||
{
|
||||
if (t < 0 || t > DATE_LUT_MAX_DAY_NUM) [[unlikely]]
|
||||
throw Exception(ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE, "Value {} is out of bounds of type Date", t);
|
||||
}
|
||||
return static_cast<UInt16>(t);
|
||||
}
|
||||
static UInt16 execute(UInt16 d, const DateLUTImpl &)
|
||||
{
|
||||
@ -750,7 +785,7 @@ struct ToTimeImpl
|
||||
}
|
||||
static constexpr bool hasPreimage() { return false; }
|
||||
|
||||
using FactorTransform = ToDateImpl;
|
||||
using FactorTransform = ToDateImpl<>;
|
||||
};
|
||||
|
||||
struct ToStartOfMinuteImpl
|
||||
@ -1401,7 +1436,7 @@ struct ToHourImpl
|
||||
}
|
||||
static constexpr bool hasPreimage() { return false; }
|
||||
|
||||
using FactorTransform = ToDateImpl;
|
||||
using FactorTransform = ToDateImpl<>;
|
||||
};
|
||||
|
||||
struct TimezoneOffsetImpl
|
||||
|
@ -4,10 +4,12 @@
|
||||
#include <Functions/IFunction.h>
|
||||
#include <Functions/FunctionHelpers.h>
|
||||
#include <DataTypes/DataTypeDateTime64.h>
|
||||
#include <DataTypes/DataTypesDecimal.h>
|
||||
#include <DataTypes/DataTypesNumber.h>
|
||||
#include <Columns/ColumnConst.h>
|
||||
#include <Columns/ColumnsDateTime.h>
|
||||
#include <Columns/ColumnsNumber.h>
|
||||
#include <Core/DecimalFunctions.h>
|
||||
#include <Interpreters/Context.h>
|
||||
|
||||
#include <base/arithmeticOverflow.h>
|
||||
@ -17,7 +19,6 @@ namespace DB
|
||||
{
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
|
||||
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
|
||||
}
|
||||
|
||||
@ -40,14 +41,15 @@ public:
|
||||
|
||||
String getName() const override { return name; }
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
bool isVariadic() const override { return false; }
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; }
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
||||
{
|
||||
if (!isDateTime(arguments[0].type))
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "The only argument for function {} must be DateTime", name);
|
||||
FunctionArgumentDescriptors args{
|
||||
{"value", &isDateTime<IDataType>, nullptr, "DateTime"}
|
||||
};
|
||||
validateFunctionArgumentTypes(*this, arguments, args);
|
||||
|
||||
return std::make_shared<DataTypeInt64>();
|
||||
}
|
||||
@ -88,13 +90,15 @@ public:
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
||||
{
|
||||
if (arguments.empty() || arguments.size() > 2)
|
||||
throw Exception(ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH, "Function {} takes one or two arguments", name);
|
||||
FunctionArgumentDescriptors mandatory_args{
|
||||
{"value", &isInt64<IDataType>, nullptr, "Int64"}
|
||||
};
|
||||
FunctionArgumentDescriptors optional_args{
|
||||
{"time_zone", &isString<IDataType>, nullptr, "String"}
|
||||
};
|
||||
validateFunctionArgumentTypes(*this, arguments, mandatory_args, optional_args);
|
||||
|
||||
if (!typeid_cast<const DataTypeInt64 *>(arguments[0].type.get()))
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "The first argument for function {} must be Int64", name);
|
||||
|
||||
std::string timezone;
|
||||
String timezone;
|
||||
if (arguments.size() == 2)
|
||||
timezone = extractTimeZoneNameFromFunctionArguments(arguments, 1, 0, allow_nonconst_timezone_arguments);
|
||||
|
||||
@ -141,14 +145,15 @@ public:
|
||||
|
||||
String getName() const override { return name; }
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
bool isVariadic() const override { return false; }
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; }
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
||||
{
|
||||
if (!isDateTime64(arguments[0].type))
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "The only argument for function {} must be DateTime64", name);
|
||||
FunctionArgumentDescriptors args{
|
||||
{"value", &isDateTime64<IDataType>, nullptr, "DateTime64"}
|
||||
};
|
||||
validateFunctionArgumentTypes(*this, arguments, args);
|
||||
|
||||
return std::make_shared<DataTypeInt64>();
|
||||
}
|
||||
@ -156,14 +161,21 @@ public:
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
|
||||
{
|
||||
const auto & src = arguments[0];
|
||||
const auto & src_column = *src.column;
|
||||
|
||||
const auto & src_column = *src.column;
|
||||
auto res_column = ColumnInt64::create(input_rows_count);
|
||||
auto & res_data = res_column->getData();
|
||||
|
||||
const auto & src_data = typeid_cast<const ColumnDecimal<DateTime64> &>(src_column).getData();
|
||||
|
||||
/// timestamps in snowflake-ids are millisecond-based, convert input to milliseconds
|
||||
UInt32 src_scale = getDecimalScale(*arguments[0].type);
|
||||
Int64 multiplier_msec = DecimalUtils::scaleMultiplier<DateTime64>(3);
|
||||
Int64 multiplier_src = DecimalUtils::scaleMultiplier<DateTime64>(src_scale);
|
||||
auto factor = multiplier_msec / static_cast<double>(multiplier_src);
|
||||
|
||||
for (size_t i = 0; i < input_rows_count; ++i)
|
||||
res_data[i] = (src_data[i] - snowflake_epoch) << time_shift;
|
||||
res_data[i] = static_cast<Int64>(src_data[i] * factor - snowflake_epoch) << time_shift;
|
||||
|
||||
return res_column;
|
||||
}
|
||||
@ -190,13 +202,15 @@ public:
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
||||
{
|
||||
if (arguments.empty() || arguments.size() > 2)
|
||||
throw Exception(ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH, "Function {} takes one or two arguments", name);
|
||||
FunctionArgumentDescriptors mandatory_args{
|
||||
{"value", &isInt64<IDataType>, nullptr, "Int64"}
|
||||
};
|
||||
FunctionArgumentDescriptors optional_args{
|
||||
{"time_zone", &isString<IDataType>, nullptr, "String"}
|
||||
};
|
||||
validateFunctionArgumentTypes(*this, arguments, mandatory_args, optional_args);
|
||||
|
||||
if (!typeid_cast<const DataTypeInt64 *>(arguments[0].type.get()))
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "The first argument for function {} must be Int64", name);
|
||||
|
||||
std::string timezone;
|
||||
String timezone;
|
||||
if (arguments.size() == 2)
|
||||
timezone = extractTimeZoneNameFromFunctionArguments(arguments, 1, 0, allow_nonconst_timezone_arguments);
|
||||
|
||||
|
@ -90,9 +90,9 @@ namespace ErrorCodes
|
||||
extern const int NOT_IMPLEMENTED;
|
||||
extern const int CANNOT_INSERT_NULL_IN_ORDINARY_COLUMN;
|
||||
extern const int CANNOT_PARSE_BOOL;
|
||||
extern const int VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE;
|
||||
}
|
||||
|
||||
|
||||
/** Type conversion functions.
|
||||
* toType - conversion in "natural way";
|
||||
*/
|
||||
@ -133,7 +133,9 @@ struct ConvertReturnZeroOnErrorTag {};
|
||||
/** Conversion of number types to each other, enums to numbers, dates and datetimes to numbers and back: done by straight assignment.
|
||||
* (Date is represented internally as number of days from some day; DateTime - as unix timestamp)
|
||||
*/
|
||||
template <typename FromDataType, typename ToDataType, typename Name, typename SpecialTag = ConvertDefaultBehaviorTag>
|
||||
template <typename FromDataType, typename ToDataType, typename Name,
|
||||
typename SpecialTag = ConvertDefaultBehaviorTag,
|
||||
FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior = default_date_time_overflow_behavior>
|
||||
struct ConvertImpl
|
||||
{
|
||||
using FromFieldType = typename FromDataType::FieldType;
|
||||
@ -388,28 +390,53 @@ struct ConvertImpl
|
||||
|
||||
/** Conversion of DateTime to Date: throw off time component.
|
||||
*/
|
||||
template <typename Name> struct ConvertImpl<DataTypeDateTime, DataTypeDate, Name, ConvertDefaultBehaviorTag>
|
||||
: DateTimeTransformImpl<DataTypeDateTime, DataTypeDate, ToDateImpl> {};
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeDateTime, DataTypeDate, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeDateTime, DataTypeDate, ToDateImpl<date_time_overflow_behavior>, false> {};
|
||||
|
||||
/** Conversion of DateTime to Date32: throw off time component.
|
||||
*/
|
||||
template <typename Name> struct ConvertImpl<DataTypeDateTime, DataTypeDate32, Name, ConvertDefaultBehaviorTag>
|
||||
: DateTimeTransformImpl<DataTypeDateTime, DataTypeDate32, ToDate32Impl> {};
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeDateTime, DataTypeDate32, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeDateTime, DataTypeDate32, ToDate32Impl, false> {};
|
||||
|
||||
/** Conversion of Date to DateTime: adding 00:00:00 time component.
|
||||
*/
|
||||
template <FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior = default_date_time_overflow_behavior>
|
||||
struct ToDateTimeImpl
|
||||
{
|
||||
static constexpr auto name = "toDateTime";
|
||||
|
||||
static UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
|
||||
{
|
||||
if constexpr (date_time_overflow_behavior == FormatSettings::DateTimeOverflowBehavior::Throw)
|
||||
{
|
||||
if (d > MAX_DATETIME_DAY_NUM) [[unlikely]]
|
||||
throw Exception(ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE, "Day number {} is out of bounds of type DateTime", d);
|
||||
}
|
||||
else if constexpr (date_time_overflow_behavior == FormatSettings::DateTimeOverflowBehavior::Saturate)
|
||||
{
|
||||
if (d > MAX_DATETIME_DAY_NUM)
|
||||
d = MAX_DATETIME_DAY_NUM;
|
||||
}
|
||||
return static_cast<UInt32>(time_zone.fromDayNum(DayNum(d)));
|
||||
}
|
||||
|
||||
static Int64 execute(Int32 d, const DateLUTImpl & time_zone)
|
||||
static UInt32 execute(Int32 d, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.fromDayNum(ExtendedDayNum(d));
|
||||
if constexpr (date_time_overflow_behavior == FormatSettings::DateTimeOverflowBehavior::Saturate)
|
||||
{
|
||||
if (d < 0)
|
||||
return 0;
|
||||
else if (d > MAX_DATETIME_DAY_NUM)
|
||||
d = MAX_DATETIME_DAY_NUM;
|
||||
}
|
||||
else if constexpr (date_time_overflow_behavior == FormatSettings::DateTimeOverflowBehavior::Throw)
|
||||
{
|
||||
if (d < 0 || d > MAX_DATETIME_DAY_NUM) [[unlikely]]
|
||||
throw Exception(ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE, "Value {} is out of bounds of type DateTime", d);
|
||||
}
|
||||
return static_cast<UInt32>(time_zone.fromDayNum(ExtendedDayNum(d)));
|
||||
}
|
||||
|
||||
static UInt32 execute(UInt32 dt, const DateLUTImpl & /*time_zone*/)
|
||||
@ -417,36 +444,63 @@ struct ToDateTimeImpl
|
||||
return dt;
|
||||
}
|
||||
|
||||
// TODO: return UInt32 ???
|
||||
static Int64 execute(Int64 dt64, const DateLUTImpl & /*time_zone*/)
|
||||
static UInt32 execute(Int64 dt64, const DateLUTImpl & /*time_zone*/)
|
||||
{
|
||||
return dt64;
|
||||
if constexpr (date_time_overflow_behavior == FormatSettings::DateTimeOverflowBehavior::Ignore)
|
||||
return static_cast<UInt32>(dt64);
|
||||
else
|
||||
{
|
||||
if (dt64 < 0 || dt64 >= MAX_DATETIME_TIMESTAMP)
|
||||
{
|
||||
if constexpr (date_time_overflow_behavior == FormatSettings::DateTimeOverflowBehavior::Saturate)
|
||||
return dt64 < 0 ? 0 : std::numeric_limits<UInt32>::max();
|
||||
else
|
||||
throw Exception(ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE, "Value {} is out of bounds of type DateTime", dt64);
|
||||
}
|
||||
else
|
||||
return static_cast<UInt32>(dt64);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Name> struct ConvertImpl<DataTypeDate, DataTypeDateTime, Name, ConvertDefaultBehaviorTag>
|
||||
: DateTimeTransformImpl<DataTypeDate, DataTypeDateTime, ToDateTimeImpl> {};
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeDate, DataTypeDateTime, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeDate, DataTypeDateTime, ToDateTimeImpl<date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename Name> struct ConvertImpl<DataTypeDate32, DataTypeDateTime, Name, ConvertDefaultBehaviorTag>
|
||||
: DateTimeTransformImpl<DataTypeDate32, DataTypeDateTime, ToDateTimeImpl> {};
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeDate32, DataTypeDateTime, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeDate32, DataTypeDateTime, ToDateTimeImpl<date_time_overflow_behavior>, false> {};
|
||||
|
||||
/// Implementation of toDate function.
|
||||
|
||||
template <typename FromType, typename ToType>
|
||||
template <typename FromType, typename ToType, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ToDateTransform32Or64
|
||||
{
|
||||
static constexpr auto name = "toDate";
|
||||
|
||||
static NO_SANITIZE_UNDEFINED ToType execute(const FromType & from, const DateLUTImpl & time_zone)
|
||||
{
|
||||
// since converting to Date, no need in values outside of default LUT range.
|
||||
return (from <= DATE_LUT_MAX_DAY_NUM)
|
||||
? from
|
||||
: time_zone.toDayNum(std::min(time_t(from), time_t(0xFFFFFFFF)));
|
||||
if constexpr (date_time_overflow_behavior == FormatSettings::DateTimeOverflowBehavior::Throw)
|
||||
{
|
||||
if (from > MAX_DATETIME_TIMESTAMP) [[unlikely]]
|
||||
throw Exception(ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE, "Value {} is out of bounds of type Date", from);
|
||||
}
|
||||
/// if value is smaller (or equal) than maximum day value for Date, than treat it as day num,
|
||||
/// otherwise treat it as unix timestamp. This is a bit weird, but we leave this behavior.
|
||||
if (from <= DATE_LUT_MAX_DAY_NUM)
|
||||
return from;
|
||||
else
|
||||
return time_zone.toDayNum(std::min(time_t(from), time_t(MAX_DATETIME_TIMESTAMP)));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename FromType, typename ToType>
|
||||
/** Conversion of Date32 to Date.
|
||||
*/
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeDate32, DataTypeDate, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeDate32, DataTypeDate, ToDateImpl<date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename FromType, typename ToType, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ToDateTransform32Or64Signed
|
||||
{
|
||||
static constexpr auto name = "toDate";
|
||||
@ -454,16 +508,23 @@ struct ToDateTransform32Or64Signed
|
||||
static NO_SANITIZE_UNDEFINED ToType execute(const FromType & from, const DateLUTImpl & time_zone)
|
||||
{
|
||||
// TODO: decide narrow or extended range based on FromType
|
||||
/// The function should be monotonic (better for query optimizations), so we saturate instead of overflow.
|
||||
if (from < 0)
|
||||
return 0;
|
||||
if constexpr (date_time_overflow_behavior == FormatSettings::DateTimeOverflowBehavior::Throw)
|
||||
{
|
||||
if (from < 0 || from > MAX_DATE_TIMESTAMP) [[unlikely]]
|
||||
throw Exception(ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE, "Value {} is out of bounds of type Date", from);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (from < 0)
|
||||
return 0;
|
||||
}
|
||||
return (from <= DATE_LUT_MAX_DAY_NUM)
|
||||
? static_cast<ToType>(from)
|
||||
: time_zone.toDayNum(std::min(time_t(from), time_t(0xFFFFFFFF)));
|
||||
: time_zone.toDayNum(std::min(time_t(from), time_t(MAX_DATE_TIMESTAMP)));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename FromType, typename ToType>
|
||||
template <typename FromType, typename ToType, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ToDateTransform8Or16Signed
|
||||
{
|
||||
static constexpr auto name = "toDate";
|
||||
@ -471,30 +532,44 @@ struct ToDateTransform8Or16Signed
|
||||
static NO_SANITIZE_UNDEFINED ToType execute(const FromType & from, const DateLUTImpl &)
|
||||
{
|
||||
if (from < 0)
|
||||
return 0;
|
||||
{
|
||||
if constexpr (date_time_overflow_behavior == FormatSettings::DateTimeOverflowBehavior::Throw)
|
||||
throw Exception(ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE, "Value {} is out of bounds of type Date", from);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
return from;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Name> struct ConvertImpl<DataTypeDateTime64, DataTypeDate32, Name, ConvertDefaultBehaviorTag>
|
||||
: DateTimeTransformImpl<DataTypeDateTime64, DataTypeDate32, TransformDateTime64<ToDate32Impl>> {};
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeDateTime64, DataTypeDate32, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeDateTime64, DataTypeDate32, TransformDateTime64<ToDate32Impl>, false> {};
|
||||
|
||||
/// Implementation of toDate32 function.
|
||||
|
||||
template <typename FromType, typename ToType>
|
||||
template <typename FromType, typename ToType, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ToDate32Transform32Or64
|
||||
{
|
||||
static constexpr auto name = "toDate32";
|
||||
|
||||
static NO_SANITIZE_UNDEFINED ToType execute(const FromType & from, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return (from < DATE_LUT_MAX_EXTEND_DAY_NUM)
|
||||
? static_cast<ToType>(from)
|
||||
: time_zone.toDayNum(std::min(time_t(from), time_t(0xFFFFFFFF)));
|
||||
if (from < DATE_LUT_MAX_EXTEND_DAY_NUM)
|
||||
return static_cast<ToType>(from);
|
||||
else
|
||||
{
|
||||
if constexpr (date_time_overflow_behavior == FormatSettings::DateTimeOverflowBehavior::Throw)
|
||||
{
|
||||
if (from > MAX_DATETIME64_TIMESTAMP) [[unlikely]]
|
||||
throw Exception(ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE, "Timestamp value {} is out of bounds of type Date32", from);
|
||||
}
|
||||
return time_zone.toDayNum(std::min(time_t(from), time_t(MAX_DATETIME64_TIMESTAMP)));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename FromType, typename ToType>
|
||||
template <typename FromType, typename ToType, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ToDate32Transform32Or64Signed
|
||||
{
|
||||
static constexpr auto name = "toDate32";
|
||||
@ -502,11 +577,19 @@ struct ToDate32Transform32Or64Signed
|
||||
static NO_SANITIZE_UNDEFINED ToType execute(const FromType & from, const DateLUTImpl & time_zone)
|
||||
{
|
||||
static const Int32 daynum_min_offset = -static_cast<Int32>(time_zone.getDayNumOffsetEpoch());
|
||||
|
||||
if constexpr (date_time_overflow_behavior == FormatSettings::DateTimeOverflowBehavior::Throw)
|
||||
{
|
||||
if (from < daynum_min_offset || from > MAX_DATETIME64_TIMESTAMP) [[unlikely]]
|
||||
throw Exception(ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE, "Timestamp value {} is out of bounds of type Date32", from);
|
||||
}
|
||||
|
||||
if (from < daynum_min_offset)
|
||||
return daynum_min_offset;
|
||||
|
||||
return (from < DATE_LUT_MAX_EXTEND_DAY_NUM)
|
||||
? static_cast<ToType>(from)
|
||||
: time_zone.toDayNum(std::min(time_t(Int64(from)), time_t(0xFFFFFFFF)));
|
||||
: time_zone.toDayNum(std::min(time_t(Int64(from)), time_t(MAX_DATETIME64_TIMESTAMP)));
|
||||
}
|
||||
};
|
||||
|
||||
@ -522,7 +605,7 @@ struct ToDate32Transform8Or16Signed
|
||||
};
|
||||
|
||||
/** Special case of converting Int8, Int16, (U)Int32 or (U)Int64 (and also, for convenience,
|
||||
* Float32, Float64) to Date. If the number is negative, saturate it to unix epoch time. If the
|
||||
* Float32, Float64) to Date. If the
|
||||
* number is less than 65536, then it is treated as DayNum, and if it's greater or equals to 65536,
|
||||
* then treated as unix timestamp. If the number exceeds UInt32, saturate to MAX_UINT32 then as DayNum.
|
||||
* It's a bit illogical, as we actually have two functions in one.
|
||||
@ -530,53 +613,89 @@ struct ToDate32Transform8Or16Signed
|
||||
* when user write toDate(UInt32), expecting conversion of unix timestamp to Date.
|
||||
* (otherwise such usage would be frequent mistake).
|
||||
*/
|
||||
template <typename Name> struct ConvertImpl<DataTypeUInt32, DataTypeDate, Name, ConvertDefaultBehaviorTag>
|
||||
: DateTimeTransformImpl<DataTypeUInt32, DataTypeDate, ToDateTransform32Or64<UInt32, UInt16>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeUInt64, DataTypeDate, Name, ConvertDefaultBehaviorTag>
|
||||
: DateTimeTransformImpl<DataTypeUInt64, DataTypeDate, ToDateTransform32Or64<UInt64, UInt16>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeInt8, DataTypeDate, Name, ConvertDefaultBehaviorTag>
|
||||
: DateTimeTransformImpl<DataTypeInt8, DataTypeDate, ToDateTransform8Or16Signed<Int8, UInt16>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeInt16, DataTypeDate, Name, ConvertDefaultBehaviorTag>
|
||||
: DateTimeTransformImpl<DataTypeInt16, DataTypeDate, ToDateTransform8Or16Signed<Int16, UInt16>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeInt32, DataTypeDate, Name, ConvertDefaultBehaviorTag>
|
||||
: DateTimeTransformImpl<DataTypeInt32, DataTypeDate, ToDateTransform32Or64Signed<Int32, UInt16>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeInt64, DataTypeDate, Name, ConvertDefaultBehaviorTag>
|
||||
: DateTimeTransformImpl<DataTypeInt64, DataTypeDate, ToDateTransform32Or64Signed<Int64, UInt16>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeFloat32, DataTypeDate, Name, ConvertDefaultBehaviorTag>
|
||||
: DateTimeTransformImpl<DataTypeFloat32, DataTypeDate, ToDateTransform32Or64Signed<Float32, UInt16>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeFloat64, DataTypeDate, Name, ConvertDefaultBehaviorTag>
|
||||
: DateTimeTransformImpl<DataTypeFloat64, DataTypeDate, ToDateTransform32Or64Signed<Float64, UInt16>> {};
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeUInt32, DataTypeDate, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeUInt32, DataTypeDate, ToDateTransform32Or64<UInt32, UInt16, default_date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename Name> struct ConvertImpl<DataTypeUInt32, DataTypeDate32, Name, ConvertDefaultBehaviorTag>
|
||||
: DateTimeTransformImpl<DataTypeUInt32, DataTypeDate32, ToDate32Transform32Or64<UInt32, Int32>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeUInt64, DataTypeDate32, Name, ConvertDefaultBehaviorTag>
|
||||
: DateTimeTransformImpl<DataTypeUInt64, DataTypeDate32, ToDate32Transform32Or64<UInt64, Int32>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeInt8, DataTypeDate32, Name, ConvertDefaultBehaviorTag>
|
||||
: DateTimeTransformImpl<DataTypeInt8, DataTypeDate32, ToDate32Transform8Or16Signed<Int8, Int32>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeInt16, DataTypeDate32, Name, ConvertDefaultBehaviorTag>
|
||||
: DateTimeTransformImpl<DataTypeInt16, DataTypeDate32, ToDate32Transform8Or16Signed<Int16, Int32>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeInt32, DataTypeDate32, Name, ConvertDefaultBehaviorTag>
|
||||
: DateTimeTransformImpl<DataTypeInt32, DataTypeDate32, ToDate32Transform32Or64Signed<Int32, Int32>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeInt64, DataTypeDate32, Name, ConvertDefaultBehaviorTag>
|
||||
: DateTimeTransformImpl<DataTypeInt64, DataTypeDate32, ToDate32Transform32Or64Signed<Int64, Int32>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeFloat32, DataTypeDate32, Name, ConvertDefaultBehaviorTag>
|
||||
: DateTimeTransformImpl<DataTypeFloat32, DataTypeDate32, ToDate32Transform32Or64Signed<Float32, Int32>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeFloat64, DataTypeDate32, Name, ConvertDefaultBehaviorTag>
|
||||
: DateTimeTransformImpl<DataTypeFloat64, DataTypeDate32, ToDate32Transform32Or64Signed<Float64, Int32>> {};
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeUInt64, DataTypeDate, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeUInt64, DataTypeDate, ToDateTransform32Or64<UInt64, UInt16, default_date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeInt8, DataTypeDate, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeInt8, DataTypeDate, ToDateTransform8Or16Signed<Int8, UInt16, default_date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeInt16, DataTypeDate, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeInt16, DataTypeDate, ToDateTransform8Or16Signed<Int16, UInt16, default_date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeInt32, DataTypeDate, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeInt32, DataTypeDate, ToDateTransform32Or64Signed<Int32, UInt16, default_date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeInt64, DataTypeDate, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeInt64, DataTypeDate, ToDateTransform32Or64Signed<Int64, UInt16, default_date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeFloat32, DataTypeDate, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeFloat32, DataTypeDate, ToDateTransform32Or64Signed<Float32, UInt16, default_date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeFloat64, DataTypeDate, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeFloat64, DataTypeDate, ToDateTransform32Or64Signed<Float64, UInt16, default_date_time_overflow_behavior>, false> {};
|
||||
|
||||
|
||||
template <typename FromType, typename ToType>
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeUInt32, DataTypeDate32, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeUInt32, DataTypeDate32, ToDate32Transform32Or64<UInt32, Int32, default_date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeUInt64, DataTypeDate32, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeUInt64, DataTypeDate32, ToDate32Transform32Or64<UInt64, Int32, default_date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeInt8, DataTypeDate32, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeInt8, DataTypeDate32, ToDate32Transform8Or16Signed<Int8, Int32>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeInt16, DataTypeDate32, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeInt16, DataTypeDate32, ToDate32Transform8Or16Signed<Int16, Int32>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeInt32, DataTypeDate32, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeInt32, DataTypeDate32, ToDate32Transform32Or64Signed<Int32, Int32, default_date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeInt64, DataTypeDate32, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeInt64, DataTypeDate32, ToDate32Transform32Or64Signed<Int64, Int32, default_date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeFloat32, DataTypeDate32, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeFloat32, DataTypeDate32, ToDate32Transform32Or64Signed<Float32, Int32, default_date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeFloat64, DataTypeDate32, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeFloat64, DataTypeDate32, ToDate32Transform32Or64Signed<Float64, Int32, default_date_time_overflow_behavior>, false> {};
|
||||
|
||||
|
||||
template <typename FromType, typename ToType, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ToDateTimeTransform64
|
||||
{
|
||||
static constexpr auto name = "toDateTime";
|
||||
|
||||
static NO_SANITIZE_UNDEFINED ToType execute(const FromType & from, const DateLUTImpl &)
|
||||
{
|
||||
return static_cast<ToType>(std::min(time_t(from), time_t(0xFFFFFFFF)));
|
||||
if constexpr (date_time_overflow_behavior == FormatSettings::DateTimeOverflowBehavior::Throw)
|
||||
{
|
||||
if (from > MAX_DATETIME_TIMESTAMP) [[unlikely]]
|
||||
throw Exception(ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE, "Timestamp value {} is out of bounds of type DateTime", from);
|
||||
}
|
||||
return static_cast<ToType>(std::min(time_t(from), time_t(MAX_DATETIME_TIMESTAMP)));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename FromType, typename ToType>
|
||||
template <typename FromType, typename ToType, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ToDateTimeTransformSigned
|
||||
{
|
||||
static constexpr auto name = "toDateTime";
|
||||
@ -584,51 +703,68 @@ struct ToDateTimeTransformSigned
|
||||
static NO_SANITIZE_UNDEFINED ToType execute(const FromType & from, const DateLUTImpl &)
|
||||
{
|
||||
if (from < 0)
|
||||
return 0;
|
||||
{
|
||||
if constexpr (date_time_overflow_behavior == FormatSettings::DateTimeOverflowBehavior::Throw)
|
||||
throw Exception(ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE, "Timestamp value {} is out of bounds of type DateTime", from);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
return from;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename FromType, typename ToType>
|
||||
template <typename FromType, typename ToType, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ToDateTimeTransform64Signed
|
||||
{
|
||||
static constexpr auto name = "toDateTime";
|
||||
|
||||
static NO_SANITIZE_UNDEFINED ToType execute(const FromType & from, const DateLUTImpl &)
|
||||
{
|
||||
if constexpr (date_time_overflow_behavior == FormatSettings::DateTimeOverflowBehavior::Throw)
|
||||
{
|
||||
if (from < 0 || from > MAX_DATETIME_TIMESTAMP) [[unlikely]]
|
||||
throw Exception(ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE, "Timestamp value {} is out of bounds of type DateTime", from);
|
||||
}
|
||||
|
||||
if (from < 0)
|
||||
return 0;
|
||||
return static_cast<ToType>(std::min(time_t(from), time_t(0xFFFFFFFF)));
|
||||
return static_cast<ToType>(std::min(time_t(from), time_t(MAX_DATETIME_TIMESTAMP)));
|
||||
}
|
||||
};
|
||||
|
||||
/** Special case of converting Int8, Int16, Int32 or (U)Int64 (and also, for convenience, Float32,
|
||||
* Float64) to DateTime. If the number is negative, saturate it to unix epoch time. If the number
|
||||
* exceeds UInt32, saturate to MAX_UINT32.
|
||||
*/
|
||||
template <typename Name> struct ConvertImpl<DataTypeInt8, DataTypeDateTime, Name>
|
||||
: DateTimeTransformImpl<DataTypeInt8, DataTypeDateTime, ToDateTimeTransformSigned<Int8, UInt32>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeInt16, DataTypeDateTime, Name>
|
||||
: DateTimeTransformImpl<DataTypeInt16, DataTypeDateTime, ToDateTimeTransformSigned<Int16, UInt32>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeInt32, DataTypeDateTime, Name>
|
||||
: DateTimeTransformImpl<DataTypeInt32, DataTypeDateTime, ToDateTimeTransformSigned<Int32, UInt32>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeInt64, DataTypeDateTime, Name>
|
||||
: DateTimeTransformImpl<DataTypeInt64, DataTypeDateTime, ToDateTimeTransform64Signed<Int64, UInt32>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeUInt64, DataTypeDateTime, Name>
|
||||
: DateTimeTransformImpl<DataTypeUInt64, DataTypeDateTime, ToDateTimeTransform64<UInt64, UInt32>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeFloat32, DataTypeDateTime, Name>
|
||||
: DateTimeTransformImpl<DataTypeFloat32, DataTypeDateTime, ToDateTimeTransform64Signed<Float32, UInt32>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeFloat64, DataTypeDateTime, Name>
|
||||
: DateTimeTransformImpl<DataTypeFloat64, DataTypeDateTime, ToDateTimeTransform64Signed<Float64, UInt32>> {};
|
||||
/// Special case of converting Int8, Int16, Int32 or (U)Int64 (and also, for convenience, Float32, Float64) to DateTime.
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeInt8, DataTypeDateTime, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeInt8, DataTypeDateTime, ToDateTimeTransformSigned<Int8, UInt32, default_date_time_overflow_behavior>, false> {};
|
||||
|
||||
constexpr time_t LUT_MIN_TIME = -2208988800l; // 1900-01-01 UTC
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeInt16, DataTypeDateTime, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeInt16, DataTypeDateTime, ToDateTimeTransformSigned<Int16, UInt32, default_date_time_overflow_behavior>, false> {};
|
||||
|
||||
constexpr time_t LUT_MAX_TIME = 10413791999l; // 2299-12-31 UTC
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeInt32, DataTypeDateTime, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeInt32, DataTypeDateTime, ToDateTimeTransformSigned<Int32, UInt32, default_date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeInt64, DataTypeDateTime, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeInt64, DataTypeDateTime, ToDateTimeTransform64Signed<Int64, UInt32, default_date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeUInt64, DataTypeDateTime, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeUInt64, DataTypeDateTime, ToDateTimeTransform64<UInt64, UInt32, default_date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeFloat32, DataTypeDateTime, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeFloat32, DataTypeDateTime, ToDateTimeTransform64Signed<Float32, UInt32, default_date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeFloat64, DataTypeDateTime, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeFloat64, DataTypeDateTime, ToDateTimeTransform64Signed<Float64, UInt32, default_date_time_overflow_behavior>, false> {};
|
||||
|
||||
/** Conversion of numeric to DateTime64
|
||||
*/
|
||||
|
||||
template <typename FromType>
|
||||
template <typename FromType, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ToDateTime64TransformUnsigned
|
||||
{
|
||||
static constexpr auto name = "toDateTime64";
|
||||
@ -641,11 +777,18 @@ struct ToDateTime64TransformUnsigned
|
||||
|
||||
NO_SANITIZE_UNDEFINED DateTime64::NativeType execute(FromType from, const DateLUTImpl &) const
|
||||
{
|
||||
from = std::min<time_t>(from, LUT_MAX_TIME);
|
||||
return DecimalUtils::decimalFromComponentsWithMultiplier<DateTime64>(from, 0, scale_multiplier);
|
||||
if constexpr (date_time_overflow_behavior == FormatSettings::DateTimeOverflowBehavior::Throw)
|
||||
{
|
||||
if (from > MAX_DATETIME64_TIMESTAMP) [[unlikely]]
|
||||
throw Exception(ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE, "Timestamp value {} is out of bounds of type DateTime64", from);
|
||||
else
|
||||
return DecimalUtils::decimalFromComponentsWithMultiplier<DateTime64>(from, 0, scale_multiplier);
|
||||
}
|
||||
else
|
||||
return DecimalUtils::decimalFromComponentsWithMultiplier<DateTime64>(std::min<time_t>(from, MAX_DATETIME64_TIMESTAMP), 0, scale_multiplier);
|
||||
}
|
||||
};
|
||||
template <typename FromType>
|
||||
template <typename FromType, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ToDateTime64TransformSigned
|
||||
{
|
||||
static constexpr auto name = "toDateTime64";
|
||||
@ -658,12 +801,18 @@ struct ToDateTime64TransformSigned
|
||||
|
||||
NO_SANITIZE_UNDEFINED DateTime64::NativeType execute(FromType from, const DateLUTImpl &) const
|
||||
{
|
||||
from = static_cast<FromType>(std::max<time_t>(from, LUT_MIN_TIME));
|
||||
from = static_cast<FromType>(std::min<time_t>(from, LUT_MAX_TIME));
|
||||
if constexpr (date_time_overflow_behavior == FormatSettings::DateTimeOverflowBehavior::Throw)
|
||||
{
|
||||
if (from < MIN_DATETIME64_TIMESTAMP || from > MAX_DATETIME64_TIMESTAMP) [[unlikely]]
|
||||
throw Exception(ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE, "Timestamp value {} is out of bounds of type DateTime64", from);
|
||||
}
|
||||
from = static_cast<FromType>(std::max<time_t>(from, MIN_DATETIME64_TIMESTAMP));
|
||||
from = static_cast<FromType>(std::min<time_t>(from, MAX_DATETIME64_TIMESTAMP));
|
||||
|
||||
return DecimalUtils::decimalFromComponentsWithMultiplier<DateTime64>(from, 0, scale_multiplier);
|
||||
}
|
||||
};
|
||||
template <typename FromDataType, typename FromType>
|
||||
template <typename FromDataType, typename FromType, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ToDateTime64TransformFloat
|
||||
{
|
||||
static constexpr auto name = "toDateTime64";
|
||||
@ -676,26 +825,45 @@ struct ToDateTime64TransformFloat
|
||||
|
||||
NO_SANITIZE_UNDEFINED DateTime64::NativeType execute(FromType from, const DateLUTImpl &) const
|
||||
{
|
||||
from = std::max(from, static_cast<FromType>(LUT_MIN_TIME));
|
||||
from = std::min(from, static_cast<FromType>(LUT_MAX_TIME));
|
||||
if constexpr (date_time_overflow_behavior == FormatSettings::DateTimeOverflowBehavior::Throw)
|
||||
{
|
||||
if (from < MIN_DATETIME64_TIMESTAMP || from > MAX_DATETIME64_TIMESTAMP) [[unlikely]]
|
||||
throw Exception(ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE, "Timestamp value {} is out of bounds of type DateTime64", from);
|
||||
}
|
||||
|
||||
from = std::max(from, static_cast<FromType>(MIN_DATETIME64_TIMESTAMP));
|
||||
from = std::min(from, static_cast<FromType>(MAX_DATETIME64_TIMESTAMP));
|
||||
return convertToDecimal<FromDataType, DataTypeDateTime64>(from, scale);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Name> struct ConvertImpl<DataTypeInt8, DataTypeDateTime64, Name>
|
||||
: DateTimeTransformImpl<DataTypeInt8, DataTypeDateTime64, ToDateTime64TransformSigned<Int8>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeInt16, DataTypeDateTime64, Name>
|
||||
: DateTimeTransformImpl<DataTypeInt16, DataTypeDateTime64, ToDateTime64TransformSigned<Int16>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeInt32, DataTypeDateTime64, Name>
|
||||
: DateTimeTransformImpl<DataTypeInt32, DataTypeDateTime64, ToDateTime64TransformSigned<Int32>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeInt64, DataTypeDateTime64, Name>
|
||||
: DateTimeTransformImpl<DataTypeInt64, DataTypeDateTime64, ToDateTime64TransformSigned<Int64>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeUInt64, DataTypeDateTime64, Name>
|
||||
: DateTimeTransformImpl<DataTypeUInt64, DataTypeDateTime64, ToDateTime64TransformUnsigned<UInt64>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeFloat32, DataTypeDateTime64, Name>
|
||||
: DateTimeTransformImpl<DataTypeFloat32, DataTypeDateTime64, ToDateTime64TransformFloat<DataTypeFloat32, Float32>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeFloat64, DataTypeDateTime64, Name>
|
||||
: DateTimeTransformImpl<DataTypeFloat64, DataTypeDateTime64, ToDateTime64TransformFloat<DataTypeFloat64, Float64>> {};
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeInt8, DataTypeDateTime64, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeInt8, DataTypeDateTime64, ToDateTime64TransformSigned<Int8, date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeInt16, DataTypeDateTime64, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeInt16, DataTypeDateTime64, ToDateTime64TransformSigned<Int16, date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeInt32, DataTypeDateTime64, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeInt32, DataTypeDateTime64, ToDateTime64TransformSigned<Int32, date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeInt64, DataTypeDateTime64, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeInt64, DataTypeDateTime64, ToDateTime64TransformSigned<Int64, date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeUInt64, DataTypeDateTime64, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeUInt64, DataTypeDateTime64, ToDateTime64TransformUnsigned<UInt64, date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeFloat32, DataTypeDateTime64, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeFloat32, DataTypeDateTime64, ToDateTime64TransformFloat<DataTypeFloat32, Float32, date_time_overflow_behavior>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeFloat64, DataTypeDateTime64, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeFloat64, DataTypeDateTime64, ToDateTime64TransformFloat<DataTypeFloat64, Float64, date_time_overflow_behavior>, false> {};
|
||||
|
||||
|
||||
/** Conversion of DateTime64 to Date or DateTime: discards fractional part.
|
||||
@ -720,10 +888,13 @@ struct FromDateTime64Transform
|
||||
|
||||
/** Conversion of DateTime64 to Date or DateTime: discards fractional part.
|
||||
*/
|
||||
template <typename Name> struct ConvertImpl<DataTypeDateTime64, DataTypeDate, Name, ConvertDefaultBehaviorTag>
|
||||
: DateTimeTransformImpl<DataTypeDateTime64, DataTypeDate, TransformDateTime64<ToDateImpl>> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeDateTime64, DataTypeDateTime, Name, ConvertDefaultBehaviorTag>
|
||||
: DateTimeTransformImpl<DataTypeDateTime64, DataTypeDateTime, TransformDateTime64<ToDateTimeImpl>> {};
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeDateTime64, DataTypeDate, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeDateTime64, DataTypeDate, TransformDateTime64<ToDateImpl<date_time_overflow_behavior>>, false> {};
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeDateTime64, DataTypeDateTime, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeDateTime64, DataTypeDateTime, TransformDateTime64<ToDateTimeImpl<date_time_overflow_behavior>>, false> {};
|
||||
|
||||
struct ToDateTime64Transform
|
||||
{
|
||||
@ -737,13 +908,13 @@ struct ToDateTime64Transform
|
||||
|
||||
DateTime64::NativeType execute(UInt16 d, const DateLUTImpl & time_zone) const
|
||||
{
|
||||
const auto dt = ToDateTimeImpl::execute(d, time_zone);
|
||||
const auto dt = ToDateTimeImpl<>::execute(d, time_zone);
|
||||
return execute(dt, time_zone);
|
||||
}
|
||||
|
||||
DateTime64::NativeType execute(Int32 d, const DateLUTImpl & time_zone) const
|
||||
{
|
||||
const auto dt = ToDateTimeImpl::execute(d, time_zone);
|
||||
Int64 dt = static_cast<Int64>(time_zone.fromDayNum(ExtendedDayNum(d)));
|
||||
return DecimalUtils::decimalFromComponentsWithMultiplier<DateTime64>(dt, 0, scale_multiplier);
|
||||
}
|
||||
|
||||
@ -755,11 +926,16 @@ struct ToDateTime64Transform
|
||||
|
||||
/** Conversion of Date or DateTime to DateTime64: add zero sub-second part.
|
||||
*/
|
||||
template <typename Name> struct ConvertImpl<DataTypeDate, DataTypeDateTime64, Name, ConvertDefaultBehaviorTag>
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeDate, DataTypeDateTime64, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeDate, DataTypeDateTime64, ToDateTime64Transform> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeDate32, DataTypeDateTime64, Name, ConvertDefaultBehaviorTag>
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeDate32, DataTypeDateTime64, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeDate32, DataTypeDateTime64, ToDateTime64Transform> {};
|
||||
template <typename Name> struct ConvertImpl<DataTypeDateTime, DataTypeDateTime64, Name, ConvertDefaultBehaviorTag>
|
||||
|
||||
template <typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct ConvertImpl<DataTypeDateTime, DataTypeDateTime64, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: DateTimeTransformImpl<DataTypeDateTime, DataTypeDateTime64, ToDateTime64Transform> {};
|
||||
|
||||
|
||||
@ -1115,8 +1291,8 @@ inline void convertFromTime<DataTypeDateTime>(DataTypeDateTime::FieldType & x, t
|
||||
{
|
||||
if (unlikely(time < 0))
|
||||
x = 0;
|
||||
else if (unlikely(time > 0xFFFFFFFF))
|
||||
x = 0xFFFFFFFF;
|
||||
else if (unlikely(time > MAX_DATETIME_TIMESTAMP))
|
||||
x = MAX_DATETIME_TIMESTAMP;
|
||||
else
|
||||
x = static_cast<UInt32>(time);
|
||||
}
|
||||
@ -1614,29 +1790,29 @@ struct ConvertThroughParsing
|
||||
};
|
||||
|
||||
|
||||
template <typename ToDataType, typename Name>
|
||||
template <typename ToDataType, typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
requires (!std::is_same_v<ToDataType, DataTypeString>)
|
||||
struct ConvertImpl<DataTypeString, ToDataType, Name, ConvertDefaultBehaviorTag>
|
||||
struct ConvertImpl<DataTypeString, ToDataType, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: ConvertThroughParsing<DataTypeString, ToDataType, Name, ConvertFromStringExceptionMode::Throw, ConvertFromStringParsingMode::Normal> {};
|
||||
|
||||
template <typename ToDataType, typename Name>
|
||||
template <typename ToDataType, typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
requires (!std::is_same_v<ToDataType, DataTypeFixedString>)
|
||||
struct ConvertImpl<DataTypeFixedString, ToDataType, Name, ConvertDefaultBehaviorTag>
|
||||
struct ConvertImpl<DataTypeFixedString, ToDataType, Name, ConvertDefaultBehaviorTag, date_time_overflow_behavior>
|
||||
: ConvertThroughParsing<DataTypeFixedString, ToDataType, Name, ConvertFromStringExceptionMode::Throw, ConvertFromStringParsingMode::Normal> {};
|
||||
|
||||
template <typename ToDataType, typename Name>
|
||||
template <typename ToDataType, typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
requires (!std::is_same_v<ToDataType, DataTypeString>)
|
||||
struct ConvertImpl<DataTypeString, ToDataType, Name, ConvertReturnNullOnErrorTag>
|
||||
struct ConvertImpl<DataTypeString, ToDataType, Name, ConvertReturnNullOnErrorTag, date_time_overflow_behavior>
|
||||
: ConvertThroughParsing<DataTypeString, ToDataType, Name, ConvertFromStringExceptionMode::Null, ConvertFromStringParsingMode::Normal> {};
|
||||
|
||||
template <typename ToDataType, typename Name>
|
||||
template <typename ToDataType, typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
requires (!std::is_same_v<ToDataType, DataTypeFixedString>)
|
||||
struct ConvertImpl<DataTypeFixedString, ToDataType, Name, ConvertReturnNullOnErrorTag>
|
||||
struct ConvertImpl<DataTypeFixedString, ToDataType, Name, ConvertReturnNullOnErrorTag, date_time_overflow_behavior>
|
||||
: ConvertThroughParsing<DataTypeFixedString, ToDataType, Name, ConvertFromStringExceptionMode::Null, ConvertFromStringParsingMode::Normal> {};
|
||||
|
||||
template <typename FromDataType, typename ToDataType, typename Name>
|
||||
template <typename FromDataType, typename ToDataType, typename Name, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
requires (is_any_of<FromDataType, DataTypeString, DataTypeFixedString> && is_any_of<ToDataType, DataTypeIPv4, DataTypeIPv6>)
|
||||
struct ConvertImpl<FromDataType, ToDataType, Name, ConvertReturnZeroOnErrorTag>
|
||||
struct ConvertImpl<FromDataType, ToDataType, Name, ConvertReturnZeroOnErrorTag, date_time_overflow_behavior>
|
||||
: ConvertThroughParsing<FromDataType, ToDataType, Name, ConvertFromStringExceptionMode::Zero, ConvertFromStringParsingMode::Normal> {};
|
||||
|
||||
/// Generic conversion of any type from String. Used for complex types: Array and Tuple or types with custom serialization.
|
||||
@ -2093,6 +2269,11 @@ private:
|
||||
const DataTypePtr from_type = removeNullable(arguments[0].type);
|
||||
ColumnPtr result_column;
|
||||
|
||||
[[maybe_unused]] FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior = default_date_time_overflow_behavior;
|
||||
|
||||
if (context)
|
||||
date_time_overflow_behavior = context->getSettingsRef().date_time_overflow_behavior.value;
|
||||
|
||||
auto call = [&](const auto & types, const auto & tag) -> bool
|
||||
{
|
||||
using Types = std::decay_t<decltype(types)>;
|
||||
@ -2116,13 +2297,42 @@ private:
|
||||
const ColumnWithTypeAndName & scale_column = arguments[1];
|
||||
UInt32 scale = extractToDecimalScale(scale_column);
|
||||
|
||||
result_column = ConvertImpl<LeftDataType, RightDataType, Name, SpecialTag>::execute(arguments, result_type, input_rows_count, scale);
|
||||
switch (date_time_overflow_behavior)
|
||||
{
|
||||
case FormatSettings::DateTimeOverflowBehavior::Throw:
|
||||
result_column = ConvertImpl<LeftDataType, RightDataType, Name, SpecialTag, FormatSettings::DateTimeOverflowBehavior::Throw>::execute(arguments, result_type, input_rows_count, scale);
|
||||
break;
|
||||
case FormatSettings::DateTimeOverflowBehavior::Ignore:
|
||||
result_column = ConvertImpl<LeftDataType, RightDataType, Name, SpecialTag, FormatSettings::DateTimeOverflowBehavior::Ignore>::execute(arguments, result_type, input_rows_count, scale);
|
||||
break;
|
||||
case FormatSettings::DateTimeOverflowBehavior::Saturate:
|
||||
result_column = ConvertImpl<LeftDataType, RightDataType, Name, SpecialTag, FormatSettings::DateTimeOverflowBehavior::Saturate>::execute(arguments, result_type, input_rows_count, scale);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
else if constexpr (IsDataTypeDateOrDateTime<RightDataType> && std::is_same_v<LeftDataType, DataTypeDateTime64>)
|
||||
{
|
||||
const auto * dt64 = assert_cast<const DataTypeDateTime64 *>(arguments[0].type.get());
|
||||
result_column = ConvertImpl<LeftDataType, RightDataType, Name, SpecialTag>::execute(arguments, result_type, input_rows_count, dt64->getScale());
|
||||
switch (date_time_overflow_behavior)
|
||||
{
|
||||
case FormatSettings::DateTimeOverflowBehavior::Throw:
|
||||
result_column = ConvertImpl<LeftDataType, RightDataType, Name, SpecialTag, FormatSettings::DateTimeOverflowBehavior::Throw>::execute(arguments, result_type, input_rows_count, dt64->getScale());
|
||||
break;
|
||||
case FormatSettings::DateTimeOverflowBehavior::Ignore:
|
||||
result_column = ConvertImpl<LeftDataType, RightDataType, Name, SpecialTag, FormatSettings::DateTimeOverflowBehavior::Ignore>::execute(arguments, result_type, input_rows_count, dt64->getScale());
|
||||
break;
|
||||
case FormatSettings::DateTimeOverflowBehavior::Saturate:
|
||||
result_column = ConvertImpl<LeftDataType, RightDataType, Name, SpecialTag, FormatSettings::DateTimeOverflowBehavior::Saturate>::execute(arguments, result_type, input_rows_count, dt64->getScale());
|
||||
break;
|
||||
}
|
||||
}
|
||||
#define GENERATE_OVERFLOW_MODE_CASE(OVERFLOW_MODE) \
|
||||
case FormatSettings::DateTimeOverflowBehavior::OVERFLOW_MODE: \
|
||||
result_column = ConvertImpl<LeftDataType, RightDataType, Name, SpecialTag, FormatSettings::DateTimeOverflowBehavior::OVERFLOW_MODE>::execute( \
|
||||
arguments, result_type, input_rows_count); \
|
||||
break;
|
||||
|
||||
else if constexpr (IsDataTypeDecimalOrNumber<LeftDataType> && IsDataTypeDecimalOrNumber<RightDataType>)
|
||||
{
|
||||
using LeftT = typename LeftDataType::FieldType;
|
||||
@ -2141,14 +2351,27 @@ private:
|
||||
}
|
||||
else
|
||||
{
|
||||
result_column
|
||||
= ConvertImpl<LeftDataType, RightDataType, Name, SpecialTag>::execute(arguments, result_type, input_rows_count);
|
||||
switch (date_time_overflow_behavior)
|
||||
{
|
||||
GENERATE_OVERFLOW_MODE_CASE(Throw)
|
||||
GENERATE_OVERFLOW_MODE_CASE(Ignore)
|
||||
GENERATE_OVERFLOW_MODE_CASE(Saturate)
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else if constexpr ((IsDataTypeNumber<LeftDataType> || IsDataTypeDateOrDateTime<LeftDataType>)
|
||||
&& IsDataTypeDateOrDateTime<RightDataType>)
|
||||
{
|
||||
result_column = ConvertImpl<LeftDataType, RightDataType, Name, SpecialTag>::execute(arguments, result_type, input_rows_count);
|
||||
switch (date_time_overflow_behavior)
|
||||
{
|
||||
GENERATE_OVERFLOW_MODE_CASE(Throw)
|
||||
GENERATE_OVERFLOW_MODE_CASE(Ignore)
|
||||
GENERATE_OVERFLOW_MODE_CASE(Saturate)
|
||||
}
|
||||
}
|
||||
#undef GENERATE_OVERFLOW_MODE_CASE
|
||||
else
|
||||
result_column = ConvertImpl<LeftDataType, RightDataType, Name, SpecialTag>::execute(arguments, result_type, input_rows_count);
|
||||
|
||||
return true;
|
||||
};
|
||||
@ -2559,16 +2782,19 @@ struct ToDateMonotonicity
|
||||
static IFunction::Monotonicity get(const IDataType & type, const Field & left, const Field & right)
|
||||
{
|
||||
auto which = WhichDataType(type);
|
||||
if (which.isDateOrDate32() || which.isDateTime() || which.isDateTime64() || which.isInt8() || which.isInt16() || which.isUInt8() || which.isUInt16())
|
||||
if (which.isDateOrDate32() || which.isDateTime() || which.isDateTime64() || which.isInt8() || which.isInt16() || which.isUInt8()
|
||||
|| which.isUInt16())
|
||||
{
|
||||
return { .is_monotonic = true, .is_always_monotonic = true };
|
||||
return {.is_monotonic = true, .is_always_monotonic = true};
|
||||
}
|
||||
else if (
|
||||
((left.getType() == Field::Types::UInt64 || left.isNull()) && (right.getType() == Field::Types::UInt64 || right.isNull())
|
||||
&& ((left.isNull() || left.get<UInt64>() < 0xFFFF) && (right.isNull() || right.get<UInt64>() >= 0xFFFF)))
|
||||
&& ((left.isNull() || left.get<UInt64>() < 0xFFFF) && (right.isNull() || right.get<UInt64>() >= 0xFFFF)))
|
||||
|| ((left.getType() == Field::Types::Int64 || left.isNull()) && (right.getType() == Field::Types::Int64 || right.isNull())
|
||||
&& ((left.isNull() || left.get<Int64>() < 0xFFFF) && (right.isNull() || right.get<Int64>() >= 0xFFFF)))
|
||||
|| (((left.getType() == Field::Types::Float64 || left.isNull()) && (right.getType() == Field::Types::Float64 || right.isNull())
|
||||
|| ((
|
||||
(left.getType() == Field::Types::Float64 || left.isNull())
|
||||
&& (right.getType() == Field::Types::Float64 || right.isNull())
|
||||
&& ((left.isNull() || left.get<Float64>() < 0xFFFF) && (right.isNull() || right.get<Float64>() >= 0xFFFF))))
|
||||
|| !isNativeNumber(type))
|
||||
{
|
||||
@ -2576,7 +2802,7 @@ struct ToDateMonotonicity
|
||||
}
|
||||
else
|
||||
{
|
||||
return { .is_monotonic = true, .is_always_monotonic = true };
|
||||
return {.is_monotonic = true, .is_always_monotonic = true};
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -2588,7 +2814,7 @@ struct ToDateTimeMonotonicity
|
||||
static IFunction::Monotonicity get(const IDataType & type, const Field &, const Field &)
|
||||
{
|
||||
if (type.isValueRepresentedByNumber())
|
||||
return { .is_monotonic = true, .is_always_monotonic = true };
|
||||
return {.is_monotonic = true, .is_always_monotonic = true};
|
||||
else
|
||||
return {};
|
||||
}
|
||||
@ -2674,11 +2900,17 @@ using FunctionToInt128 = FunctionConvert<DataTypeInt128, NameToInt128, ToNumberM
|
||||
using FunctionToInt256 = FunctionConvert<DataTypeInt256, NameToInt256, ToNumberMonotonicity<Int256>>;
|
||||
using FunctionToFloat32 = FunctionConvert<DataTypeFloat32, NameToFloat32, ToNumberMonotonicity<Float32>>;
|
||||
using FunctionToFloat64 = FunctionConvert<DataTypeFloat64, NameToFloat64, ToNumberMonotonicity<Float64>>;
|
||||
|
||||
using FunctionToDate = FunctionConvert<DataTypeDate, NameToDate, ToDateMonotonicity>;
|
||||
|
||||
using FunctionToDate32 = FunctionConvert<DataTypeDate32, NameToDate32, ToDateMonotonicity>;
|
||||
|
||||
using FunctionToDateTime = FunctionConvert<DataTypeDateTime, NameToDateTime, ToDateTimeMonotonicity>;
|
||||
|
||||
using FunctionToDateTime32 = FunctionConvert<DataTypeDateTime, NameToDateTime32, ToDateTimeMonotonicity>;
|
||||
|
||||
using FunctionToDateTime64 = FunctionConvert<DataTypeDateTime64, NameToDateTime64, ToDateTimeMonotonicity>;
|
||||
|
||||
using FunctionToUUID = FunctionConvert<DataTypeUUID, NameToUUID, ToNumberMonotonicity<UInt128>>;
|
||||
using FunctionToIPv4 = FunctionConvert<DataTypeIPv4, NameToIPv4, ToNumberMonotonicity<UInt32>>;
|
||||
using FunctionToIPv6 = FunctionConvert<DataTypeIPv6, NameToIPv6, ToNumberMonotonicity<UInt128>>;
|
||||
@ -2689,8 +2921,7 @@ using FunctionToDecimal64 = FunctionConvert<DataTypeDecimal<Decimal64>, NameToDe
|
||||
using FunctionToDecimal128 = FunctionConvert<DataTypeDecimal<Decimal128>, NameToDecimal128, UnknownMonotonicity>;
|
||||
using FunctionToDecimal256 = FunctionConvert<DataTypeDecimal<Decimal256>, NameToDecimal256, UnknownMonotonicity>;
|
||||
|
||||
|
||||
template <typename DataType> struct FunctionTo;
|
||||
template <typename DataType, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior = default_date_time_overflow_behavior> struct FunctionTo;
|
||||
|
||||
template <> struct FunctionTo<DataTypeUInt8> { using Type = FunctionToUInt8; };
|
||||
template <> struct FunctionTo<DataTypeUInt16> { using Type = FunctionToUInt16; };
|
||||
@ -2706,10 +2937,19 @@ template <> struct FunctionTo<DataTypeInt128> { using Type = FunctionToInt128; }
|
||||
template <> struct FunctionTo<DataTypeInt256> { using Type = FunctionToInt256; };
|
||||
template <> struct FunctionTo<DataTypeFloat32> { using Type = FunctionToFloat32; };
|
||||
template <> struct FunctionTo<DataTypeFloat64> { using Type = FunctionToFloat64; };
|
||||
template <> struct FunctionTo<DataTypeDate> { using Type = FunctionToDate; };
|
||||
template <> struct FunctionTo<DataTypeDate32> { using Type = FunctionToDate32; };
|
||||
template <> struct FunctionTo<DataTypeDateTime> { using Type = FunctionToDateTime; };
|
||||
template <> struct FunctionTo<DataTypeDateTime64> { using Type = FunctionToDateTime64; };
|
||||
|
||||
template <FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct FunctionTo<DataTypeDate, date_time_overflow_behavior> { using Type = FunctionToDate; };
|
||||
|
||||
template <FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct FunctionTo<DataTypeDate32, date_time_overflow_behavior> { using Type = FunctionToDate32; };
|
||||
|
||||
template <FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct FunctionTo<DataTypeDateTime, date_time_overflow_behavior> { using Type = FunctionToDateTime; };
|
||||
|
||||
template <FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior>
|
||||
struct FunctionTo<DataTypeDateTime64, date_time_overflow_behavior> { using Type = FunctionToDateTime64; };
|
||||
|
||||
template <> struct FunctionTo<DataTypeUUID> { using Type = FunctionToUUID; };
|
||||
template <> struct FunctionTo<DataTypeIPv4> { using Type = FunctionToIPv4; };
|
||||
template <> struct FunctionTo<DataTypeIPv6> { using Type = FunctionToIPv6; };
|
||||
@ -3044,6 +3284,10 @@ private:
|
||||
bool can_apply_accurate_cast = (cast_type == CastType::accurate || cast_type == CastType::accurateOrNull)
|
||||
&& (which.isInt() || which.isUInt() || which.isFloat());
|
||||
|
||||
FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior = default_date_time_overflow_behavior;
|
||||
if (context)
|
||||
date_time_overflow_behavior = context->getSettingsRef().date_time_overflow_behavior;
|
||||
|
||||
if (requested_result_is_nullable && checkAndGetDataType<DataTypeString>(from_type.get()))
|
||||
{
|
||||
/// In case when converting to Nullable type, we apply different parsing rule,
|
||||
@ -3060,7 +3304,7 @@ private:
|
||||
|
||||
auto wrapper_cast_type = cast_type;
|
||||
|
||||
return [wrapper_cast_type, from_type_index, to_type]
|
||||
return [wrapper_cast_type, from_type_index, to_type, date_time_overflow_behavior]
|
||||
(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, const ColumnNullable *column_nullable, size_t input_rows_count)
|
||||
{
|
||||
ColumnPtr result_column;
|
||||
@ -3073,31 +3317,60 @@ private:
|
||||
{
|
||||
if constexpr (IsDataTypeNumber<RightDataType>)
|
||||
{
|
||||
#define GENERATE_OVERFLOW_MODE_CASE(OVERFLOW_MODE, ADDITIONS) \
|
||||
case FormatSettings::DateTimeOverflowBehavior::OVERFLOW_MODE: \
|
||||
result_column = ConvertImpl<LeftDataType, RightDataType, FunctionName, ConvertDefaultBehaviorTag, FormatSettings::DateTimeOverflowBehavior::OVERFLOW_MODE>::execute( \
|
||||
arguments, result_type, input_rows_count, ADDITIONS()); \
|
||||
break;
|
||||
if (wrapper_cast_type == CastType::accurate)
|
||||
{
|
||||
result_column = ConvertImpl<LeftDataType, RightDataType, FunctionName>::execute(
|
||||
arguments, result_type, input_rows_count, AccurateConvertStrategyAdditions());
|
||||
switch (date_time_overflow_behavior)
|
||||
{
|
||||
GENERATE_OVERFLOW_MODE_CASE(Throw, AccurateConvertStrategyAdditions)
|
||||
GENERATE_OVERFLOW_MODE_CASE(Ignore, AccurateConvertStrategyAdditions)
|
||||
GENERATE_OVERFLOW_MODE_CASE(Saturate, AccurateConvertStrategyAdditions)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result_column = ConvertImpl<LeftDataType, RightDataType, FunctionName>::execute(
|
||||
arguments, result_type, input_rows_count, AccurateOrNullConvertStrategyAdditions());
|
||||
switch (date_time_overflow_behavior)
|
||||
{
|
||||
GENERATE_OVERFLOW_MODE_CASE(Throw, AccurateOrNullConvertStrategyAdditions)
|
||||
GENERATE_OVERFLOW_MODE_CASE(Ignore, AccurateOrNullConvertStrategyAdditions)
|
||||
GENERATE_OVERFLOW_MODE_CASE(Saturate, AccurateOrNullConvertStrategyAdditions)
|
||||
}
|
||||
}
|
||||
#undef GENERATE_OVERFLOW_MODE_CASE
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if constexpr (std::is_same_v<RightDataType, DataTypeDate> || std::is_same_v<RightDataType, DataTypeDateTime>)
|
||||
{
|
||||
#define GENERATE_OVERFLOW_MODE_CASE(OVERFLOW_MODE, ADDITIONS) \
|
||||
case FormatSettings::DateTimeOverflowBehavior::OVERFLOW_MODE: \
|
||||
result_column = ConvertImpl<LeftDataType, RightDataType, FunctionName, ConvertDefaultBehaviorTag, FormatSettings::DateTimeOverflowBehavior::OVERFLOW_MODE>::template execute<ADDITIONS>( \
|
||||
arguments, result_type, input_rows_count); \
|
||||
break;
|
||||
if (wrapper_cast_type == CastType::accurate)
|
||||
{
|
||||
result_column = ConvertImpl<LeftDataType, RightDataType, FunctionName>::template execute<DateTimeAccurateConvertStrategyAdditions>(
|
||||
arguments, result_type, input_rows_count);
|
||||
switch (date_time_overflow_behavior)
|
||||
{
|
||||
GENERATE_OVERFLOW_MODE_CASE(Throw, DateTimeAccurateConvertStrategyAdditions)
|
||||
GENERATE_OVERFLOW_MODE_CASE(Ignore, DateTimeAccurateConvertStrategyAdditions)
|
||||
GENERATE_OVERFLOW_MODE_CASE(Saturate, DateTimeAccurateConvertStrategyAdditions)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result_column = ConvertImpl<LeftDataType, RightDataType, FunctionName>::template execute<DateTimeAccurateOrNullConvertStrategyAdditions>(
|
||||
arguments, result_type, input_rows_count);
|
||||
switch (date_time_overflow_behavior)
|
||||
{
|
||||
GENERATE_OVERFLOW_MODE_CASE(Throw, DateTimeAccurateOrNullConvertStrategyAdditions)
|
||||
GENERATE_OVERFLOW_MODE_CASE(Ignore, DateTimeAccurateOrNullConvertStrategyAdditions)
|
||||
GENERATE_OVERFLOW_MODE_CASE(Saturate, DateTimeAccurateOrNullConvertStrategyAdditions)
|
||||
}
|
||||
}
|
||||
#undef GENERATE_OVERFLOW_MODE_CASE
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -578,7 +578,6 @@ ColumnPtr FunctionArrayElement::executeString(
|
||||
return nullptr;
|
||||
|
||||
auto col_res = ColumnString::create();
|
||||
|
||||
ArrayElementStringImpl::vector<IndexType>(
|
||||
col_nested->getChars(),
|
||||
col_array->getOffsets(),
|
||||
@ -819,11 +818,49 @@ void FunctionArrayElement::executeMatchKeyToIndex(
|
||||
const Offsets & offsets, PaddedPODArray<UInt64> & matched_idxs, const Matcher & matcher)
|
||||
{
|
||||
size_t rows = offsets.size();
|
||||
for (size_t i = 0; i < rows; ++i)
|
||||
size_t expected_match_pos = 0;
|
||||
bool matched = false;
|
||||
if (!rows)
|
||||
return;
|
||||
|
||||
/// In practice, map keys are usually in the same order, it is worth a try to
|
||||
/// predict the next key position. So it can avoid a lot of unnecessary comparisons.
|
||||
for (size_t j = offsets[-1], end = offsets[0]; j < end; ++j)
|
||||
{
|
||||
bool matched = false;
|
||||
size_t begin = offsets[i - 1];
|
||||
size_t end = offsets[i];
|
||||
if (matcher.match(j, 0))
|
||||
{
|
||||
matched_idxs.push_back(j - offsets[-1] + 1);
|
||||
matched = true;
|
||||
expected_match_pos = end + j - offsets[-1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!matched)
|
||||
{
|
||||
expected_match_pos = offsets[0];
|
||||
matched_idxs.push_back(0);
|
||||
}
|
||||
size_t i = 1;
|
||||
for (; i < rows; ++i)
|
||||
{
|
||||
const auto & begin = offsets[i - 1];
|
||||
const auto & end = offsets[i];
|
||||
if (expected_match_pos < end && matcher.match(expected_match_pos, i))
|
||||
{
|
||||
auto map_key_index = expected_match_pos - begin;
|
||||
matched_idxs.push_back(map_key_index + 1);
|
||||
expected_match_pos = end + map_key_index;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// fallback to linear search
|
||||
for (; i < rows; ++i)
|
||||
{
|
||||
matched = false;
|
||||
const auto & begin = offsets[i - 1];
|
||||
const auto & end = offsets[i];
|
||||
for (size_t j = begin; j < end; ++j)
|
||||
{
|
||||
if (matcher.match(j, i))
|
||||
|
137
src/Functions/formatQuery.cpp
Normal file
137
src/Functions/formatQuery.cpp
Normal file
@ -0,0 +1,137 @@
|
||||
#include <Columns/ColumnString.h>
|
||||
#include <Functions/FunctionFactory.h>
|
||||
#include <Functions/FunctionHelpers.h>
|
||||
#include <IO/WriteBufferFromVector.h>
|
||||
#include <Interpreters/Context.h>
|
||||
#include <Parsers/ParserQuery.h>
|
||||
#include <Parsers/formatAST.h>
|
||||
#include <Parsers/parseQuery.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int ILLEGAL_COLUMN;
|
||||
}
|
||||
|
||||
template <bool one_line, typename Name>
|
||||
class FunctionFormatQuery : public IFunction
|
||||
{
|
||||
public:
|
||||
static constexpr auto name = Name::name;
|
||||
static FunctionPtr create(ContextPtr context)
|
||||
{
|
||||
const auto & settings = context->getSettings();
|
||||
return std::make_shared<FunctionFormatQuery>(settings.max_query_size, settings.max_parser_depth);
|
||||
}
|
||||
|
||||
FunctionFormatQuery(size_t max_query_size_, size_t max_parser_depth_)
|
||||
: max_query_size(max_query_size_), max_parser_depth(max_parser_depth_)
|
||||
{
|
||||
}
|
||||
|
||||
String getName() const override { return name; }
|
||||
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
|
||||
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; }
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
||||
{
|
||||
FunctionArgumentDescriptors mandatory_args{{"query", &isString<IDataType>, nullptr, "String"}};
|
||||
validateFunctionArgumentTypes(*this, arguments, mandatory_args);
|
||||
return arguments[0].type;
|
||||
}
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const ColumnPtr column = arguments[0].column;
|
||||
if (const ColumnString * col = checkAndGetColumn<ColumnString>(column.get()))
|
||||
{
|
||||
auto col_res = ColumnString::create();
|
||||
formatVector(col->getChars(), col->getOffsets(), col_res->getChars(), col_res->getOffsets());
|
||||
return col_res;
|
||||
}
|
||||
else
|
||||
throw Exception(
|
||||
ErrorCodes::ILLEGAL_COLUMN, "Illegal column {} of argument of function {}", arguments[0].column->getName(), getName());
|
||||
}
|
||||
|
||||
private:
|
||||
void formatQueryImpl(const char * begin, const char * end, ColumnString::Chars & output) const
|
||||
{
|
||||
ParserQuery parser{end};
|
||||
auto ast = parseQuery(parser, begin, end, {}, max_query_size, max_parser_depth);
|
||||
WriteBufferFromVector buf(output, AppendModeTag{});
|
||||
formatAST(*ast, buf, /* hilite */ false, /* one_line */ one_line);
|
||||
buf.finalize();
|
||||
}
|
||||
void formatVector(
|
||||
const ColumnString::Chars & data,
|
||||
const ColumnString::Offsets & offsets,
|
||||
ColumnString::Chars & res_data,
|
||||
ColumnString::Offsets & res_offsets) const
|
||||
{
|
||||
const size_t size = offsets.size();
|
||||
res_offsets.resize(size);
|
||||
res_data.reserve(data.size());
|
||||
|
||||
size_t prev_in_offset = 0;
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
const auto * begin = reinterpret_cast<const char *>(&data[prev_in_offset]);
|
||||
const char * end = begin + offsets[i] - 1;
|
||||
formatQueryImpl(begin, end, res_data);
|
||||
res_offsets[i] = res_data.size() + 1;
|
||||
prev_in_offset = offsets[i];
|
||||
}
|
||||
}
|
||||
size_t max_query_size;
|
||||
size_t max_parser_depth;
|
||||
};
|
||||
|
||||
struct NameFormatQuery
|
||||
{
|
||||
static constexpr auto name = "formatQuery";
|
||||
};
|
||||
|
||||
struct NameFormatQuerySingleLine
|
||||
{
|
||||
static constexpr auto name = "formatQuerySingleLine";
|
||||
};
|
||||
|
||||
REGISTER_FUNCTION(formatQuery)
|
||||
{
|
||||
factory.registerFunction<FunctionFormatQuery<false, NameFormatQuery>>(FunctionDocumentation{
|
||||
.description = "Returns a formatted, possibly multi-line, version of the given SQL query.\n[example:multiline]",
|
||||
.syntax = "formatQuery(query)",
|
||||
.arguments = {{"query", "The SQL query to be formatted. [String](../../sql-reference/data-types/string.md)"}},
|
||||
.returned_value = "The formatted query. [String](../../sql-reference/data-types/string.md).",
|
||||
.examples{
|
||||
{"multiline",
|
||||
"SELECT formatQuery('select a, b FRom tab WHERE a > 3 and b < 3');",
|
||||
"SELECT\n"
|
||||
" a,\n"
|
||||
" b\n"
|
||||
"FROM tab\n"
|
||||
"WHERE (a > 3) AND (b < 3)"}},
|
||||
.categories{"Other"}});
|
||||
}
|
||||
|
||||
REGISTER_FUNCTION(formatQuerySingleLine)
|
||||
{
|
||||
factory.registerFunction<FunctionFormatQuery<true, NameFormatQuerySingleLine>>(FunctionDocumentation{
|
||||
.description = "Like formatQuery() but the returned formatted string contains no line breaks.\n[example:multiline]",
|
||||
.syntax = "formatQuerySingleLine(query)",
|
||||
.arguments = {{"query", "The SQL query to be formatted. [String](../../sql-reference/data-types/string.md)"}},
|
||||
.returned_value = "The formatted query. [String](../../sql-reference/data-types/string.md).",
|
||||
.examples{
|
||||
{"multiline",
|
||||
"SELECT formatQuerySingleLine('select a, b FRom tab WHERE a > 3 and b < 3');",
|
||||
"SELECT a, b FROM tab WHERE (a > 3) AND (b < 3)"}},
|
||||
.categories{"Other"}});
|
||||
}
|
||||
}
|
@ -902,8 +902,8 @@ namespace
|
||||
{
|
||||
void checkTemporaryTableEngineName(const String& name)
|
||||
{
|
||||
if (name.starts_with("Replicated") || name == "KeeperMap")
|
||||
throw Exception(ErrorCodes::INCORRECT_QUERY, "Temporary tables cannot be created with Replicated or KeeperMap table engines");
|
||||
if (name.starts_with("Replicated") || name.starts_with("Shared") || name == "KeeperMap")
|
||||
throw Exception(ErrorCodes::INCORRECT_QUERY, "Temporary tables cannot be created with Replicated, Shared or KeeperMap table engines");
|
||||
}
|
||||
|
||||
void setDefaultTableEngine(ASTStorage &storage, DefaultTableEngine engine)
|
||||
|
@ -2936,7 +2936,11 @@ void InterpreterSelectQuery::executeWindow(QueryPlan & query_plan)
|
||||
query_plan.addStep(std::move(sorting_step));
|
||||
}
|
||||
|
||||
auto window_step = std::make_unique<WindowStep>(query_plan.getCurrentDataStream(), window, window.window_functions);
|
||||
// Fan out streams only for the last window to preserve the ordering between windows,
|
||||
// and WindowTransform works on single stream anyway.
|
||||
const bool streams_fan_out = settings.query_plan_enable_multithreading_after_window_functions && ((i + 1) == windows_sorted.size());
|
||||
|
||||
auto window_step = std::make_unique<WindowStep>(query_plan.getCurrentDataStream(), window, window.window_functions, streams_fan_out);
|
||||
window_step->setStepDescription("Window step for window '" + window.window_name + "'");
|
||||
|
||||
query_plan.addStep(std::move(window_step));
|
||||
|
@ -905,8 +905,12 @@ void addWindowSteps(QueryPlan & query_plan,
|
||||
query_plan.addStep(std::move(sorting_step));
|
||||
}
|
||||
|
||||
// Fan out streams only for the last window to preserve the ordering between windows,
|
||||
// and WindowTransform works on single stream anyway.
|
||||
const bool streams_fan_out = settings.query_plan_enable_multithreading_after_window_functions && ((i + 1) == window_descriptions_size);
|
||||
|
||||
auto window_step
|
||||
= std::make_unique<WindowStep>(query_plan.getCurrentDataStream(), window_description, window_description.window_functions);
|
||||
= std::make_unique<WindowStep>(query_plan.getCurrentDataStream(), window_description, window_description.window_functions, streams_fan_out);
|
||||
window_step->setStepDescription("Window step for window '" + window_description.window_name + "'");
|
||||
query_plan.addStep(std::move(window_step));
|
||||
}
|
||||
|
@ -157,6 +157,7 @@ void ArrowBlockInputFormat::prepareReader()
|
||||
"Arrow",
|
||||
format_settings.arrow.allow_missing_columns,
|
||||
format_settings.null_as_default,
|
||||
format_settings.date_time_overflow_behavior,
|
||||
format_settings.arrow.case_insensitive_column_matching);
|
||||
|
||||
if (stream)
|
||||
|
@ -247,11 +247,13 @@ static ColumnWithTypeAndName readColumnWithBooleanData(std::shared_ptr<arrow::Ch
|
||||
return {std::move(internal_column), internal_type, column_name};
|
||||
}
|
||||
|
||||
static ColumnWithTypeAndName readColumnWithDate32Data(std::shared_ptr<arrow::ChunkedArray> & arrow_column, const String & column_name, const DataTypePtr & type_hint)
|
||||
static ColumnWithTypeAndName readColumnWithDate32Data(std::shared_ptr<arrow::ChunkedArray> & arrow_column, const String & column_name,
|
||||
const DataTypePtr & type_hint, FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior)
|
||||
{
|
||||
DataTypePtr internal_type;
|
||||
bool check_date_range = false;
|
||||
/// Make result type Date32 when requested type is actually Date32 or when we use schema inference
|
||||
|
||||
if (!type_hint || (type_hint && isDate32(*type_hint)))
|
||||
{
|
||||
internal_type = std::make_shared<DataTypeDate32>();
|
||||
@ -277,8 +279,21 @@ static ColumnWithTypeAndName readColumnWithDate32Data(std::shared_ptr<arrow::Chu
|
||||
{
|
||||
Int32 days_num = static_cast<Int32>(chunk.Value(value_i));
|
||||
if (days_num > DATE_LUT_MAX_EXTEND_DAY_NUM || days_num < -DAYNUM_OFFSET_EPOCH)
|
||||
throw Exception{ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE,
|
||||
"Input value {} of a column \"{}\" is out of allowed Date32 range, which is [{}, {}]", days_num, column_name, DAYNUM_OFFSET_EPOCH, DATE_LUT_MAX_EXTEND_DAY_NUM};
|
||||
{
|
||||
switch (date_time_overflow_behavior)
|
||||
{
|
||||
case FormatSettings::DateTimeOverflowBehavior::Saturate:
|
||||
days_num = (days_num < -DAYNUM_OFFSET_EPOCH) ? -DAYNUM_OFFSET_EPOCH : DATE_LUT_MAX_EXTEND_DAY_NUM;
|
||||
break;
|
||||
default:
|
||||
/// Prior to introducing `date_time_overflow_behavior`, this function threw an error in case value was out of range.
|
||||
/// In order to leave this behavior as default, we also throw when `date_time_overflow_mode == ignore`, as it is the setting's default value
|
||||
/// (As we want to make this backwards compatible, not break any workflows.)
|
||||
throw Exception{ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE,
|
||||
"Input value {} of a column \"{}\" is out of allowed Date32 range, which is [{}, {}]",
|
||||
days_num,column_name, -DAYNUM_OFFSET_EPOCH, DATE_LUT_MAX_EXTEND_DAY_NUM};
|
||||
}
|
||||
}
|
||||
|
||||
column_data.emplace_back(days_num);
|
||||
}
|
||||
@ -681,6 +696,7 @@ static ColumnWithTypeAndName readColumnFromArrowColumn(
|
||||
bool allow_null_type,
|
||||
bool skip_columns_with_unsupported_types,
|
||||
bool & skipped,
|
||||
FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior = FormatSettings::DateTimeOverflowBehavior::Ignore,
|
||||
DataTypePtr type_hint = nullptr,
|
||||
bool is_map_nested = false)
|
||||
{
|
||||
@ -691,7 +707,7 @@ static ColumnWithTypeAndName readColumnFromArrowColumn(
|
||||
DataTypePtr nested_type_hint;
|
||||
if (type_hint)
|
||||
nested_type_hint = removeNullable(type_hint);
|
||||
auto nested_column = readColumnFromArrowColumn(arrow_column, column_name, format_name, true, dictionary_infos, allow_null_type, skip_columns_with_unsupported_types, skipped, nested_type_hint);
|
||||
auto nested_column = readColumnFromArrowColumn(arrow_column, column_name, format_name, true, dictionary_infos, allow_null_type, skip_columns_with_unsupported_types, skipped, date_time_overflow_behavior, nested_type_hint);
|
||||
if (skipped)
|
||||
return {};
|
||||
auto nullmap_column = readByteMapFromArrowColumn(arrow_column);
|
||||
@ -756,7 +772,7 @@ static ColumnWithTypeAndName readColumnFromArrowColumn(
|
||||
case arrow::Type::BOOL:
|
||||
return readColumnWithBooleanData(arrow_column, column_name);
|
||||
case arrow::Type::DATE32:
|
||||
return readColumnWithDate32Data(arrow_column, column_name, type_hint);
|
||||
return readColumnWithDate32Data(arrow_column, column_name, type_hint, date_time_overflow_behavior);
|
||||
case arrow::Type::DATE64:
|
||||
return readColumnWithDate64Data(arrow_column, column_name);
|
||||
// ClickHouse writes Date as arrow UINT16 and DateTime as arrow UINT32,
|
||||
@ -804,7 +820,7 @@ static ColumnWithTypeAndName readColumnFromArrowColumn(
|
||||
}
|
||||
}
|
||||
auto arrow_nested_column = getNestedArrowColumn(arrow_column);
|
||||
auto nested_column = readColumnFromArrowColumn(arrow_nested_column, column_name, format_name, false, dictionary_infos, allow_null_type, skip_columns_with_unsupported_types, skipped, nested_type_hint, true);
|
||||
auto nested_column = readColumnFromArrowColumn(arrow_nested_column, column_name, format_name, false, dictionary_infos, allow_null_type, skip_columns_with_unsupported_types, skipped, date_time_overflow_behavior, nested_type_hint, true);
|
||||
if (skipped)
|
||||
return {};
|
||||
|
||||
@ -839,7 +855,7 @@ static ColumnWithTypeAndName readColumnFromArrowColumn(
|
||||
nested_type_hint = array_type_hint->getNestedType();
|
||||
}
|
||||
auto arrow_nested_column = getNestedArrowColumn(arrow_column);
|
||||
auto nested_column = readColumnFromArrowColumn(arrow_nested_column, column_name, format_name, false, dictionary_infos, allow_null_type, skip_columns_with_unsupported_types, skipped, nested_type_hint);
|
||||
auto nested_column = readColumnFromArrowColumn(arrow_nested_column, column_name, format_name, false, dictionary_infos, allow_null_type, skip_columns_with_unsupported_types, skipped, date_time_overflow_behavior, nested_type_hint);
|
||||
if (skipped)
|
||||
return {};
|
||||
auto offsets_column = readOffsetsFromArrowListColumn(arrow_column);
|
||||
@ -880,7 +896,7 @@ static ColumnWithTypeAndName readColumnFromArrowColumn(
|
||||
nested_type_hint = tuple_type_hint->getElement(i);
|
||||
}
|
||||
auto nested_arrow_column = std::make_shared<arrow::ChunkedArray>(nested_arrow_columns[i]);
|
||||
auto element = readColumnFromArrowColumn(nested_arrow_column, field_name, format_name, false, dictionary_infos, allow_null_type, skip_columns_with_unsupported_types, skipped, nested_type_hint);
|
||||
auto element = readColumnFromArrowColumn(nested_arrow_column, field_name, format_name, false, dictionary_infos, allow_null_type, skip_columns_with_unsupported_types, skipped, date_time_overflow_behavior, nested_type_hint);
|
||||
if (skipped)
|
||||
return {};
|
||||
tuple_elements.emplace_back(std::move(element.column));
|
||||
@ -907,7 +923,7 @@ static ColumnWithTypeAndName readColumnFromArrowColumn(
|
||||
dict_array.emplace_back(dict_chunk.dictionary());
|
||||
}
|
||||
auto arrow_dict_column = std::make_shared<arrow::ChunkedArray>(dict_array);
|
||||
auto dict_column = readColumnFromArrowColumn(arrow_dict_column, column_name, format_name, false, dictionary_infos, allow_null_type, skip_columns_with_unsupported_types, skipped);
|
||||
auto dict_column = readColumnFromArrowColumn(arrow_dict_column, column_name, format_name, false, dictionary_infos, allow_null_type, skip_columns_with_unsupported_types, skipped, date_time_overflow_behavior);
|
||||
for (size_t i = 0; i != dict_column.column->size(); ++i)
|
||||
{
|
||||
if (dict_column.column->isDefaultAt(i))
|
||||
@ -997,7 +1013,8 @@ static void checkStatus(const arrow::Status & status, const String & column_name
|
||||
|
||||
|
||||
Block ArrowColumnToCHColumn::arrowSchemaToCHHeader(
|
||||
const arrow::Schema & schema, const std::string & format_name, bool skip_columns_with_unsupported_types, const Block * hint_header, bool ignore_case)
|
||||
const arrow::Schema & schema, const std::string & format_name,
|
||||
bool skip_columns_with_unsupported_types, const Block * hint_header, bool ignore_case)
|
||||
{
|
||||
ColumnsWithTypeAndName sample_columns;
|
||||
std::unordered_set<String> nested_table_names;
|
||||
@ -1040,12 +1057,14 @@ ArrowColumnToCHColumn::ArrowColumnToCHColumn(
|
||||
const std::string & format_name_,
|
||||
bool allow_missing_columns_,
|
||||
bool null_as_default_,
|
||||
FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior_,
|
||||
bool case_insensitive_matching_)
|
||||
: header(header_)
|
||||
, format_name(format_name_)
|
||||
, allow_missing_columns(allow_missing_columns_)
|
||||
, null_as_default(null_as_default_)
|
||||
, case_insensitive_matching(case_insensitive_matching_)
|
||||
, date_time_overflow_behavior(date_time_overflow_behavior_)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1102,8 +1121,9 @@ void ArrowColumnToCHColumn::arrowColumnsToCHChunk(Chunk & res, NameToColumnPtr &
|
||||
auto nested_table_type = Nested::collect(nested_columns).front().type;
|
||||
|
||||
std::shared_ptr<arrow::ChunkedArray> arrow_column = name_to_column_ptr[search_nested_table_name];
|
||||
ColumnsWithTypeAndName cols = {readColumnFromArrowColumn(
|
||||
arrow_column, nested_table_name, format_name, false, dictionary_infos, true, false, skipped, nested_table_type)};
|
||||
ColumnsWithTypeAndName cols = {
|
||||
readColumnFromArrowColumn(arrow_column, nested_table_name, format_name, false, dictionary_infos, true, false,
|
||||
skipped, date_time_overflow_behavior, nested_table_type)};
|
||||
BlockPtr block_ptr = std::make_shared<Block>(cols);
|
||||
auto column_extractor = std::make_shared<NestedColumnExtractHelper>(*block_ptr, case_insensitive_matching);
|
||||
nested_tables[search_nested_table_name] = {block_ptr, column_extractor};
|
||||
@ -1138,7 +1158,7 @@ void ArrowColumnToCHColumn::arrowColumnsToCHChunk(Chunk & res, NameToColumnPtr &
|
||||
{
|
||||
auto arrow_column = name_to_column_ptr[search_column_name];
|
||||
column = readColumnFromArrowColumn(
|
||||
arrow_column, header_column.name, format_name, false, dictionary_infos, true, false, skipped, header_column.type);
|
||||
arrow_column, header_column.name, format_name, false, dictionary_infos, true, false, skipped, date_time_overflow_behavior, header_column.type);
|
||||
}
|
||||
|
||||
if (null_as_default)
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <Core/ColumnWithTypeAndName.h>
|
||||
#include <Core/Block.h>
|
||||
#include <arrow/table.h>
|
||||
|
||||
#include <Formats/FormatSettings.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
@ -26,6 +26,7 @@ public:
|
||||
const std::string & format_name_,
|
||||
bool allow_missing_columns_,
|
||||
bool null_as_default_,
|
||||
FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior_,
|
||||
bool case_insensitive_matching_ = false);
|
||||
|
||||
void arrowTableToCHChunk(Chunk & res, std::shared_ptr<arrow::Table> & table, size_t num_rows, BlockMissingValues * block_missing_values = nullptr);
|
||||
@ -56,6 +57,7 @@ private:
|
||||
bool allow_missing_columns;
|
||||
bool null_as_default;
|
||||
bool case_insensitive_matching;
|
||||
FormatSettings::DateTimeOverflowBehavior date_time_overflow_behavior;
|
||||
|
||||
/// Map {column name : dictionary column}.
|
||||
/// To avoid converting dictionary from Arrow Dictionary
|
||||
|
@ -131,6 +131,7 @@ void ORCBlockInputFormat::prepareReader()
|
||||
"ORC",
|
||||
format_settings.orc.allow_missing_columns,
|
||||
format_settings.null_as_default,
|
||||
format_settings.date_time_overflow_behavior,
|
||||
format_settings.orc.case_insensitive_column_matching);
|
||||
|
||||
const bool ignore_case = format_settings.orc.case_insensitive_column_matching;
|
||||
|
@ -493,6 +493,7 @@ void ParquetBlockInputFormat::initializeRowGroupBatchReader(size_t row_group_bat
|
||||
"Parquet",
|
||||
format_settings.parquet.allow_missing_columns,
|
||||
format_settings.null_as_default,
|
||||
format_settings.date_time_overflow_behavior,
|
||||
format_settings.parquet.case_insensitive_column_matching);
|
||||
}
|
||||
|
||||
|
@ -10,14 +10,14 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
static ITransformingStep::Traits getTraits()
|
||||
static ITransformingStep::Traits getTraits(bool preserves_sorting)
|
||||
{
|
||||
return ITransformingStep::Traits
|
||||
{
|
||||
{
|
||||
.returns_single_stream = false,
|
||||
.preserves_number_of_streams = true,
|
||||
.preserves_sorting = true,
|
||||
.preserves_sorting = preserves_sorting,
|
||||
},
|
||||
{
|
||||
.preserves_number_of_rows = true
|
||||
@ -46,10 +46,12 @@ static Block addWindowFunctionResultColumns(const Block & block,
|
||||
WindowStep::WindowStep(
|
||||
const DataStream & input_stream_,
|
||||
const WindowDescription & window_description_,
|
||||
const std::vector<WindowFunctionDescription> & window_functions_)
|
||||
: ITransformingStep(input_stream_, addWindowFunctionResultColumns(input_stream_.header, window_functions_), getTraits())
|
||||
const std::vector<WindowFunctionDescription> & window_functions_,
|
||||
bool streams_fan_out_)
|
||||
: ITransformingStep(input_stream_, addWindowFunctionResultColumns(input_stream_.header, window_functions_), getTraits(!streams_fan_out_))
|
||||
, window_description(window_description_)
|
||||
, window_functions(window_functions_)
|
||||
, streams_fan_out(streams_fan_out_)
|
||||
{
|
||||
// We don't remove any columns, only add, so probably we don't have to update
|
||||
// the output DataStream::distinct_columns.
|
||||
@ -60,6 +62,8 @@ WindowStep::WindowStep(
|
||||
|
||||
void WindowStep::transformPipeline(QueryPipelineBuilder & pipeline, const BuildQueryPipelineSettings &)
|
||||
{
|
||||
auto num_threads = pipeline.getNumThreads();
|
||||
|
||||
// This resize is needed for cases such as `over ()` when we don't have a
|
||||
// sort node, and the input might have multiple streams. The sort node would
|
||||
// have resized it.
|
||||
@ -72,6 +76,11 @@ void WindowStep::transformPipeline(QueryPipelineBuilder & pipeline, const BuildQ
|
||||
input_streams.front().header, output_stream->header, window_description, window_functions);
|
||||
});
|
||||
|
||||
if (streams_fan_out)
|
||||
{
|
||||
pipeline.resize(num_threads);
|
||||
}
|
||||
|
||||
assertBlocksHaveEqualStructure(pipeline.getHeader(), output_stream->header,
|
||||
"WindowStep transform for '" + window_description.window_name + "'");
|
||||
}
|
||||
|
@ -16,7 +16,8 @@ class WindowStep : public ITransformingStep
|
||||
public:
|
||||
explicit WindowStep(const DataStream & input_stream_,
|
||||
const WindowDescription & window_description_,
|
||||
const std::vector<WindowFunctionDescription> & window_functions_);
|
||||
const std::vector<WindowFunctionDescription> & window_functions_,
|
||||
bool streams_fan_out_);
|
||||
|
||||
String getName() const override { return "Window"; }
|
||||
|
||||
@ -32,6 +33,7 @@ private:
|
||||
|
||||
WindowDescription window_description;
|
||||
std::vector<WindowFunctionDescription> window_functions;
|
||||
bool streams_fan_out;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1193,6 +1193,16 @@ bool PredefinedQueryHandler::customizeQueryParam(ContextMutablePtr context, cons
|
||||
return true;
|
||||
}
|
||||
|
||||
if (startsWith(key, QUERY_PARAMETER_NAME_PREFIX))
|
||||
{
|
||||
/// Save name and values of substitution in dictionary.
|
||||
const String parameter_name = key.substr(strlen(QUERY_PARAMETER_NAME_PREFIX));
|
||||
|
||||
if (receive_params.contains(parameter_name))
|
||||
context->setQueryParameter(parameter_name, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -180,7 +180,23 @@ void addDefaultHandlersFactory(
|
||||
return std::make_unique<DynamicQueryHandler>(server, "query");
|
||||
};
|
||||
auto query_handler = std::make_shared<HandlingRuleHTTPHandlerFactory<DynamicQueryHandler>>(std::move(dynamic_creator));
|
||||
query_handler->allowPostAndGetParamsAndOptionsRequest();
|
||||
query_handler->addFilter([](const auto & request)
|
||||
{
|
||||
bool path_matches_get_or_head = startsWith(request.getURI(), "?")
|
||||
|| startsWith(request.getURI(), "/?")
|
||||
|| startsWith(request.getURI(), "/query?");
|
||||
bool is_get_or_head_request = request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET
|
||||
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_HEAD;
|
||||
|
||||
bool path_matches_post_or_options = path_matches_get_or_head
|
||||
|| request.getURI() == "/"
|
||||
|| request.getURI().empty();
|
||||
bool is_post_or_options_request = request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST
|
||||
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_OPTIONS;
|
||||
|
||||
return (path_matches_get_or_head && is_get_or_head_request) || (path_matches_post_or_options && is_post_or_options_request);
|
||||
}
|
||||
);
|
||||
factory.addHandler(query_handler);
|
||||
|
||||
/// We check that prometheus handler will be served on current (default) port.
|
||||
|
@ -98,7 +98,7 @@ static inline auto headersFilter(const Poco::Util::AbstractConfiguration & confi
|
||||
{
|
||||
for (const auto & [header_name, header_expression] : headers_expression)
|
||||
{
|
||||
const auto & header_value = request.get(header_name, "");
|
||||
const auto header_value = request.get(header_name, "");
|
||||
if (!checkExpression(std::string_view(header_value.data(), header_value.size()), header_expression))
|
||||
return false;
|
||||
}
|
||||
|
@ -283,6 +283,7 @@ struct DeltaLakeMetadataParser<Configuration, MetadataReadHelper>::Impl
|
||||
header, "Parquet",
|
||||
format_settings.parquet.allow_missing_columns,
|
||||
/* null_as_default */true,
|
||||
format_settings.date_time_overflow_behavior,
|
||||
/* case_insensitive_column_matching */false);
|
||||
|
||||
Chunk res;
|
||||
|
@ -159,6 +159,13 @@ def test_predefined_query_handler():
|
||||
assert cluster.instance.query("SELECT * FROM test_table") == "100\tTEST\n"
|
||||
cluster.instance.query("DROP TABLE test_table")
|
||||
|
||||
res4 = cluster.instance.http_request(
|
||||
"test_predefined_handler_get?max_threads=1¶m_setting_name=max_threads",
|
||||
method="GET",
|
||||
headers={"XXX": "xxx"},
|
||||
)
|
||||
assert b"max_threads\t1\n" == res1.content
|
||||
|
||||
|
||||
def test_fixed_static_handler():
|
||||
with contextlib.closing(
|
||||
@ -441,6 +448,55 @@ def test_defaults_http_handlers():
|
||||
== cluster.instance.http_request("?query=SELECT+1", method="GET").content
|
||||
)
|
||||
|
||||
assert (
|
||||
404
|
||||
== cluster.instance.http_request(
|
||||
"/nonexistent?query=SELECT+1", method="GET"
|
||||
).status_code
|
||||
)
|
||||
|
||||
|
||||
def test_defaults_http_handlers_config_order():
|
||||
def check_predefined_query_handler():
|
||||
assert (
|
||||
200
|
||||
== cluster.instance.http_request(
|
||||
"?query=SELECT+1", method="GET"
|
||||
).status_code
|
||||
)
|
||||
assert (
|
||||
b"1\n"
|
||||
== cluster.instance.http_request("?query=SELECT+1", method="GET").content
|
||||
)
|
||||
response = cluster.instance.http_request(
|
||||
"test_predefined_handler_get?max_threads=1&setting_name=max_threads",
|
||||
method="GET",
|
||||
headers={"XXX": "xxx"},
|
||||
)
|
||||
assert b"max_threads\t1\n" == response.content
|
||||
assert (
|
||||
"text/tab-separated-values; charset=UTF-8"
|
||||
== response.headers["content-type"]
|
||||
)
|
||||
|
||||
with contextlib.closing(
|
||||
SimpleCluster(
|
||||
ClickHouseCluster(__file__),
|
||||
"defaults_handlers_config_order_first",
|
||||
"test_defaults_handlers_config_order/defaults_first",
|
||||
)
|
||||
) as cluster:
|
||||
check_predefined_query_handler()
|
||||
|
||||
with contextlib.closing(
|
||||
SimpleCluster(
|
||||
ClickHouseCluster(__file__),
|
||||
"defaults_handlers_config_order_first",
|
||||
"test_defaults_handlers_config_order/defaults_last",
|
||||
)
|
||||
) as cluster:
|
||||
check_predefined_query_handler()
|
||||
|
||||
|
||||
def test_prometheus_handler():
|
||||
with contextlib.closing(
|
||||
|
@ -0,0 +1,17 @@
|
||||
|
||||
<clickhouse>
|
||||
<http_server_default_response>Default server response</http_server_default_response>
|
||||
|
||||
<http_handlers>
|
||||
<defaults/>
|
||||
<rule>
|
||||
<methods>GET</methods>
|
||||
<headers><XXX>xxx</XXX></headers>
|
||||
<url>/test_predefined_handler_get</url>
|
||||
<handler>
|
||||
<type>predefined_query_handler</type>
|
||||
<query>SELECT name, value FROM system.settings WHERE name = {setting_name:String}</query>
|
||||
</handler>
|
||||
</rule>
|
||||
</http_handlers>
|
||||
</clickhouse>
|
@ -0,0 +1,17 @@
|
||||
|
||||
<clickhouse>
|
||||
<http_server_default_response>Default server response</http_server_default_response>
|
||||
|
||||
<http_handlers>
|
||||
<rule>
|
||||
<methods>GET</methods>
|
||||
<headers><XXX>xxx</XXX></headers>
|
||||
<url>/test_predefined_handler_get</url>
|
||||
<handler>
|
||||
<type>predefined_query_handler</type>
|
||||
<query>SELECT name, value FROM system.settings WHERE name = {setting_name:String}</query>
|
||||
</handler>
|
||||
</rule>
|
||||
<defaults/>
|
||||
</http_handlers>
|
||||
</clickhouse>
|
@ -30,13 +30,10 @@ def started_cluster():
|
||||
|
||||
def http_works(port=8123):
|
||||
try:
|
||||
response = requests.post(f"http://{main_node.ip_address}:{port}/ping")
|
||||
if response.status_code == 400:
|
||||
return True
|
||||
except:
|
||||
pass
|
||||
|
||||
return False
|
||||
response = requests.get(f"http://{main_node.ip_address}:{port}/ping")
|
||||
return response.status_code == 200
|
||||
except requests.exceptions.ConnectionError:
|
||||
return False
|
||||
|
||||
|
||||
def assert_everything_works():
|
||||
|
22
tests/performance/get_map_value.xml
Normal file
22
tests/performance/get_map_value.xml
Normal file
@ -0,0 +1,22 @@
|
||||
<test>
|
||||
<create_query>
|
||||
CREATE TABLE test_table_map_1 (a Map(String, String)) ENGINE=Memory
|
||||
</create_query>
|
||||
|
||||
<fill_query>insert into test_table_map_1 select CAST((['xyz', 'abc', '123'], [cast(number % 10 as String), 'dsdfsd', '123']), 'Map(String, String)') from numbers(10000000)</fill_query>
|
||||
|
||||
<query>select a['xyz'] from test_table_map_1 Format Null settings max_threads=1</query>
|
||||
<query>select a['123'] from test_table_map_1 Format Null settings max_threads=1</query>
|
||||
|
||||
<drop_query>drop table test_table_map_1</drop_query>
|
||||
|
||||
<create_query>
|
||||
CREATE TABLE test_table_map_2 (a Map(String, String)) ENGINE=Memory
|
||||
</create_query>
|
||||
|
||||
<fill_query>insert into test_table_map_2 select if (number % 2 = 0, CAST((['xyz', 'abc', '123'], [cast(number % 10 as String), 'dsdfsd', '123']), 'Map(String, String)'), CAST((['123', 'abc', 'xyz'], ['123', 'dsdfsd', cast(number % 10 as String)]), 'Map(String, String)')) from numbers(10000000)</fill_query>
|
||||
|
||||
<query>select a['xyz'] from test_table_map_2 Format Null settings max_threads=1</query>
|
||||
|
||||
<drop_query>drop table test_table_map_2</drop_query>
|
||||
</test>
|
@ -0,0 +1,69 @@
|
||||
<test>
|
||||
<create_query>
|
||||
CREATE TABLE
|
||||
window_test(id Int64, value Int64, partition Int64, msg String)
|
||||
Engine=MergeTree
|
||||
ORDER BY id
|
||||
</create_query>
|
||||
|
||||
<fill_query>
|
||||
INSERT INTO window_test
|
||||
SELECT number, rand(1) % 500, number % 3000, randomPrintableASCII(2) FROM numbers(5000000)
|
||||
</fill_query>
|
||||
|
||||
<query>
|
||||
SELECT id,
|
||||
AVG(value) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS frame1,
|
||||
MAX(value) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS frame2,
|
||||
sipHash64(frame1),
|
||||
sipHash64(frame2)
|
||||
FROM window_test
|
||||
</query>
|
||||
|
||||
<query>
|
||||
SELECT id AS key,
|
||||
sipHash64(sum(frame)) AS value
|
||||
FROM (
|
||||
SELECT id,
|
||||
AVG(value) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS frame
|
||||
FROM window_test)
|
||||
GROUP BY key
|
||||
ORDER BY key, value
|
||||
</query>
|
||||
|
||||
<query>
|
||||
SELECT id % 100000 AS key,
|
||||
sipHash64(sum(frame)) AS value
|
||||
FROM (
|
||||
SELECT id,
|
||||
AVG(value) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS frame
|
||||
FROM window_test)
|
||||
GROUP BY key
|
||||
ORDER BY key, value
|
||||
</query>
|
||||
|
||||
<query>
|
||||
WITH 'xxxxyyyyxxxxyyyyxxxxyyyyxxxxyyyy' AS cipherKey
|
||||
SELECT id,
|
||||
AVG(value) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS frame,
|
||||
toString(frame) AS str,
|
||||
encrypt('aes-256-ofb', str, cipherKey) AS enc,
|
||||
decrypt('aes-256-ofb', str, cipherKey) AS dec
|
||||
FROM window_test
|
||||
</query>
|
||||
|
||||
<query>
|
||||
SELECT id,
|
||||
AVG(value) OVER (PARTITION by partition ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS frame
|
||||
FROM window_test
|
||||
ORDER BY id
|
||||
</query>
|
||||
|
||||
<query>
|
||||
SELECT DISTINCT AVG(value) OVER (PARTITION by partition ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS frame
|
||||
FROM window_test
|
||||
ORDER BY frame
|
||||
</query>
|
||||
|
||||
<drop_query>DROP TABLE IF EXISTS window_test</drop_query>
|
||||
</test>
|
@ -1,18 +1,18 @@
|
||||
-- { echo }
|
||||
select row_number() over (order by dummy) from (select * from remote('127.0.0.{1,2}', system, one));
|
||||
select row_number() over (order by dummy) as x from (select * from remote('127.0.0.{1,2}', system, one)) order by x;
|
||||
1
|
||||
2
|
||||
select row_number() over (order by dummy) from remote('127.0.0.{1,2}', system, one);
|
||||
select row_number() over (order by dummy) as x from remote('127.0.0.{1,2}', system, one) order by x;
|
||||
1
|
||||
2
|
||||
select max(identity(dummy + 1)) over () from remote('127.0.0.{1,2}', system, one);
|
||||
select max(identity(dummy + 1)) over () as x from remote('127.0.0.{1,2}', system, one) order by x;
|
||||
1
|
||||
1
|
||||
drop table if exists t_01568;
|
||||
create table t_01568 engine Memory as
|
||||
select intDiv(number, 3) p, modulo(number, 3) o, number
|
||||
from numbers(9);
|
||||
select sum(number) over w, max(number) over w from t_01568 window w as (partition by p);
|
||||
select sum(number) over w as x, max(number) over w as y from t_01568 window w as (partition by p) order by x, y;
|
||||
3 2
|
||||
3 2
|
||||
3 2
|
||||
@ -22,7 +22,7 @@ select sum(number) over w, max(number) over w from t_01568 window w as (partitio
|
||||
21 8
|
||||
21 8
|
||||
21 8
|
||||
select sum(number) over w, max(number) over w from remote('127.0.0.{1,2}', '', t_01568) window w as (partition by p);
|
||||
select sum(number) over w as x, max(number) over w as y from remote('127.0.0.{1,2}', '', t_01568) window w as (partition by p) order by x, y;
|
||||
6 2
|
||||
6 2
|
||||
6 2
|
||||
@ -41,23 +41,23 @@ select sum(number) over w, max(number) over w from remote('127.0.0.{1,2}', '', t
|
||||
42 8
|
||||
42 8
|
||||
42 8
|
||||
select distinct sum(number) over w, max(number) over w from remote('127.0.0.{1,2}', '', t_01568) window w as (partition by p);
|
||||
select distinct sum(number) over w as x, max(number) over w as y from remote('127.0.0.{1,2}', '', t_01568) window w as (partition by p) order by x, y;
|
||||
6 2
|
||||
24 5
|
||||
42 8
|
||||
-- window functions + aggregation w/shards
|
||||
select groupArray(groupArray(number)) over (rows unbounded preceding) from remote('127.0.0.{1,2}', '', t_01568) group by mod(number, 3);
|
||||
select groupArray(groupArray(number)) over (rows unbounded preceding) as x from remote('127.0.0.{1,2}', '', t_01568) group by mod(number, 3) order by x;
|
||||
[[0,3,6,0,3,6]]
|
||||
[[0,3,6,0,3,6],[1,4,7,1,4,7]]
|
||||
[[0,3,6,0,3,6],[1,4,7,1,4,7],[2,5,8,2,5,8]]
|
||||
select groupArray(groupArray(number)) over (rows unbounded preceding) from remote('127.0.0.{1,2}', '', t_01568) group by mod(number, 3) settings distributed_group_by_no_merge=1;
|
||||
select groupArray(groupArray(number)) over (rows unbounded preceding) as x from remote('127.0.0.{1,2}', '', t_01568) group by mod(number, 3) order by x settings distributed_group_by_no_merge=1;
|
||||
[[0,3,6]]
|
||||
[[0,3,6],[1,4,7]]
|
||||
[[0,3,6],[1,4,7],[2,5,8]]
|
||||
[[0,3,6]]
|
||||
[[0,3,6],[1,4,7]]
|
||||
[[0,3,6],[1,4,7],[2,5,8]]
|
||||
select groupArray(groupArray(number)) over (rows unbounded preceding) from remote('127.0.0.{1,2}', '', t_01568) group by mod(number, 3) settings distributed_group_by_no_merge=2; -- { serverError 48 }
|
||||
select groupArray(groupArray(number)) over (rows unbounded preceding) as x from remote('127.0.0.{1,2}', '', t_01568) group by mod(number, 3) order by x settings distributed_group_by_no_merge=2; -- { serverError 48 }
|
||||
-- proper ORDER BY w/window functions
|
||||
select p, o, count() over (partition by p)
|
||||
from remote('127.0.0.{1,2}', '', t_01568)
|
||||
|
@ -1,11 +1,11 @@
|
||||
-- Tags: distributed
|
||||
|
||||
-- { echo }
|
||||
select row_number() over (order by dummy) from (select * from remote('127.0.0.{1,2}', system, one));
|
||||
select row_number() over (order by dummy) as x from (select * from remote('127.0.0.{1,2}', system, one)) order by x;
|
||||
|
||||
select row_number() over (order by dummy) from remote('127.0.0.{1,2}', system, one);
|
||||
select row_number() over (order by dummy) as x from remote('127.0.0.{1,2}', system, one) order by x;
|
||||
|
||||
select max(identity(dummy + 1)) over () from remote('127.0.0.{1,2}', system, one);
|
||||
select max(identity(dummy + 1)) over () as x from remote('127.0.0.{1,2}', system, one) order by x;
|
||||
|
||||
drop table if exists t_01568;
|
||||
|
||||
@ -13,16 +13,16 @@ create table t_01568 engine Memory as
|
||||
select intDiv(number, 3) p, modulo(number, 3) o, number
|
||||
from numbers(9);
|
||||
|
||||
select sum(number) over w, max(number) over w from t_01568 window w as (partition by p);
|
||||
select sum(number) over w as x, max(number) over w as y from t_01568 window w as (partition by p) order by x, y;
|
||||
|
||||
select sum(number) over w, max(number) over w from remote('127.0.0.{1,2}', '', t_01568) window w as (partition by p);
|
||||
select sum(number) over w as x, max(number) over w as y from remote('127.0.0.{1,2}', '', t_01568) window w as (partition by p) order by x, y;
|
||||
|
||||
select distinct sum(number) over w, max(number) over w from remote('127.0.0.{1,2}', '', t_01568) window w as (partition by p);
|
||||
select distinct sum(number) over w as x, max(number) over w as y from remote('127.0.0.{1,2}', '', t_01568) window w as (partition by p) order by x, y;
|
||||
|
||||
-- window functions + aggregation w/shards
|
||||
select groupArray(groupArray(number)) over (rows unbounded preceding) from remote('127.0.0.{1,2}', '', t_01568) group by mod(number, 3);
|
||||
select groupArray(groupArray(number)) over (rows unbounded preceding) from remote('127.0.0.{1,2}', '', t_01568) group by mod(number, 3) settings distributed_group_by_no_merge=1;
|
||||
select groupArray(groupArray(number)) over (rows unbounded preceding) from remote('127.0.0.{1,2}', '', t_01568) group by mod(number, 3) settings distributed_group_by_no_merge=2; -- { serverError 48 }
|
||||
select groupArray(groupArray(number)) over (rows unbounded preceding) as x from remote('127.0.0.{1,2}', '', t_01568) group by mod(number, 3) order by x;
|
||||
select groupArray(groupArray(number)) over (rows unbounded preceding) as x from remote('127.0.0.{1,2}', '', t_01568) group by mod(number, 3) order by x settings distributed_group_by_no_merge=1;
|
||||
select groupArray(groupArray(number)) over (rows unbounded preceding) as x from remote('127.0.0.{1,2}', '', t_01568) group by mod(number, 3) order by x settings distributed_group_by_no_merge=2; -- { serverError 48 }
|
||||
|
||||
-- proper ORDER BY w/window functions
|
||||
select p, o, count() over (partition by p)
|
||||
|
@ -19,7 +19,8 @@ system stop merges order_by_const;
|
||||
INSERT INTO order_by_const(a, b, c, d) VALUES (1, 1, 101, 1), (1, 2, 102, 1), (1, 3, 103, 1), (1, 4, 104, 1);
|
||||
INSERT INTO order_by_const(a, b, c, d) VALUES (1, 5, 104, 1), (1, 6, 105, 1), (2, 1, 106, 2), (2, 1, 107, 2);
|
||||
INSERT INTO order_by_const(a, b, c, d) VALUES (2, 2, 107, 2), (2, 3, 108, 2), (2, 4, 109, 2);
|
||||
SELECT row_number() OVER (order by 1, a) FROM order_by_const;
|
||||
-- output 1 sorted stream
|
||||
SELECT row_number() OVER (order by 1, a) FROM order_by_const SETTINGS query_plan_enable_multithreading_after_window_functions=0;
|
||||
1
|
||||
2
|
||||
3
|
||||
|
@ -20,7 +20,9 @@ system stop merges order_by_const;
|
||||
INSERT INTO order_by_const(a, b, c, d) VALUES (1, 1, 101, 1), (1, 2, 102, 1), (1, 3, 103, 1), (1, 4, 104, 1);
|
||||
INSERT INTO order_by_const(a, b, c, d) VALUES (1, 5, 104, 1), (1, 6, 105, 1), (2, 1, 106, 2), (2, 1, 107, 2);
|
||||
INSERT INTO order_by_const(a, b, c, d) VALUES (2, 2, 107, 2), (2, 3, 108, 2), (2, 4, 109, 2);
|
||||
SELECT row_number() OVER (order by 1, a) FROM order_by_const;
|
||||
|
||||
-- output 1 sorted stream
|
||||
SELECT row_number() OVER (order by 1, a) FROM order_by_const SETTINGS query_plan_enable_multithreading_after_window_functions=0;
|
||||
|
||||
drop table order_by_const;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
const column
|
||||
2021-08-15 18:57:56 1426860702823350272
|
||||
2021-08-15 18:57:56.492 1426860704886947840
|
||||
non-const column
|
||||
2021-08-15 18:57:56 1426860702823350272
|
||||
2021-08-15 18:57:56.492 1426860704886947840
|
||||
-- const / non-const inputs
|
||||
2021-08-15 18:57:56 1426860702823350272 1426860702823350272
|
||||
2021-08-15 18:57:56.492 1426860704886947840 1426860704886947840
|
||||
-- different DateTime64 scales
|
||||
1426981498778550272 1426981500456271872 1426981500833759232 1426981500842147840 1426981500842147840
|
||||
1 1 1 1
|
||||
2023-11-11 11:11:11.1231 2023-11-11 11:11:11.123
|
||||
|
@ -1,23 +1,45 @@
|
||||
SET session_timezone = 'Africa/Juba';
|
||||
|
||||
-- Error cases
|
||||
SELECT dateTimeToSnowflake(); -- {serverError 42}
|
||||
SELECT dateTime64ToSnowflake(); -- {serverError 42}
|
||||
SELECT dateTimeToSnowflake(); -- {serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH}
|
||||
SELECT dateTime64ToSnowflake(); -- {serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH}
|
||||
|
||||
SELECT dateTimeToSnowflake('abc'); -- {serverError 43}
|
||||
SELECT dateTime64ToSnowflake('abc'); -- {serverError 43}
|
||||
SELECT dateTimeToSnowflake('abc'); -- {serverError ILLEGAL_TYPE_OF_ARGUMENT}
|
||||
SELECT dateTime64ToSnowflake('abc'); -- {serverError ILLEGAL_TYPE_OF_ARGUMENT}
|
||||
|
||||
SELECT dateTimeToSnowflake('abc', 123); -- {serverError 42}
|
||||
SELECT dateTime64ToSnowflake('abc', 123); -- {serverError 42}
|
||||
SELECT dateTimeToSnowflake('abc', 123); -- {serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH}
|
||||
SELECT dateTime64ToSnowflake('abc', 123); -- {serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH}
|
||||
|
||||
SELECT '-- const / non-const inputs';
|
||||
|
||||
SELECT 'const column';
|
||||
WITH toDateTime('2021-08-15 18:57:56', 'Asia/Shanghai') AS dt
|
||||
SELECT dt, dateTimeToSnowflake(dt);
|
||||
SELECT dt, dateTimeToSnowflake(dt), materialize(dateTimeToSnowflake(dt));
|
||||
|
||||
WITH toDateTime64('2021-08-15 18:57:56.492', 3, 'Asia/Shanghai') AS dt64
|
||||
SELECT dt64, dateTime64ToSnowflake(dt64);
|
||||
SELECT dt64, dateTime64ToSnowflake(dt64), materialize(dateTime64ToSnowflake(dt64));
|
||||
|
||||
SELECT 'non-const column';
|
||||
WITH toDateTime('2021-08-15 18:57:56', 'Asia/Shanghai') AS x
|
||||
SELECT materialize(x) as dt, dateTimeToSnowflake(dt);;
|
||||
SELECT '-- different DateTime64 scales';
|
||||
|
||||
WITH toDateTime64('2021-08-15 18:57:56.492', 3, 'Asia/Shanghai') AS x
|
||||
SELECT materialize(x) as dt64, dateTime64ToSnowflake(dt64);
|
||||
WITH toDateTime64('2021-08-15 18:57:56.492', 0, 'UTC') AS dt64_0,
|
||||
toDateTime64('2021-08-15 18:57:56.492', 1, 'UTC') AS dt64_1,
|
||||
toDateTime64('2021-08-15 18:57:56.492', 2, 'UTC') AS dt64_2,
|
||||
toDateTime64('2021-08-15 18:57:56.492', 3, 'UTC') AS dt64_3,
|
||||
toDateTime64('2021-08-15 18:57:56.492', 4, 'UTC') AS dt64_4
|
||||
SELECT dateTime64ToSnowflake(dt64_0),
|
||||
dateTime64ToSnowflake(dt64_1),
|
||||
dateTime64ToSnowflake(dt64_2),
|
||||
dateTime64ToSnowflake(dt64_3),
|
||||
dateTime64ToSnowflake(dt64_4);
|
||||
|
||||
-- DateTime64-to-Snowflake-to-DateTime64 is idempotent *if* the scale is <=3 (millisecond precision)
|
||||
WITH now64(0, 'UTC') AS dt64_0,
|
||||
now64(1, 'UTC') AS dt64_1,
|
||||
now64(2, 'UTC') AS dt64_2,
|
||||
now64(3, 'UTC') AS dt64_3
|
||||
SELECT snowflakeToDateTime64(dateTime64ToSnowflake(dt64_0), 'UTC') == dt64_0,
|
||||
snowflakeToDateTime64(dateTime64ToSnowflake(dt64_1), 'UTC') == dt64_1,
|
||||
snowflakeToDateTime64(dateTime64ToSnowflake(dt64_2), 'UTC') == dt64_2,
|
||||
snowflakeToDateTime64(dateTime64ToSnowflake(dt64_3), 'UTC') == dt64_3;
|
||||
|
||||
WITH toDateTime64('2023-11-11 11:11:11.1231', 4, 'UTC') AS dt64_4
|
||||
SELECT dt64_4, snowflakeToDateTime64(dateTime64ToSnowflake(dt64_4), 'UTC'); -- not idempotent
|
||||
|
@ -1,12 +1,12 @@
|
||||
-- -- Error cases
|
||||
SELECT snowflakeToDateTime(); -- {serverError 42}
|
||||
SELECT snowflakeToDateTime64(); -- {serverError 42}
|
||||
SELECT snowflakeToDateTime(); -- {serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH}
|
||||
SELECT snowflakeToDateTime64(); -- {serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH}
|
||||
|
||||
SELECT snowflakeToDateTime('abc'); -- {serverError 43}
|
||||
SELECT snowflakeToDateTime64('abc'); -- {serverError 43}
|
||||
SELECT snowflakeToDateTime('abc'); -- {serverError ILLEGAL_TYPE_OF_ARGUMENT}
|
||||
SELECT snowflakeToDateTime64('abc'); -- {serverError ILLEGAL_TYPE_OF_ARGUMENT}
|
||||
|
||||
SELECT snowflakeToDateTime('abc', 123); -- {serverError 43}
|
||||
SELECT snowflakeToDateTime64('abc', 123); -- {serverError 43}
|
||||
SELECT snowflakeToDateTime('abc', 123); -- {serverError ILLEGAL_TYPE_OF_ARGUMENT}
|
||||
SELECT snowflakeToDateTime64('abc', 123); -- {serverError ILLEGAL_TYPE_OF_ARGUMENT}
|
||||
|
||||
SELECT 'const column';
|
||||
WITH
|
||||
|
@ -14,7 +14,7 @@ def main():
|
||||
sock = socket(AF_INET, SOCK_STREAM)
|
||||
sock.connect((host, port))
|
||||
sock.settimeout(60)
|
||||
s = "POST /play HTTP/1.1\r\n"
|
||||
s = "POST / HTTP/1.1\r\n"
|
||||
s += "Host: %s\r\n" % host
|
||||
s += "Content-type: multipart/form-data\r\n"
|
||||
s += "Transfer-encoding: chunked\r\n"
|
||||
|
19
tests/queries/0_stateless/02882_formatQuery.reference
Normal file
19
tests/queries/0_stateless/02882_formatQuery.reference
Normal file
@ -0,0 +1,19 @@
|
||||
SELECT 1
|
||||
SELECT 1
|
||||
SELECT 1
|
||||
SELECT 1
|
||||
1
|
||||
INSERT INTO tab FORMAT Values
|
||||
CREATE TABLE default.no_prop_table\n(\n `some_column` UInt64\n)\nENGINE = MergeTree\nORDER BY tuple()\nSETTINGS index_granularity = 8192
|
||||
EXPLAIN SYNTAX\nSELECT\n CAST(1, \'INT\'),\n CEIL(1),\n CEILING(1),\n CHAR(49),\n CHAR_LENGTH(\'1\'),\n CHARACTER_LENGTH(\'1\'),\n COALESCE(1),\n CONCAT(\'1\', \'1\'),\n CORR(1, 1),\n COS(1),\n COUNT(1),\n COVAR_POP(1, 1),\n COVAR_SAMP(1, 1),\n DATABASE(),\n SCHEMA(),\n dateDiff(\'DAY\', toDate(\'2020-10-24\'), toDate(\'2019-10-24\')),\n EXP(1),\n FLATTEN([[1]]),\n FLOOR(1),\n FQDN(),\n GREATEST(1),\n IF(1, 1, 1),\n IFNULL(1, 1),\n LCASE(\'A\'),\n LEAST(1),\n LENGTH(\'1\'),\n LN(1),\n LOCATE(\'1\', \'1\'),\n LOG(1),\n LOG10(1),\n LOG2(1),\n LOWER(\'A\'),\n MAX(1),\n MID(\'123\', 1, 1),\n MIN(1),\n MOD(1, 1),\n NOT 1,\n NOW(),\n NOW64(),\n NULLIF(1, 1),\n PI(),\n position(\'123\', \'2\'),\n POW(1, 1),\n POWER(1, 1),\n RAND(),\n REPLACE(\'1\', \'1\', \'2\'),\n REVERSE(\'123\'),\n ROUND(1),\n SIN(1),\n SQRT(1),\n STDDEV_POP(1),\n STDDEV_SAMP(1),\n SUBSTR(\'123\', 2),\n substring(\'123\', 2),\n SUM(1),\n TAN(1),\n TANH(1),\n TRUNC(1),\n TRUNCATE(1),\n UCASE(\'A\'),\n UPPER(\'A\'),\n USER(),\n VAR_POP(1),\n VAR_SAMP(1),\n WEEK(toDate(\'2020-10-24\')),\n YEARWEEK(toDate(\'2020-10-24\'))\nFORMAT TSVRaw
|
||||
1
|
||||
formatQuerySingleLine
|
||||
SELECT 1
|
||||
SELECT 1
|
||||
SELECT 1
|
||||
SELECT 1
|
||||
1
|
||||
INSERT INTO tab FORMAT Values
|
||||
CREATE TABLE default.no_prop_table (`some_column` UInt64) ENGINE = MergeTree ORDER BY tuple() SETTINGS index_granularity = 8192
|
||||
EXPLAIN SYNTAX SELECT CAST(1, \'INT\'), CEIL(1), CEILING(1), CHAR(49), CHAR_LENGTH(\'1\'), CHARACTER_LENGTH(\'1\'), COALESCE(1), CONCAT(\'1\', \'1\'), CORR(1, 1), COS(1), COUNT(1), COVAR_POP(1, 1), COVAR_SAMP(1, 1), DATABASE(), SCHEMA(), dateDiff(\'DAY\', toDate(\'2020-10-24\'), toDate(\'2019-10-24\')), EXP(1), FLATTEN([[1]]), FLOOR(1), FQDN(), GREATEST(1), IF(1, 1, 1), IFNULL(1, 1), LCASE(\'A\'), LEAST(1), LENGTH(\'1\'), LN(1), LOCATE(\'1\', \'1\'), LOG(1), LOG10(1), LOG2(1), LOWER(\'A\'), MAX(1), MID(\'123\', 1, 1), MIN(1), MOD(1, 1), NOT 1, NOW(), NOW64(), NULLIF(1, 1), PI(), position(\'123\', \'2\'), POW(1, 1), POWER(1, 1), RAND(), REPLACE(\'1\', \'1\', \'2\'), REVERSE(\'123\'), ROUND(1), SIN(1), SQRT(1), STDDEV_POP(1), STDDEV_SAMP(1), SUBSTR(\'123\', 2), substring(\'123\', 2), SUM(1), TAN(1), TANH(1), TRUNC(1), TRUNCATE(1), UCASE(\'A\'), UPPER(\'A\'), USER(), VAR_POP(1), VAR_SAMP(1), WEEK(toDate(\'2020-10-24\')), YEARWEEK(toDate(\'2020-10-24\')) FORMAT TSVRaw
|
||||
1
|
21
tests/queries/0_stateless/02882_formatQuery.sql
Normal file
21
tests/queries/0_stateless/02882_formatQuery.sql
Normal file
@ -0,0 +1,21 @@
|
||||
SELECT formatQuery('select 1;');
|
||||
SELECT formatQuery('select 1');
|
||||
SELECT formatQuery('SELECT 1;');
|
||||
SELECT formatQuery('SELECT 1');
|
||||
SELECT formatQuery('select 1;') == formatQuery('SeLecT 1');
|
||||
SELECT formatQuery('INSERT INTO tab VALUES (\'\') (\'test\')');
|
||||
SELECT formatQuery('CREATE TABLE default.no_prop_table(`some_column` UInt64) ENGINE = MergeTree ORDER BY tuple() SETTINGS index_granularity = 8192');
|
||||
SELECT formatQuery('EXPLAIN SYNTAX SELECT CAST(1 AS INT), CEIL(1), CEILING(1), CHAR(49), CHAR_LENGTH(\'1\'), CHARACTER_LENGTH(\'1\'), COALESCE(1), CONCAT(\'1\', \'1\'), CORR(1, 1), COS(1), COUNT(1), COVAR_POP(1, 1), COVAR_SAMP(1, 1), DATABASE(), SCHEMA(), DATEDIFF(\'DAY\', toDate(\'2020-10-24\'), toDate(\'2019-10-24\')), EXP(1), FLATTEN([[1]]), FLOOR(1), FQDN(), GREATEST(1), IF(1, 1, 1), IFNULL(1, 1), LCASE(\'A\'), LEAST(1), LENGTH(\'1\'), LN(1), LOCATE(\'1\', \'1\'), LOG(1), LOG10(1), LOG2(1), LOWER(\'A\'), MAX(1), MID(\'123\', 1, 1), MIN(1), MOD(1, 1), NOT(1), NOW(), NOW64(), NULLIF(1, 1), PI(), POSITION(\'123\', \'2\'), POW(1, 1), POWER(1, 1), RAND(), REPLACE(\'1\', \'1\', \'2\'), REVERSE(\'123\'), ROUND(1), SIN(1), SQRT(1), STDDEV_POP(1), STDDEV_SAMP(1), SUBSTR(\'123\', 2), SUBSTRING(\'123\', 2), SUM(1), TAN(1), TANH(1), TRUNC(1), TRUNCATE(1), UCASE(\'A\'), UPPER(\'A\'), USER(), VAR_POP(1), VAR_SAMP(1), WEEK(toDate(\'2020-10-24\')), YEARWEEK(toDate(\'2020-10-24\')) format TSVRaw;');
|
||||
SELECT normalizedQueryHash(formatQuery('select 1')) = normalizedQueryHash(formatQuery('SELECT 1'));
|
||||
SELECT formatQuery('SEECTwrong'); -- { serverError SYNTAX_ERROR }
|
||||
SELECT 'formatQuerySingleLine';
|
||||
SELECT formatQuerySingleLine('select 1;');
|
||||
SELECT formatQuerySingleLine('select 1');
|
||||
SELECT formatQuerySingleLine('SELECT 1;');
|
||||
SELECT formatQuerySingleLine('SELECT 1');
|
||||
SELECT formatQuerySingleLine('select 1;') == formatQuerySingleLine('SeLecT 1');
|
||||
SELECT formatQuerySingleLine('INSERT INTO tab VALUES (\'\') (\'test\')');
|
||||
SELECT formatQuerySingleLine('CREATE TABLE default.no_prop_table(`some_column` UInt64) ENGINE = MergeTree ORDER BY tuple() SETTINGS index_granularity = 8192');
|
||||
SELECT formatQuerySingleLine('EXPLAIN SYNTAX SELECT CAST(1 AS INT), CEIL(1), CEILING(1), CHAR(49), CHAR_LENGTH(\'1\'), CHARACTER_LENGTH(\'1\'), COALESCE(1), CONCAT(\'1\', \'1\'), CORR(1, 1), COS(1), COUNT(1), COVAR_POP(1, 1), COVAR_SAMP(1, 1), DATABASE(), SCHEMA(), DATEDIFF(\'DAY\', toDate(\'2020-10-24\'), toDate(\'2019-10-24\')), EXP(1), FLATTEN([[1]]), FLOOR(1), FQDN(), GREATEST(1), IF(1, 1, 1), IFNULL(1, 1), LCASE(\'A\'), LEAST(1), LENGTH(\'1\'), LN(1), LOCATE(\'1\', \'1\'), LOG(1), LOG10(1), LOG2(1), LOWER(\'A\'), MAX(1), MID(\'123\', 1, 1), MIN(1), MOD(1, 1), NOT(1), NOW(), NOW64(), NULLIF(1, 1), PI(), POSITION(\'123\', \'2\'), POW(1, 1), POWER(1, 1), RAND(), REPLACE(\'1\', \'1\', \'2\'), REVERSE(\'123\'), ROUND(1), SIN(1), SQRT(1), STDDEV_POP(1), STDDEV_SAMP(1), SUBSTR(\'123\', 2), SUBSTRING(\'123\', 2), SUM(1), TAN(1), TANH(1), TRUNC(1), TRUNCATE(1), UCASE(\'A\'), UPPER(\'A\'), USER(), VAR_POP(1), VAR_SAMP(1), WEEK(toDate(\'2020-10-24\')), YEARWEEK(toDate(\'2020-10-24\')) format TSVRaw;');
|
||||
SELECT normalizedQueryHash(formatQuerySingleLine('select 1')) = normalizedQueryHash(formatQuerySingleLine('SELECT 1'));
|
||||
SELECT formatQuerySingleLine('SEECTwrong'); -- { serverError SYNTAX_ERROR }
|
@ -0,0 +1,23 @@
|
||||
ignore
|
||||
2036-02-07 06:28:16
|
||||
2027-10-18 11:03:27
|
||||
2036-02-07 06:28:16
|
||||
2027-10-17 11:03:28
|
||||
2013-04-29 17:31:44
|
||||
2079-06-07
|
||||
1970-01-01
|
||||
2120-07-26
|
||||
2079-06-07
|
||||
2120-07-26
|
||||
No output on `throw`
|
||||
saturate
|
||||
1970-01-01 00:00:00
|
||||
2106-02-07 06:28:15
|
||||
1970-01-01 00:00:00
|
||||
2106-02-07 00:00:00
|
||||
2106-02-07 00:00:00
|
||||
1970-01-01
|
||||
2149-06-06
|
||||
2149-06-06
|
||||
1970-01-01
|
||||
2149-06-06
|
50
tests/queries/0_stateless/02900_date_time_check_overflow.sql
Normal file
50
tests/queries/0_stateless/02900_date_time_check_overflow.sql
Normal file
@ -0,0 +1,50 @@
|
||||
SET session_timezone = 'UTC';
|
||||
|
||||
SELECT 'ignore';
|
||||
SET date_time_overflow_behavior = 'ignore';
|
||||
SELECT toDateTime(toDateTime64('1900-01-01 00:00:00.123', 3));
|
||||
SELECT toDateTime(toDateTime64('2299-12-31 23:59:59.999', 3));
|
||||
|
||||
SELECT toDateTime(toDate32('1900-01-01'));
|
||||
SELECT toDateTime(toDate32('2299-12-31'));
|
||||
|
||||
SELECT toDateTime(toDate('2149-06-06'));
|
||||
|
||||
SELECT toDate(toDateTime64('1900-01-01 00:00:00.123', 3));
|
||||
SELECT toDate(toDateTime64('2149-06-07 00:00:00.123', 3));
|
||||
SELECT toDate(toDateTime64('2299-12-31 23:59:59.999', 3));
|
||||
|
||||
SELECT toDate(toDate32('1900-01-01'));
|
||||
SELECT toDate(toDate32('2299-12-31'));
|
||||
|
||||
|
||||
SELECT 'No output on `throw`';
|
||||
SET date_time_overflow_behavior = 'throw';
|
||||
SELECT toDateTime(toDateTime64('1900-01-01 00:00:00.123', 3)); -- { serverError VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE }
|
||||
SELECT toDateTime(toDateTime64('2299-12-31 23:59:59.999', 3)); -- { serverError VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE }
|
||||
SELECT toDateTime(toDate32('1900-01-01')); -- { serverError VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE }
|
||||
SELECT toDateTime(toDate32('2299-12-31')); -- { serverError VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE }
|
||||
SELECT toDateTime(toDate('2149-06-06')); -- { serverError VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE }
|
||||
SELECT toDate(toDateTime64('1900-01-01 00:00:00.123', 3)); -- { serverError VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE }
|
||||
SELECT toDate(toDateTime64('2299-12-31 23:59:59.999', 3)); -- { serverError VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE }
|
||||
SELECT toDate(toDate32('1900-01-01')); -- { serverError VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE }
|
||||
SELECT toDate(toDate32('2299-12-31')); -- { serverError VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE }
|
||||
|
||||
|
||||
SELECT 'saturate';
|
||||
SET date_time_overflow_behavior = 'saturate';
|
||||
|
||||
SELECT toDateTime(toDateTime64('1900-01-01 00:00:00.123', 3));
|
||||
SELECT toDateTime(toDateTime64('2299-12-31 23:59:59.999', 3));
|
||||
|
||||
SELECT toDateTime(toDate32('1900-01-01'));
|
||||
SELECT toDateTime(toDate32('2299-12-31'));
|
||||
|
||||
SELECT toDateTime(toDate('2149-06-06'));
|
||||
|
||||
SELECT toDate(toDateTime64('1900-01-01 00:00:00.123', 3));
|
||||
SELECT toDate(toDateTime64('2149-06-07 00:00:00.123', 3));
|
||||
SELECT toDate(toDateTime64('2299-12-31 23:59:59.999', 3));
|
||||
|
||||
SELECT toDate(toDate32('1900-01-01'));
|
||||
SELECT toDate(toDate32('2299-12-31'));
|
@ -1479,6 +1479,8 @@ fmtlib
|
||||
formatDateTime
|
||||
formatDateTimeInJoda
|
||||
formatDateTimeInJodaSyntax
|
||||
formatQuery
|
||||
formatQuerySingleLine
|
||||
formatReadableDecimalSize
|
||||
formatReadableQuantity
|
||||
formatReadableSize
|
||||
|
Loading…
Reference in New Issue
Block a user