mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 23:21:59 +00:00
Merge branch 'master' into dynamic-constraints
This commit is contained in:
commit
e0ae648b1c
@ -16,3 +16,6 @@
|
||||
|
||||
# Applied Black formatter for Python code
|
||||
e6f5a3f98b21ba99cf274a9833797889e020a2b3
|
||||
|
||||
# Enabling clang-tidy readability-else-no-return rule
|
||||
67c1e89d90ef576e62f8b1c68269742a3c6f9b1e
|
||||
|
@ -110,8 +110,7 @@ struct DecomposedFloat
|
||||
{
|
||||
if (!isNegative())
|
||||
return rhs > 0 ? -1 : 1;
|
||||
else
|
||||
return rhs >= 0 ? -1 : 1;
|
||||
return rhs >= 0 ? -1 : 1;
|
||||
}
|
||||
|
||||
/// The case of the most negative integer
|
||||
@ -128,8 +127,7 @@ struct DecomposedFloat
|
||||
|
||||
if (mantissa() == 0)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -169,9 +167,8 @@ struct DecomposedFloat
|
||||
/// Float has no fractional part means that the numbers are equal.
|
||||
if (large_and_always_integer || (mantissa() & ((1ULL << (Traits::mantissa_bits - normalizedExponent())) - 1)) == 0)
|
||||
return 0;
|
||||
else
|
||||
/// Float has fractional part means its abs value is larger.
|
||||
return isNegative() ? -1 : 1;
|
||||
/// Float has fractional part means its abs value is larger.
|
||||
return isNegative() ? -1 : 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -205,8 +205,7 @@ JSON::ElementType JSON::getType() const
|
||||
Pos after_string = skipString();
|
||||
if (after_string < ptr_end && *after_string == ':')
|
||||
return TYPE_NAME_VALUE_PAIR;
|
||||
else
|
||||
return TYPE_STRING;
|
||||
return TYPE_STRING;
|
||||
}
|
||||
default:
|
||||
throw JSONException(std::string("JSON: unexpected char ") + *ptr_begin + ", expected one of '{[tfn-0123456789\"'");
|
||||
@ -474,8 +473,7 @@ JSON::Pos JSON::searchField(const char * data, size_t size) const
|
||||
|
||||
if (it == end())
|
||||
return nullptr;
|
||||
else
|
||||
return it->data();
|
||||
return it->data();
|
||||
}
|
||||
|
||||
|
||||
@ -487,7 +485,7 @@ bool JSON::hasEscapes() const
|
||||
|
||||
if (*pos == '"')
|
||||
return false;
|
||||
else if (*pos == '\\')
|
||||
if (*pos == '\\')
|
||||
return true;
|
||||
throw JSONException("JSON: unexpected end of data.");
|
||||
}
|
||||
@ -503,7 +501,7 @@ bool JSON::hasSpecialChars() const
|
||||
|
||||
if (*pos == '"')
|
||||
return false;
|
||||
else if (pos < ptr_end)
|
||||
if (pos < ptr_end)
|
||||
return true;
|
||||
throw JSONException("JSON: unexpected end of data.");
|
||||
}
|
||||
@ -682,10 +680,9 @@ double JSON::toDouble() const
|
||||
|
||||
if (type == TYPE_NUMBER)
|
||||
return getDouble();
|
||||
else if (type == TYPE_STRING)
|
||||
if (type == TYPE_STRING)
|
||||
return JSON(ptr_begin + 1, ptr_end, level + 1).getDouble();
|
||||
else
|
||||
throw JSONException("JSON: cannot convert value to double.");
|
||||
throw JSONException("JSON: cannot convert value to double.");
|
||||
}
|
||||
|
||||
Int64 JSON::toInt() const
|
||||
@ -694,10 +691,9 @@ Int64 JSON::toInt() const
|
||||
|
||||
if (type == TYPE_NUMBER)
|
||||
return getInt();
|
||||
else if (type == TYPE_STRING)
|
||||
if (type == TYPE_STRING)
|
||||
return JSON(ptr_begin + 1, ptr_end, level + 1).getInt();
|
||||
else
|
||||
throw JSONException("JSON: cannot convert value to signed integer.");
|
||||
throw JSONException("JSON: cannot convert value to signed integer.");
|
||||
}
|
||||
|
||||
UInt64 JSON::toUInt() const
|
||||
@ -706,10 +702,9 @@ UInt64 JSON::toUInt() const
|
||||
|
||||
if (type == TYPE_NUMBER)
|
||||
return getUInt();
|
||||
else if (type == TYPE_STRING)
|
||||
if (type == TYPE_STRING)
|
||||
return JSON(ptr_begin + 1, ptr_end, level + 1).getUInt();
|
||||
else
|
||||
throw JSONException("JSON: cannot convert value to unsigned integer.");
|
||||
throw JSONException("JSON: cannot convert value to unsigned integer.");
|
||||
}
|
||||
|
||||
std::string JSON::toString() const
|
||||
@ -718,11 +713,9 @@ std::string JSON::toString() const
|
||||
|
||||
if (type == TYPE_STRING)
|
||||
return getString();
|
||||
else
|
||||
{
|
||||
Pos pos = skipElement();
|
||||
return std::string(ptr_begin, pos - ptr_begin);
|
||||
}
|
||||
|
||||
Pos pos = skipElement();
|
||||
return std::string(ptr_begin, pos - ptr_begin);
|
||||
}
|
||||
|
||||
|
||||
|
@ -203,9 +203,7 @@ T JSON::getWithDefault(const std::string & key, const T & default_) const
|
||||
|
||||
if (key_json.isType<T>())
|
||||
return key_json.get<T>();
|
||||
else
|
||||
return default_;
|
||||
}
|
||||
else
|
||||
return default_;
|
||||
}
|
||||
return default_;
|
||||
}
|
||||
|
@ -151,19 +151,19 @@ inline bool memequalWide(const char * p1, const char * p2, size_t size)
|
||||
return unalignedLoad<uint64_t>(p1) == unalignedLoad<uint64_t>(p2)
|
||||
&& unalignedLoad<uint64_t>(p1 + size - 8) == unalignedLoad<uint64_t>(p2 + size - 8);
|
||||
}
|
||||
else if (size >= 4)
|
||||
if (size >= 4)
|
||||
{
|
||||
/// Chunks of 4..7 bytes.
|
||||
return unalignedLoad<uint32_t>(p1) == unalignedLoad<uint32_t>(p2)
|
||||
&& unalignedLoad<uint32_t>(p1 + size - 4) == unalignedLoad<uint32_t>(p2 + size - 4);
|
||||
}
|
||||
else if (size >= 2)
|
||||
if (size >= 2)
|
||||
{
|
||||
/// Chunks of 2..3 bytes.
|
||||
return unalignedLoad<uint16_t>(p1) == unalignedLoad<uint16_t>(p2)
|
||||
&& unalignedLoad<uint16_t>(p1 + size - 2) == unalignedLoad<uint16_t>(p2 + size - 2);
|
||||
}
|
||||
else if (size >= 1)
|
||||
if (size >= 1)
|
||||
{
|
||||
/// A single byte.
|
||||
return *p1 == *p2;
|
||||
|
@ -53,10 +53,9 @@ void argsToConfig(const Poco::Util::Application::ArgVec & argv,
|
||||
key = arg.substr(key_start);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
key = "";
|
||||
}
|
||||
|
||||
key = "";
|
||||
|
||||
|
||||
if (key_start == std::string::npos)
|
||||
continue;
|
||||
|
@ -330,9 +330,8 @@ inline const char * find_first_symbols_dispatch(const char * begin, const char *
|
||||
#if defined(__SSE4_2__)
|
||||
if (sizeof...(symbols) >= 5)
|
||||
return find_first_symbols_sse42<positive, return_mode, sizeof...(symbols), symbols...>(begin, end);
|
||||
else
|
||||
#endif
|
||||
return find_first_symbols_sse2<positive, return_mode, symbols...>(begin, end);
|
||||
return find_first_symbols_sse2<positive, return_mode, symbols...>(begin, end);
|
||||
}
|
||||
|
||||
template <bool positive, ReturnMode return_mode>
|
||||
@ -341,9 +340,8 @@ inline const char * find_first_symbols_dispatch(const std::string_view haystack,
|
||||
#if defined(__SSE4_2__)
|
||||
if (symbols.str.size() >= 5)
|
||||
return find_first_symbols_sse42<positive, return_mode>(haystack.begin(), haystack.end(), symbols);
|
||||
else
|
||||
#endif
|
||||
return find_first_symbols_sse2<positive, return_mode>(haystack.begin(), haystack.end(), symbols.str.data(), symbols.str.size());
|
||||
return find_first_symbols_sse2<positive, return_mode>(haystack.begin(), haystack.end(), symbols.str.data(), symbols.str.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -33,8 +33,7 @@ std::optional<uint64_t> getCgroupsV2MemoryLimit()
|
||||
uint64_t value;
|
||||
if (setting_file >> value)
|
||||
return {value};
|
||||
else
|
||||
return {}; /// e.g. the cgroups default "max"
|
||||
return {}; /// e.g. the cgroups default "max"
|
||||
}
|
||||
current_cgroup = current_cgroup.parent_path();
|
||||
}
|
||||
|
49
docs/changelogs/v24.3.12.75-lts.md
Normal file
49
docs/changelogs/v24.3.12.75-lts.md
Normal file
@ -0,0 +1,49 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
sidebar_label: 2024
|
||||
---
|
||||
|
||||
# 2024 Changelog
|
||||
|
||||
### ClickHouse release v24.3.12.75-lts (7cb5dff8019) FIXME as compared to v24.3.11.7-lts (28795d0a47e)
|
||||
|
||||
#### Improvement
|
||||
* Backported in [#69607](https://github.com/ClickHouse/ClickHouse/issues/69607): Improved memory accounting for cgroups v2 to exclude the amount occupied by the page cache. [#65470](https://github.com/ClickHouse/ClickHouse/pull/65470) ([Nikita Taranov](https://github.com/nickitat)).
|
||||
|
||||
#### Bug Fix (user-visible misbehavior in an official stable release)
|
||||
* Backported in [#69785](https://github.com/ClickHouse/ClickHouse/issues/69785): Fix attaching table when pg dbname contains "-" in MaterializedPostgreSQL. [#62730](https://github.com/ClickHouse/ClickHouse/pull/62730) ([takakawa](https://github.com/takakawa)).
|
||||
* Backported in [#69461](https://github.com/ClickHouse/ClickHouse/issues/69461): Fix expiration in `RoleCache`. [#67748](https://github.com/ClickHouse/ClickHouse/pull/67748) ([Vitaly Baranov](https://github.com/vitlibar)).
|
||||
* Backported in [#68217](https://github.com/ClickHouse/ClickHouse/issues/68217): Fixed a NULL pointer dereference, triggered by a specially crafted query, that crashed the server via hopEnd, hopStart, tumbleEnd, and tumbleStart. [#68098](https://github.com/ClickHouse/ClickHouse/pull/68098) ([Salvatore Mesoraca](https://github.com/aiven-sal)).
|
||||
* Backported in [#69437](https://github.com/ClickHouse/ClickHouse/issues/69437): After unexpected restart, fail to start replication of ReplicatedMergeTree due to abnormal handling of covered-by-broken part. [#68584](https://github.com/ClickHouse/ClickHouse/pull/68584) ([baolin](https://github.com/baolinhuang)).
|
||||
* Backported in [#69827](https://github.com/ClickHouse/ClickHouse/issues/69827): Make `ColumnsDescription::toString` format each column using the same `IAST::FormatState object`. This results in uniform columns metadata being written to disk and ZooKeeper. [#68733](https://github.com/ClickHouse/ClickHouse/pull/68733) ([Miсhael Stetsyuk](https://github.com/mstetsyuk)).
|
||||
* Backported in [#69294](https://github.com/ClickHouse/ClickHouse/issues/69294): Fix merging of aggregated data for grouping sets. [#68744](https://github.com/ClickHouse/ClickHouse/pull/68744) ([Nikolai Kochetov](https://github.com/KochetovNicolai)).
|
||||
* Backported in [#70470](https://github.com/ClickHouse/ClickHouse/issues/70470): Fix inf loop after `restore replica` in the replicated merge tree with zero copy. [#69293](https://github.com/ClickHouse/ClickHouse/pull/69293) ([MikhailBurdukov](https://github.com/MikhailBurdukov)).
|
||||
* Backported in [#69456](https://github.com/ClickHouse/ClickHouse/issues/69456): Fix undefined behavior when all connection attempts fail getting a connection for insertions. [#69390](https://github.com/ClickHouse/ClickHouse/pull/69390) ([Pablo Marcos](https://github.com/pamarcos)).
|
||||
* Backported in [#69497](https://github.com/ClickHouse/ClickHouse/issues/69497): Fixed a `LOGICAL_ERROR` with function `sqidDecode` ([#69450](https://github.com/ClickHouse/ClickHouse/issues/69450)). [#69451](https://github.com/ClickHouse/ClickHouse/pull/69451) ([Robert Schulze](https://github.com/rschu1ze)).
|
||||
* Backported in [#69724](https://github.com/ClickHouse/ClickHouse/issues/69724): Keep original order of conditions during move to prewhere. Previously the order could change and it could lead to failing queries when the order is important. [#69560](https://github.com/ClickHouse/ClickHouse/pull/69560) ([Pavel Kruglov](https://github.com/Avogar)).
|
||||
* Backported in [#69668](https://github.com/ClickHouse/ClickHouse/issues/69668): Fix Keeper multi-request preprocessing after ZNOAUTH error. [#69627](https://github.com/ClickHouse/ClickHouse/pull/69627) ([Antonio Andelic](https://github.com/antonio2368)).
|
||||
* Backported in [#69792](https://github.com/ClickHouse/ClickHouse/issues/69792): Make getHyperrectangleForRowGroup not throw an exception when the data type in parquet file is not convertable into the requested data type. Solved the user's problem when the Parquet file had Decimal64 data type and the column data type was DateTime. [#69745](https://github.com/ClickHouse/ClickHouse/pull/69745) ([Miсhael Stetsyuk](https://github.com/mstetsyuk)).
|
||||
* Backported in [#70089](https://github.com/ClickHouse/ClickHouse/issues/70089): Now SQL security will work with parameterized views correctly. [#69984](https://github.com/ClickHouse/ClickHouse/pull/69984) ([pufit](https://github.com/pufit)).
|
||||
* Backported in [#70077](https://github.com/ClickHouse/ClickHouse/issues/70077): Closes [#69752](https://github.com/ClickHouse/ClickHouse/issues/69752). [#69985](https://github.com/ClickHouse/ClickHouse/pull/69985) ([pufit](https://github.com/pufit)).
|
||||
* Backported in [#70162](https://github.com/ClickHouse/ClickHouse/issues/70162): Fix wrong LOGICAL_ERROR when replacing literals in ranges. [#70122](https://github.com/ClickHouse/ClickHouse/pull/70122) ([Pablo Marcos](https://github.com/pamarcos)).
|
||||
* Backported in [#70232](https://github.com/ClickHouse/ClickHouse/issues/70232): Check for Nullable(Nothing) type during ALTER TABLE MODIFY COLUMN/QUERY to prevent tables with such data type. [#70123](https://github.com/ClickHouse/ClickHouse/pull/70123) ([Pavel Kruglov](https://github.com/Avogar)).
|
||||
* Backported in [#70179](https://github.com/ClickHouse/ClickHouse/issues/70179): Fix data race in ColumnObject/ColumnTuple decompress method that could lead to heap use after free. [#70137](https://github.com/ClickHouse/ClickHouse/pull/70137) ([Pavel Kruglov](https://github.com/Avogar)).
|
||||
* Backported in [#70241](https://github.com/ClickHouse/ClickHouse/issues/70241): Fix the password being displayed in `system.query_log` for users with bcrypt password authentication method. [#70148](https://github.com/ClickHouse/ClickHouse/pull/70148) ([Nikolay Degterinsky](https://github.com/evillique)).
|
||||
* Backported in [#70397](https://github.com/ClickHouse/ClickHouse/issues/70397): Fix crash when using WITH FILL incorrectly. [#70338](https://github.com/ClickHouse/ClickHouse/pull/70338) ([Raúl Marín](https://github.com/Algunenano)).
|
||||
|
||||
#### NO CL CATEGORY
|
||||
|
||||
* Backported in [#69526](https://github.com/ClickHouse/ClickHouse/issues/69526):. [#67029](https://github.com/ClickHouse/ClickHouse/pull/67029) ([Alexander Tokmakov](https://github.com/tavplubix)).
|
||||
|
||||
#### NOT FOR CHANGELOG / INSIGNIFICANT
|
||||
|
||||
* Backported in [#69506](https://github.com/ClickHouse/ClickHouse/issues/69506): Better handling of errors from azure storage. [#62306](https://github.com/ClickHouse/ClickHouse/pull/62306) ([Anton Popov](https://github.com/CurtizJ)).
|
||||
* Backported in [#69955](https://github.com/ClickHouse/ClickHouse/issues/69955): Output an operation error for ZK Multi request failed operation into log. [#68127](https://github.com/ClickHouse/ClickHouse/pull/68127) ([Aleksei Filatov](https://github.com/aalexfvk)).
|
||||
* Backported in [#69485](https://github.com/ClickHouse/ClickHouse/issues/69485): Fix test_role & test_keeper_s3_snapshot integration tests. [#69013](https://github.com/ClickHouse/ClickHouse/pull/69013) ([Shankar](https://github.com/shiyer7474)).
|
||||
* Backported in [#70028](https://github.com/ClickHouse/ClickHouse/issues/70028): Remove stale moving parts without zookeeper. [#69075](https://github.com/ClickHouse/ClickHouse/pull/69075) ([Kirill](https://github.com/kirillgarbar)).
|
||||
* Backported in [#69421](https://github.com/ClickHouse/ClickHouse/issues/69421): Fix: Not-ready Set with parallel replicas. [#69264](https://github.com/ClickHouse/ClickHouse/pull/69264) ([Igor Nikonov](https://github.com/devcrafter)).
|
||||
* Backported in [#69747](https://github.com/ClickHouse/ClickHouse/issues/69747): Add function `kill_ci_runner`. Kill runner when pre-pull failed. [#69557](https://github.com/ClickHouse/ClickHouse/pull/69557) ([Mikhail f. Shiryaev](https://github.com/Felixoid)).
|
||||
* Backported in [#69636](https://github.com/ClickHouse/ClickHouse/issues/69636): Add more contexts to the debug action and use it broadly. [#69599](https://github.com/ClickHouse/ClickHouse/pull/69599) ([Mikhail f. Shiryaev](https://github.com/Felixoid)).
|
||||
* The test is flaky and the feature experimental. [#70269](https://github.com/ClickHouse/ClickHouse/pull/70269) ([Raúl Marín](https://github.com/Algunenano)).
|
||||
* Fix test distributed inter server secret in 24.3. [#70325](https://github.com/ClickHouse/ClickHouse/pull/70325) ([Raúl Marín](https://github.com/Algunenano)).
|
||||
|
73
docs/changelogs/v24.8.5.115-lts.md
Normal file
73
docs/changelogs/v24.8.5.115-lts.md
Normal file
@ -0,0 +1,73 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
sidebar_label: 2024
|
||||
---
|
||||
|
||||
# 2024 Changelog
|
||||
|
||||
### ClickHouse release v24.8.5.115-lts (8c4cb00a384) FIXME as compared to v24.8.4.13-lts (53195bc189b)
|
||||
|
||||
#### Improvement
|
||||
* Backported in [#70046](https://github.com/ClickHouse/ClickHouse/issues/70046): Add new column readonly_duration to the system.replicas table. Needed to be able to distinguish actual readonly replicas from sentinel ones in alerts. [#69871](https://github.com/ClickHouse/ClickHouse/pull/69871) ([Miсhael Stetsyuk](https://github.com/mstetsyuk)).
|
||||
|
||||
#### Bug Fix (user-visible misbehavior in an official stable release)
|
||||
* Backported in [#69786](https://github.com/ClickHouse/ClickHouse/issues/69786): Fix attaching table when pg dbname contains "-" in MaterializedPostgreSQL. [#62730](https://github.com/ClickHouse/ClickHouse/pull/62730) ([takakawa](https://github.com/takakawa)).
|
||||
* Backported in [#70318](https://github.com/ClickHouse/ClickHouse/issues/70318): Fixed error on generated columns in MaterializedPostgreSQL when adnum ordering is broken [#63161](https://github.com/ClickHouse/ClickHouse/issues/63161). Fixed error on id column with nextval expression as default MaterializedPostgreSQL when there are generated columns in table. Fixed error on dropping publication with symbols except [a-z1-9-]. [#67664](https://github.com/ClickHouse/ClickHouse/pull/67664) ([Kruglov Kirill](https://github.com/1on)).
|
||||
* Backported in [#69467](https://github.com/ClickHouse/ClickHouse/issues/69467): Fix expiration in `RoleCache`. [#67748](https://github.com/ClickHouse/ClickHouse/pull/67748) ([Vitaly Baranov](https://github.com/vitlibar)).
|
||||
* Backported in [#69735](https://github.com/ClickHouse/ClickHouse/issues/69735): Fix crash in `lag`/`lead` which is introduced in [#67091](https://github.com/ClickHouse/ClickHouse/issues/67091). [#68262](https://github.com/ClickHouse/ClickHouse/pull/68262) ([lgbo](https://github.com/lgbo-ustc)).
|
||||
* Backported in [#69444](https://github.com/ClickHouse/ClickHouse/issues/69444): After unexpected restart, fail to start replication of ReplicatedMergeTree due to abnormal handling of covered-by-broken part. [#68584](https://github.com/ClickHouse/ClickHouse/pull/68584) ([baolin](https://github.com/baolinhuang)).
|
||||
* Backported in [#69810](https://github.com/ClickHouse/ClickHouse/issues/69810): Make `ColumnsDescription::toString` format each column using the same `IAST::FormatState object`. This results in uniform columns metadata being written to disk and ZooKeeper. [#68733](https://github.com/ClickHouse/ClickHouse/pull/68733) ([Miсhael Stetsyuk](https://github.com/mstetsyuk)).
|
||||
* Backported in [#69757](https://github.com/ClickHouse/ClickHouse/issues/69757): Fix incorrect results of Fix uniq and GROUP BY for JSON/Dynamic types. [#69203](https://github.com/ClickHouse/ClickHouse/pull/69203) ([Pavel Kruglov](https://github.com/Avogar)).
|
||||
* Backported in [#70195](https://github.com/ClickHouse/ClickHouse/issues/70195): Fix insertion of incomplete type into Dynamic during deserialization. It could lead to `Parameter out of bound` errors. [#69291](https://github.com/ClickHouse/ClickHouse/pull/69291) ([Pavel Kruglov](https://github.com/Avogar)).
|
||||
* Backported in [#69398](https://github.com/ClickHouse/ClickHouse/issues/69398): Mark Dynamic type as not safe primary key type to avoid issues with Fields. [#69311](https://github.com/ClickHouse/ClickHouse/pull/69311) ([Pavel Kruglov](https://github.com/Avogar)).
|
||||
* Backported in [#69704](https://github.com/ClickHouse/ClickHouse/issues/69704): Improve restoring of access entities' dependencies. [#69346](https://github.com/ClickHouse/ClickHouse/pull/69346) ([Vitaly Baranov](https://github.com/vitlibar)).
|
||||
* Backported in [#69459](https://github.com/ClickHouse/ClickHouse/issues/69459): Fix undefined behavior when all connection attempts fail getting a connection for insertions. [#69390](https://github.com/ClickHouse/ClickHouse/pull/69390) ([Pablo Marcos](https://github.com/pamarcos)).
|
||||
* Backported in [#69503](https://github.com/ClickHouse/ClickHouse/issues/69503): Fixed a `LOGICAL_ERROR` with function `sqidDecode` ([#69450](https://github.com/ClickHouse/ClickHouse/issues/69450)). [#69451](https://github.com/ClickHouse/ClickHouse/pull/69451) ([Robert Schulze](https://github.com/rschu1ze)).
|
||||
* Backported in [#69480](https://github.com/ClickHouse/ClickHouse/issues/69480): Quick fix for s3queue problem on 24.6 or create query with database replicated. [#69454](https://github.com/ClickHouse/ClickHouse/pull/69454) ([Kseniia Sumarokova](https://github.com/kssenii)).
|
||||
* Backported in [#69535](https://github.com/ClickHouse/ClickHouse/issues/69535): Fixed case when memory consumption was too high because of the squashing in `INSERT INTO ... SELECT` or `CREATE TABLE AS SELECT` queries. [#69469](https://github.com/ClickHouse/ClickHouse/pull/69469) ([Yarik Briukhovetskyi](https://github.com/yariks5s)).
|
||||
* Backported in [#69696](https://github.com/ClickHouse/ClickHouse/issues/69696): Keep original order of conditions during move to prewhere. Previously the order could change and it could lead to failing queries when the order is important. [#69560](https://github.com/ClickHouse/ClickHouse/pull/69560) ([Pavel Kruglov](https://github.com/Avogar)).
|
||||
* Backported in [#70439](https://github.com/ClickHouse/ClickHouse/issues/70439): Fix vrash during insertion into FixedString column in PostgreSQL engine. [#69584](https://github.com/ClickHouse/ClickHouse/pull/69584) ([Pavel Kruglov](https://github.com/Avogar)).
|
||||
* Backported in [#69666](https://github.com/ClickHouse/ClickHouse/issues/69666): Fix Keeper multi-request preprocessing after ZNOAUTH error. [#69627](https://github.com/ClickHouse/ClickHouse/pull/69627) ([Antonio Andelic](https://github.com/antonio2368)).
|
||||
* Backported in [#70191](https://github.com/ClickHouse/ClickHouse/issues/70191): Fix crash when executing `create view t as (with recursive 42 as ttt select ttt);`. [#69676](https://github.com/ClickHouse/ClickHouse/pull/69676) ([Han Fei](https://github.com/hanfei1991)).
|
||||
* Backported in [#69798](https://github.com/ClickHouse/ClickHouse/issues/69798): Make getHyperrectangleForRowGroup not throw an exception when the data type in parquet file is not convertable into the requested data type. Solved the user's problem when the Parquet file had Decimal64 data type and the column data type was DateTime. [#69745](https://github.com/ClickHouse/ClickHouse/pull/69745) ([Miсhael Stetsyuk](https://github.com/mstetsyuk)).
|
||||
* Backported in [#70410](https://github.com/ClickHouse/ClickHouse/issues/70410): Fixed `maxMapState` throwing 'Bad get' if value type is DateTime64. [#69787](https://github.com/ClickHouse/ClickHouse/pull/69787) ([Michael Kolupaev](https://github.com/al13n321)).
|
||||
* Backported in [#70019](https://github.com/ClickHouse/ClickHouse/issues/70019): Fix analyzer default with old compatibility value. [#69895](https://github.com/ClickHouse/ClickHouse/pull/69895) ([Raúl Marín](https://github.com/Algunenano)).
|
||||
* Backported in [#69941](https://github.com/ClickHouse/ClickHouse/issues/69941): Don't check dependencies during CREATE OR REPLACE VIEW during DROP of old table. Previously CREATE OR REPLACE query failed when there are dependent tables of the recreated view. [#69907](https://github.com/ClickHouse/ClickHouse/pull/69907) ([Pavel Kruglov](https://github.com/Avogar)).
|
||||
* Backported in [#70001](https://github.com/ClickHouse/ClickHouse/issues/70001): Now SQL security will work with parameterized views correctly. [#69984](https://github.com/ClickHouse/ClickHouse/pull/69984) ([pufit](https://github.com/pufit)).
|
||||
* Backported in [#70081](https://github.com/ClickHouse/ClickHouse/issues/70081): Closes [#69752](https://github.com/ClickHouse/ClickHouse/issues/69752). [#69985](https://github.com/ClickHouse/ClickHouse/pull/69985) ([pufit](https://github.com/pufit)).
|
||||
* Backported in [#70068](https://github.com/ClickHouse/ClickHouse/issues/70068): Fixes `Block structure mismatch` for queries with nested views and `WHERE` condition. Fixes [#66209](https://github.com/ClickHouse/ClickHouse/issues/66209). [#70054](https://github.com/ClickHouse/ClickHouse/pull/70054) ([Nikolai Kochetov](https://github.com/KochetovNicolai)).
|
||||
* Backported in [#70166](https://github.com/ClickHouse/ClickHouse/issues/70166): Fix wrong LOGICAL_ERROR when replacing literals in ranges. [#70122](https://github.com/ClickHouse/ClickHouse/pull/70122) ([Pablo Marcos](https://github.com/pamarcos)).
|
||||
* Backported in [#70236](https://github.com/ClickHouse/ClickHouse/issues/70236): Check for Nullable(Nothing) type during ALTER TABLE MODIFY COLUMN/QUERY to prevent tables with such data type. [#70123](https://github.com/ClickHouse/ClickHouse/pull/70123) ([Pavel Kruglov](https://github.com/Avogar)).
|
||||
* Backported in [#70203](https://github.com/ClickHouse/ClickHouse/issues/70203): Fix wrong result with skipping index. [#70127](https://github.com/ClickHouse/ClickHouse/pull/70127) ([Raúl Marín](https://github.com/Algunenano)).
|
||||
* Backported in [#70183](https://github.com/ClickHouse/ClickHouse/issues/70183): Fix data race in ColumnObject/ColumnTuple decompress method that could lead to heap use after free. [#70137](https://github.com/ClickHouse/ClickHouse/pull/70137) ([Pavel Kruglov](https://github.com/Avogar)).
|
||||
* Backported in [#70251](https://github.com/ClickHouse/ClickHouse/issues/70251): Fix possible hung in ALTER COLUMN with Dynamic type. [#70144](https://github.com/ClickHouse/ClickHouse/pull/70144) ([Pavel Kruglov](https://github.com/Avogar)).
|
||||
* Backported in [#70228](https://github.com/ClickHouse/ClickHouse/issues/70228): Use correct `max_types` parameter during Dynamic type creation for JSON subcolumn. [#70147](https://github.com/ClickHouse/ClickHouse/pull/70147) ([Pavel Kruglov](https://github.com/Avogar)).
|
||||
* Backported in [#70243](https://github.com/ClickHouse/ClickHouse/issues/70243): Fix the password being displayed in `system.query_log` for users with bcrypt password authentication method. [#70148](https://github.com/ClickHouse/ClickHouse/pull/70148) ([Nikolay Degterinsky](https://github.com/evillique)).
|
||||
* Backported in [#70432](https://github.com/ClickHouse/ClickHouse/issues/70432): Fix possible crash in JSON column. [#70172](https://github.com/ClickHouse/ClickHouse/pull/70172) ([Pavel Kruglov](https://github.com/Avogar)).
|
||||
* Backported in [#70307](https://github.com/ClickHouse/ClickHouse/issues/70307): Fix multiple issues with arrayMin and arrayMax. [#70207](https://github.com/ClickHouse/ClickHouse/pull/70207) ([Raúl Marín](https://github.com/Algunenano)).
|
||||
* Backported in [#70274](https://github.com/ClickHouse/ClickHouse/issues/70274): Respect setting allow_simdjson in JSON type parser. [#70218](https://github.com/ClickHouse/ClickHouse/pull/70218) ([Pavel Kruglov](https://github.com/Avogar)).
|
||||
* Backported in [#70345](https://github.com/ClickHouse/ClickHouse/issues/70345): Don't modify global settings with startup scripts. Previously, changing a setting in a startup script would change it globally. [#70310](https://github.com/ClickHouse/ClickHouse/pull/70310) ([Antonio Andelic](https://github.com/antonio2368)).
|
||||
* Backported in [#70426](https://github.com/ClickHouse/ClickHouse/issues/70426): Fix ALTER of Dynamic type with reducing max_types parameter that could lead to server crash. [#70328](https://github.com/ClickHouse/ClickHouse/pull/70328) ([Pavel Kruglov](https://github.com/Avogar)).
|
||||
* Backported in [#70371](https://github.com/ClickHouse/ClickHouse/issues/70371): Fix crash when using WITH FILL incorrectly. [#70338](https://github.com/ClickHouse/ClickHouse/pull/70338) ([Raúl Marín](https://github.com/Algunenano)).
|
||||
|
||||
#### NO CL ENTRY
|
||||
|
||||
* NO CL ENTRY: 'Revert "Backport [#70146](https://github.com/ClickHouse/ClickHouse/issues/70146) to 24.8: Upgrade integration-runner image"'. [#70324](https://github.com/ClickHouse/ClickHouse/pull/70324) ([Max K.](https://github.com/maxknv)).
|
||||
|
||||
#### NOT FOR CHANGELOG / INSIGNIFICANT
|
||||
|
||||
* Backported in [#69961](https://github.com/ClickHouse/ClickHouse/issues/69961): Output an operation error for ZK Multi request failed operation into log. [#68127](https://github.com/ClickHouse/ClickHouse/pull/68127) ([Aleksei Filatov](https://github.com/aalexfvk)).
|
||||
* Backported in [#69491](https://github.com/ClickHouse/ClickHouse/issues/69491): Fix test_role & test_keeper_s3_snapshot integration tests. [#69013](https://github.com/ClickHouse/ClickHouse/pull/69013) ([Shankar](https://github.com/shiyer7474)).
|
||||
* Backported in [#69953](https://github.com/ClickHouse/ClickHouse/issues/69953): Remove stale moving parts without zookeeper. [#69075](https://github.com/ClickHouse/ClickHouse/pull/69075) ([Kirill](https://github.com/kirillgarbar)).
|
||||
* Backported in [#69353](https://github.com/ClickHouse/ClickHouse/issues/69353): Fix: Not-ready Set with parallel replicas. [#69264](https://github.com/ClickHouse/ClickHouse/pull/69264) ([Igor Nikonov](https://github.com/devcrafter)).
|
||||
* Backported in [#69427](https://github.com/ClickHouse/ClickHouse/issues/69427): Fix 24.8 setting compatibility `rows_before_aggregation`. [#69394](https://github.com/ClickHouse/ClickHouse/pull/69394) ([Nikita Fomichev](https://github.com/fm4v)).
|
||||
* Backported in [#69689](https://github.com/ClickHouse/ClickHouse/issues/69689): Add function `kill_ci_runner`. Kill runner when pre-pull failed. [#69557](https://github.com/ClickHouse/ClickHouse/pull/69557) ([Mikhail f. Shiryaev](https://github.com/Felixoid)).
|
||||
* Backported in [#69639](https://github.com/ClickHouse/ClickHouse/issues/69639): Add more contexts to the debug action and use it broadly. [#69599](https://github.com/ClickHouse/ClickHouse/pull/69599) ([Mikhail f. Shiryaev](https://github.com/Felixoid)).
|
||||
* Backported in [#69721](https://github.com/ClickHouse/ClickHouse/issues/69721): Prohibit `ALTER TABLE ... ADD INDEX ... TYPE` inverted if setting = 0. [#69684](https://github.com/ClickHouse/ClickHouse/pull/69684) ([Robert Schulze](https://github.com/rschu1ze)).
|
||||
* Backported in [#69972](https://github.com/ClickHouse/ClickHouse/issues/69972): S3Queue: support having deprecated settings to not fail server startup. [#69769](https://github.com/ClickHouse/ClickHouse/pull/69769) ([Kseniia Sumarokova](https://github.com/kssenii)).
|
||||
* Backported in [#70283](https://github.com/ClickHouse/ClickHouse/issues/70283): Improve pipdeptree generator for docker images. - Update requirements.txt for the integration tests runner container - Remove some small dependencies, improve `helpers/retry_decorator.py` - Upgrade docker-compose from EOL version 1 to version 2. [#70146](https://github.com/ClickHouse/ClickHouse/pull/70146) ([Mikhail f. Shiryaev](https://github.com/Felixoid)).
|
||||
* Backported in [#70260](https://github.com/ClickHouse/ClickHouse/issues/70260): Update test_storage_s3_queue/test.py. [#70159](https://github.com/ClickHouse/ClickHouse/pull/70159) ([Kseniia Sumarokova](https://github.com/kssenii)).
|
||||
* Backported in [#70314](https://github.com/ClickHouse/ClickHouse/issues/70314): CI: Remove await feature from release branches. [#70294](https://github.com/ClickHouse/ClickHouse/pull/70294) ([Max K.](https://github.com/maxknv)).
|
||||
* Backported in [#70380](https://github.com/ClickHouse/ClickHouse/issues/70380): Fix tiny mistake, responsible for some of kafka test flaps. Example [report](https://s3.amazonaws.com/clickhouse-test-reports/0/3198aafac59c368993e7b5f49d95674cc1b1be18/integration_tests__release__[2_4].html). [#70352](https://github.com/ClickHouse/ClickHouse/pull/70352) ([filimonov](https://github.com/filimonov)).
|
||||
* Backported in [#70405](https://github.com/ClickHouse/ClickHouse/issues/70405): Closes [#69634](https://github.com/ClickHouse/ClickHouse/issues/69634). [#70354](https://github.com/ClickHouse/ClickHouse/pull/70354) ([pufit](https://github.com/pufit)).
|
||||
|
@ -49,6 +49,18 @@ Default values are defined in [Settings.h](https://github.com/ClickHouse/ClickHo
|
||||
|
||||
See also the description of [max_memory_usage](#settings_max_memory_usage).
|
||||
|
||||
For example if you want to set `max_memory_usage_for_user` to 1000 bytes for a user named `clickhouse_read`, you can use the statement
|
||||
|
||||
``` sql
|
||||
ALTER USER clickhouse_read SETTINGS max_memory_usage_for_user = 1000;
|
||||
```
|
||||
|
||||
You can verify it worked by logging out of your client, logging back in, then use the `getSetting` function:
|
||||
|
||||
```sql
|
||||
SELECT getSetting('max_memory_usage_for_user');
|
||||
```
|
||||
|
||||
## max_rows_to_read {#max-rows-to-read}
|
||||
|
||||
The following restrictions can be checked on each block (instead of on each row). That is, the restrictions can be broken a little.
|
||||
|
@ -6,7 +6,7 @@ sidebar_label: User Settings
|
||||
|
||||
# Users and Roles Settings
|
||||
|
||||
The `users` section of the `user.xml` configuration file contains user settings.
|
||||
The `users` section of the `users.xml` configuration file contains user settings.
|
||||
|
||||
:::note
|
||||
ClickHouse also supports [SQL-driven workflow](../../guides/sre/user-management/index.md#access-control) for managing users. We recommend using it.
|
||||
|
@ -297,99 +297,259 @@ $$)
|
||||
└───────────────┴────────────────┴───────────────┴──────┴───────┴────────────┴─────────┘
|
||||
```
|
||||
|
||||
## Comparing values of Dynamic type
|
||||
## Using Dynamic type in functions
|
||||
|
||||
Values of `Dynamic` types are compared similar to values of `Variant` type:
|
||||
Most of the functions support arguments with type `Dynamic`. In this case the function is executed separately on each internal data type stored inside `Dynamic` column.
|
||||
When the result type of the function depends on the arguments types, the result of such function executed with `Dynamic` arguments will be `Dynamic`. When the result type of the function doesn't depend on the arguments types - the result will be `Nullable(T)` where `T` the usual result type of this function.
|
||||
|
||||
Examples:
|
||||
|
||||
```sql
|
||||
CREATE TABLE test (d Dynamic) ENGINE=Memory;
|
||||
INSERT INTO test VALUES (NULL), (1::Int8), (2::Int16), (3::Int32), (4::Int64);
|
||||
```
|
||||
|
||||
```sql
|
||||
SELECT d, dynamicType(d) FROM test;
|
||||
```
|
||||
|
||||
```text
|
||||
┌─d────┬─dynamicType(d)─┐
|
||||
│ ᴺᵁᴸᴸ │ None │
|
||||
│ 1 │ Int8 │
|
||||
│ 2 │ Int16 │
|
||||
│ 3 │ Int32 │
|
||||
│ 4 │ Int64 │
|
||||
└──────┴────────────────┘
|
||||
```
|
||||
|
||||
```sql
|
||||
SELECT d, d + 1 AS res, toTypeName(res), dynamicType(res) FROM test;
|
||||
```
|
||||
|
||||
```text
|
||||
┌─d────┬─res──┬─toTypeName(res)─┬─dynamicType(res)─┐
|
||||
│ ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ │ Dynamic │ None │
|
||||
│ 1 │ 2 │ Dynamic │ Int16 │
|
||||
│ 2 │ 3 │ Dynamic │ Int32 │
|
||||
│ 3 │ 4 │ Dynamic │ Int64 │
|
||||
│ 4 │ 5 │ Dynamic │ Int64 │
|
||||
└──────┴──────┴─────────────────┴──────────────────┘
|
||||
```
|
||||
|
||||
```sql
|
||||
SELECT d, d + d AS res, toTypeName(res), dynamicType(res) FROM test;
|
||||
```
|
||||
|
||||
```text
|
||||
┌─d────┬─res──┬─toTypeName(res)─┬─dynamicType(res)─┐
|
||||
│ ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ │ Dynamic │ None │
|
||||
│ 1 │ 2 │ Dynamic │ Int16 │
|
||||
│ 2 │ 4 │ Dynamic │ Int32 │
|
||||
│ 3 │ 6 │ Dynamic │ Int64 │
|
||||
│ 4 │ 8 │ Dynamic │ Int64 │
|
||||
└──────┴──────┴─────────────────┴──────────────────┘
|
||||
```
|
||||
|
||||
```sql
|
||||
SELECT d, d < 3 AS res, toTypeName(res) FROM test;
|
||||
```
|
||||
|
||||
```text
|
||||
┌─d────┬──res─┬─toTypeName(res)─┐
|
||||
│ ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ │ Nullable(UInt8) │
|
||||
│ 1 │ 1 │ Nullable(UInt8) │
|
||||
│ 2 │ 1 │ Nullable(UInt8) │
|
||||
│ 3 │ 0 │ Nullable(UInt8) │
|
||||
│ 4 │ 0 │ Nullable(UInt8) │
|
||||
└──────┴──────┴─────────────────┘
|
||||
```
|
||||
|
||||
```sql
|
||||
SELECT d, exp2(d) AS res, toTypeName(res) FROM test;
|
||||
```
|
||||
|
||||
```sql
|
||||
┌─d────┬──res─┬─toTypeName(res)───┐
|
||||
│ ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ │ Nullable(Float64) │
|
||||
│ 1 │ 2 │ Nullable(Float64) │
|
||||
│ 2 │ 4 │ Nullable(Float64) │
|
||||
│ 3 │ 8 │ Nullable(Float64) │
|
||||
│ 4 │ 16 │ Nullable(Float64) │
|
||||
└──────┴──────┴───────────────────┘
|
||||
```
|
||||
|
||||
```sql
|
||||
TRUNCATE TABLE test;
|
||||
INSERT INTO test VALUES (NULL), ('str_1'), ('str_2');
|
||||
SELECT d, dynamicType(d) FROM test;
|
||||
```
|
||||
|
||||
```text
|
||||
┌─d─────┬─dynamicType(d)─┐
|
||||
│ ᴺᵁᴸᴸ │ None │
|
||||
│ str_1 │ String │
|
||||
│ str_2 │ String │
|
||||
└───────┴────────────────┘
|
||||
```
|
||||
|
||||
```sql
|
||||
SELECT d, upper(d) AS res, toTypeName(res) FROM test;
|
||||
```
|
||||
|
||||
```text
|
||||
┌─d─────┬─res───┬─toTypeName(res)──┐
|
||||
│ ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ │ Nullable(String) │
|
||||
│ str_1 │ STR_1 │ Nullable(String) │
|
||||
│ str_2 │ STR_2 │ Nullable(String) │
|
||||
└───────┴───────┴──────────────────┘
|
||||
```
|
||||
|
||||
```sql
|
||||
SELECT d, extract(d, '([0-3])') AS res, toTypeName(res) FROM test;
|
||||
```
|
||||
|
||||
```text
|
||||
┌─d─────┬─res──┬─toTypeName(res)──┐
|
||||
│ ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ │ Nullable(String) │
|
||||
│ str_1 │ 1 │ Nullable(String) │
|
||||
│ str_2 │ 2 │ Nullable(String) │
|
||||
└───────┴──────┴──────────────────┘
|
||||
```
|
||||
|
||||
```sql
|
||||
TRUNCATE TABLE test;
|
||||
INSERT INTO test VALUES (NULL), ([1, 2]), ([3, 4]);
|
||||
SELECT d, dynamicType(d) FROM test;
|
||||
```
|
||||
|
||||
```text
|
||||
┌─d─────┬─dynamicType(d)─┐
|
||||
│ ᴺᵁᴸᴸ │ None │
|
||||
│ [1,2] │ Array(Int64) │
|
||||
│ [3,4] │ Array(Int64) │
|
||||
└───────┴────────────────┘
|
||||
```
|
||||
|
||||
```sql
|
||||
SELECT d, d[1] AS res, toTypeName(res), dynamicType(res) FROM test;
|
||||
```
|
||||
|
||||
```text
|
||||
┌─d─────┬─res──┬─toTypeName(res)─┬─dynamicType(res)─┐
|
||||
│ ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ │ Dynamic │ None │
|
||||
│ [1,2] │ 1 │ Dynamic │ Int64 │
|
||||
│ [3,4] │ 3 │ Dynamic │ Int64 │
|
||||
└───────┴──────┴─────────────────┴──────────────────┘
|
||||
```
|
||||
|
||||
If function cannot be executed on some type inside `Dynamic` column, the exception will be thrown:
|
||||
|
||||
```sql
|
||||
INSERT INTO test VALUES (42), (43), ('str_1');
|
||||
SELECT d, dynamicType(d) FROM test;
|
||||
```
|
||||
|
||||
|
||||
```text
|
||||
┌─d─────┬─dynamicType(d)─┐
|
||||
│ 42 │ Int64 │
|
||||
│ 43 │ Int64 │
|
||||
│ str_1 │ String │
|
||||
└───────┴────────────────┘
|
||||
┌─d─────┬─dynamicType(d)─┐
|
||||
│ ᴺᵁᴸᴸ │ None │
|
||||
│ [1,2] │ Array(Int64) │
|
||||
│ [3,4] │ Array(Int64) │
|
||||
└───────┴────────────────┘
|
||||
```
|
||||
|
||||
```sql
|
||||
SELECT d, d + 1 AS res, toTypeName(res), dynamicType(d) FROM test;
|
||||
```
|
||||
|
||||
```text
|
||||
Received exception:
|
||||
Code: 43. DB::Exception: Illegal types Array(Int64) and UInt8 of arguments of function plus: while executing 'FUNCTION plus(__table1.d : 3, 1_UInt8 :: 1) -> plus(__table1.d, 1_UInt8) Dynamic : 0'. (ILLEGAL_TYPE_OF_ARGUMENT)
|
||||
```
|
||||
|
||||
We can filter out unneeded types:
|
||||
|
||||
```sql
|
||||
SELECT d, d + 1 AS res, toTypeName(res), dynamicType(res) FROM test WHERE dynamicType(d) NOT IN ('String', 'Array(Int64)', 'None')
|
||||
```
|
||||
|
||||
```text
|
||||
┌─d──┬─res─┬─toTypeName(res)─┬─dynamicType(res)─┐
|
||||
│ 42 │ 43 │ Dynamic │ Int64 │
|
||||
│ 43 │ 44 │ Dynamic │ Int64 │
|
||||
└────┴─────┴─────────────────┴──────────────────┘
|
||||
```
|
||||
|
||||
Or extract required type as subcolumn:
|
||||
|
||||
```sql
|
||||
SELECT d, d.Int64 + 1 AS res, toTypeName(res) FROM test;
|
||||
```
|
||||
|
||||
```text
|
||||
┌─d─────┬──res─┬─toTypeName(res)─┐
|
||||
│ 42 │ 43 │ Nullable(Int64) │
|
||||
│ 43 │ 44 │ Nullable(Int64) │
|
||||
│ str_1 │ ᴺᵁᴸᴸ │ Nullable(Int64) │
|
||||
└───────┴──────┴─────────────────┘
|
||||
┌─d─────┬──res─┬─toTypeName(res)─┐
|
||||
│ ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ │ Nullable(Int64) │
|
||||
│ [1,2] │ ᴺᵁᴸᴸ │ Nullable(Int64) │
|
||||
│ [3,4] │ ᴺᵁᴸᴸ │ Nullable(Int64) │
|
||||
└───────┴──────┴─────────────────┘
|
||||
```
|
||||
|
||||
## Using Dynamic type in ORDER BY and GROUP BY
|
||||
|
||||
During `ORDER BY` and `GROUP BY` values of `Dynamic` types are compared similar to values of `Variant` type:
|
||||
The result of operator `<` for values `d1` with underlying type `T1` and `d2` with underlying type `T2` of a type `Dynamic` is defined as follows:
|
||||
- If `T1 = T2 = T`, the result will be `d1.T < d2.T` (underlying values will be compared).
|
||||
- If `T1 != T2`, the result will be `T1 < T2` (type names will be compared).
|
||||
|
||||
By default `Dynamic` type is not allowed in `GROUP BY`/`ORDER BY` keys, if you want to use it consider its special comparison rule and enable `allow_suspicious_types_in_group_by`/`allow_suspicious_types_in_order_by` settings.
|
||||
|
||||
Examples:
|
||||
```sql
|
||||
CREATE TABLE test (d1 Dynamic, d2 Dynamic) ENGINE=Memory;
|
||||
INSERT INTO test VALUES (42, 42), (42, 43), (42, 'abc'), (42, [1, 2, 3]), (42, []), (42, NULL);
|
||||
CREATE TABLE test (d Dynamic) ENGINE=Memory;
|
||||
INSERT INTO test VALUES (42), (43), ('abc'), ('abd'), ([1, 2, 3]), ([]), (NULL);
|
||||
```
|
||||
|
||||
```sql
|
||||
SELECT d2, dynamicType(d2) as d2_type from test order by d2;
|
||||
SELECT d, dynamicType(d) FROM test;
|
||||
```
|
||||
|
||||
```text
|
||||
┌─d2──────┬─d2_type──────┐
|
||||
│ [] │ Array(Int64) │
|
||||
│ [1,2,3] │ Array(Int64) │
|
||||
│ 42 │ Int64 │
|
||||
│ 43 │ Int64 │
|
||||
│ abc │ String │
|
||||
│ ᴺᵁᴸᴸ │ None │
|
||||
└─────────┴──────────────┘
|
||||
┌─d───────┬─dynamicType(d)─┐
|
||||
│ 42 │ Int64 │
|
||||
│ 43 │ Int64 │
|
||||
│ abc │ String │
|
||||
│ abd │ String │
|
||||
│ [1,2,3] │ Array(Int64) │
|
||||
│ [] │ Array(Int64) │
|
||||
│ ᴺᵁᴸᴸ │ None │
|
||||
└─────────┴────────────────┘
|
||||
```
|
||||
|
||||
```sql
|
||||
SELECT d1, dynamicType(d1) as d1_type, d2, dynamicType(d2) as d2_type, d1 = d2, d1 < d2, d1 > d2 from test;
|
||||
```
|
||||
|
||||
```text
|
||||
┌─d1─┬─d1_type─┬─d2──────┬─d2_type──────┬─equals(d1, d2)─┬─less(d1, d2)─┬─greater(d1, d2)─┐
|
||||
│ 42 │ Int64 │ 42 │ Int64 │ 1 │ 0 │ 0 │
|
||||
│ 42 │ Int64 │ 43 │ Int64 │ 0 │ 1 │ 0 │
|
||||
│ 42 │ Int64 │ abc │ String │ 0 │ 1 │ 0 │
|
||||
│ 42 │ Int64 │ [1,2,3] │ Array(Int64) │ 0 │ 0 │ 1 │
|
||||
│ 42 │ Int64 │ [] │ Array(Int64) │ 0 │ 0 │ 1 │
|
||||
│ 42 │ Int64 │ ᴺᵁᴸᴸ │ None │ 0 │ 1 │ 0 │
|
||||
└────┴─────────┴─────────┴──────────────┴────────────────┴──────────────┴─────────────────┘
|
||||
```
|
||||
|
||||
If you need to find the row with specific `Dynamic` value, you can do one of the following:
|
||||
|
||||
- Cast value to the `Dynamic` type:
|
||||
|
||||
```sql
|
||||
SELECT * FROM test WHERE d2 == [1,2,3]::Array(UInt32)::Dynamic;
|
||||
```
|
||||
|
||||
```text
|
||||
┌─d1─┬─d2──────┐
|
||||
│ 42 │ [1,2,3] │
|
||||
└────┴─────────┘
|
||||
```
|
||||
|
||||
- Compare `Dynamic` subcolumn with required type:
|
||||
|
||||
```sql
|
||||
SELECT * FROM test WHERE d2.`Array(Int65)` == [1,2,3] -- or using variantElement(d2, 'Array(UInt32)')
|
||||
```
|
||||
|
||||
```text
|
||||
┌─d1─┬─d2──────┐
|
||||
│ 42 │ [1,2,3] │
|
||||
└────┴─────────┘
|
||||
```
|
||||
|
||||
Sometimes it can be useful to make additional check on dynamic type as subcolumns with complex types like `Array/Map/Tuple` cannot be inside `Nullable` and will have default values instead of `NULL` on rows with different types:
|
||||
|
||||
```sql
|
||||
SELECT d2, d2.`Array(Int64)`, dynamicType(d2) FROM test WHERE d2.`Array(Int64)` == [];
|
||||
```
|
||||
|
||||
```text
|
||||
┌─d2───┬─d2.Array(UInt32)─┬─dynamicType(d2)─┐
|
||||
│ 42 │ [] │ Int64 │
|
||||
│ 43 │ [] │ Int64 │
|
||||
│ abc │ [] │ String │
|
||||
│ [] │ [] │ Array(Int32) │
|
||||
│ ᴺᵁᴸᴸ │ [] │ None │
|
||||
└──────┴──────────────────┴─────────────────┘
|
||||
SELECT d, dynamicType(d) FROM test ORDER BY d SETTINGS allow_suspicious_types_in_order_by=1;
|
||||
```
|
||||
|
||||
```sql
|
||||
SELECT d2, d2.`Array(Int64)`, dynamicType(d2) FROM test WHERE dynamicType(d2) == 'Array(Int64)' AND d2.`Array(Int64)` == [];
|
||||
```
|
||||
|
||||
```text
|
||||
┌─d2─┬─d2.Array(UInt32)─┬─dynamicType(d2)─┐
|
||||
│ [] │ [] │ Array(Int64) │
|
||||
└────┴──────────────────┴─────────────────┘
|
||||
┌─d───────┬─dynamicType(d)─┐
|
||||
│ [] │ Array(Int64) │
|
||||
│ [1,2,3] │ Array(Int64) │
|
||||
│ 42 │ Int64 │
|
||||
│ 43 │ Int64 │
|
||||
│ abc │ String │
|
||||
│ abd │ String │
|
||||
│ ᴺᵁᴸᴸ │ None │
|
||||
└─────────┴────────────────┘
|
||||
```
|
||||
|
||||
**Note:** values of dynamic types with different numeric types are considered as different values and not compared between each other, their type names are compared instead.
|
||||
@ -399,7 +559,7 @@ Example:
|
||||
```sql
|
||||
CREATE TABLE test (d Dynamic) ENGINE=Memory;
|
||||
INSERT INTO test VALUES (1::UInt32), (1::Int64), (100::UInt32), (100::Int64);
|
||||
SELECT d, dynamicType(d) FROM test ORDER by d;
|
||||
SELECT d, dynamicType(d) FROM test ORDER BY d SETTINGS allow_suspicious_types_in_order_by=1;
|
||||
```
|
||||
|
||||
```text
|
||||
@ -411,8 +571,20 @@ SELECT d, dynamicType(d) FROM test ORDER by d;
|
||||
└─────┴────────────────┘
|
||||
```
|
||||
|
||||
**Note** by default `Dynamic` type is not allowed in `GROUP BY`/`ORDER BY` keys, if you want to use it consider its special comparison rule and enable `allow_suspicious_types_in_group_by`/`allow_suspicious_types_in_order_by` settings.
|
||||
```sql
|
||||
SELECT d, dynamicType(d) FROM test GROUP by d SETTINGS allow_suspicious_types_in_group_by=1;
|
||||
```
|
||||
|
||||
```text
|
||||
┌─d───┬─dynamicType(d)─┐
|
||||
│ 1 │ Int64 │
|
||||
│ 100 │ UInt32 │
|
||||
│ 1 │ UInt32 │
|
||||
│ 100 │ Int64 │
|
||||
└─────┴────────────────┘
|
||||
```
|
||||
|
||||
**Note:** the described comparison rule is not applied during execution of comparison functions like `<`/`>`/`=` and others because of [special work](#using-dynamic-type-in-functions) of functions with `Dynamic` type
|
||||
|
||||
## Reaching the limit in number of different data types stored inside Dynamic
|
||||
|
||||
|
@ -1972,7 +1972,7 @@ Result:
|
||||
|
||||
## toISOYear
|
||||
|
||||
Converts a date, or date with time, to a UInt16 number containing the ISO Year number.
|
||||
Converts a date, or date with time, to the ISO year as a UInt16 number.
|
||||
|
||||
**Syntax**
|
||||
|
||||
@ -1982,11 +1982,11 @@ toISOYear(value)
|
||||
|
||||
**Arguments**
|
||||
|
||||
- `value` — The value with date or date with time.
|
||||
- `value` — The value with date or date with time. [Date](../data-types/date.md), [Date32](../data-types/date32.md), [DateTime](../data-types/datetime.md) or [DateTime64](../data-types/datetime64.md)
|
||||
|
||||
**Returned value**
|
||||
|
||||
- `value` converted to the current ISO year number. [UInt16](../data-types/int-uint.md).
|
||||
- The input value converted to a ISO year number. [UInt16](../data-types/int-uint.md).
|
||||
|
||||
**Example**
|
||||
|
||||
@ -1995,7 +1995,7 @@ Query:
|
||||
```sql
|
||||
SELECT
|
||||
toISOYear(toDate('2024/10/02')) as year1,
|
||||
toISOYear(toDateTime('2024/10/02 01:30:00')) as year2
|
||||
toISOYear(toDateTime('2024-10-02 01:30:00')) as year2
|
||||
```
|
||||
|
||||
Result:
|
||||
|
@ -288,11 +288,11 @@ toIPv4OrDefault(value)
|
||||
|
||||
**Arguments**
|
||||
|
||||
- `value` — The value with IPv4 address.
|
||||
- `value` — A string-encoded IPv4 address. [String](../data-types/string.md)
|
||||
|
||||
**Returned value**
|
||||
|
||||
- `value` converted to the current IPv4 address. [String](../data-types/string.md).
|
||||
- `value` converted to an IPv4 address. [IPv4](../data-types/ipv4.md).
|
||||
|
||||
**Example**
|
||||
|
||||
@ -324,11 +324,11 @@ toIPv4OrNull(value)
|
||||
|
||||
**Arguments**
|
||||
|
||||
- `value` — The value with IPv4 address.
|
||||
- `value` — A string-encoded IPv4 address. [String](../data-types/string.md)
|
||||
|
||||
**Returned value**
|
||||
|
||||
- `value` converted to the current IPv4 address. [String](../data-types/string.md).
|
||||
- `value` converted to an IPv4 address. [IPv4](../data-types/ipv4.md).
|
||||
|
||||
**Example**
|
||||
|
||||
|
@ -202,7 +202,7 @@ Result:
|
||||
|
||||
Returns the type name of the passed argument.
|
||||
|
||||
If `NULL` is passed, then the function returns type `Nullable(Nothing)`, which corresponds to ClickHouse's internal `NULL` representation.
|
||||
If `NULL` is passed, the function returns type `Nullable(Nothing)`, which corresponds to ClickHouse's internal `NULL` representation.
|
||||
|
||||
**Syntax**
|
||||
|
||||
@ -212,11 +212,11 @@ toTypeName(value)
|
||||
|
||||
**Arguments**
|
||||
|
||||
- `value` — The value with any arbitrary.
|
||||
- `value` — A value of arbitrary type.
|
||||
|
||||
**Returned value**
|
||||
|
||||
- `value` converted to the current data type name. [String](../data-types/string.md).
|
||||
- The data type name of the input value. [String](../data-types/string.md).
|
||||
|
||||
**Example**
|
||||
|
||||
@ -410,13 +410,37 @@ Code: 44. DB::Exception: Received from localhost:9000. DB::Exception: Illegal ty
|
||||
|
||||
## ignore
|
||||
|
||||
Accepts any arguments, including `NULL` and does nothing. Always returns 0.
|
||||
The argument is internally still evaluated. Useful e.g. for benchmarks.
|
||||
Accepts arbitrary arguments and unconditionally returns `0`.
|
||||
The argument is still evaluated internally, making it useful for eg. benchmarking.
|
||||
|
||||
**Syntax**
|
||||
|
||||
```sql
|
||||
ignore(x)
|
||||
ignore([arg1[, arg2[, ...]])
|
||||
```
|
||||
|
||||
**Arguments**
|
||||
|
||||
- Accepts arbitrarily many arguments of arbitrary type, including `NULL`.
|
||||
|
||||
**Returned value**
|
||||
|
||||
- Returns `0`.
|
||||
|
||||
**Example**
|
||||
|
||||
Query:
|
||||
|
||||
```sql
|
||||
SELECT ignore(0, 'ClickHouse', NULL);
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```response
|
||||
┌─ignore(0, 'ClickHouse', NULL)─┐
|
||||
│ 0 │
|
||||
└───────────────────────────────┘
|
||||
```
|
||||
|
||||
## sleep
|
||||
@ -524,13 +548,9 @@ Useful in table engine parameters of `CREATE TABLE` queries where you need to sp
|
||||
currentDatabase()
|
||||
```
|
||||
|
||||
**Arguments**
|
||||
|
||||
None.
|
||||
|
||||
**Returned value**
|
||||
|
||||
- `value` returns the current database name. [String](../data-types/string.md).
|
||||
- Returns the current database name. [String](../data-types/string.md).
|
||||
|
||||
**Example**
|
||||
|
||||
@ -579,6 +599,42 @@ Result:
|
||||
└───────────────┘
|
||||
```
|
||||
|
||||
## currentSchemas
|
||||
|
||||
Returns a single-element array with the name of the current database schema.
|
||||
|
||||
**Syntax**
|
||||
|
||||
```sql
|
||||
currentSchemas(bool)
|
||||
```
|
||||
|
||||
Alias: `current_schemas`.
|
||||
|
||||
**Arguments**
|
||||
|
||||
- `bool`: A boolean value. [Bool](../data-types/boolean.md).
|
||||
|
||||
:::note
|
||||
The boolean argument is ignored. It only exists for the sake of compatibility with the [implementation](https://www.postgresql.org/docs/7.3/functions-misc.html) of this function in PostgreSQL.
|
||||
:::
|
||||
|
||||
**Returned values**
|
||||
|
||||
- Returns a single-element array with the name of the current database
|
||||
|
||||
**Example**
|
||||
|
||||
```sql
|
||||
SELECT currentSchemas(true);
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```response
|
||||
['default']
|
||||
```
|
||||
|
||||
## isConstant
|
||||
|
||||
Returns whether the argument is a constant expression.
|
||||
@ -1821,7 +1877,7 @@ toColumnTypeName(value)
|
||||
|
||||
**Example**
|
||||
|
||||
Difference between `toTypeName ' and ' toColumnTypeName`:
|
||||
Difference between `toTypeName` and `toColumnTypeName`:
|
||||
|
||||
```sql
|
||||
SELECT toTypeName(CAST('2018-01-01 01:02:03' AS DateTime))
|
||||
@ -3897,13 +3953,15 @@ Retrieves the connection ID of the client that submitted the current query and r
|
||||
connectionId()
|
||||
```
|
||||
|
||||
Alias: `connection_id`.
|
||||
|
||||
**Parameters**
|
||||
|
||||
None.
|
||||
|
||||
**Returned value**
|
||||
|
||||
Returns an integer of type UInt64.
|
||||
The current connection ID. [UInt64](../data-types/int-uint.md).
|
||||
|
||||
**Implementation details**
|
||||
|
||||
@ -3921,40 +3979,6 @@ SELECT connectionId();
|
||||
0
|
||||
```
|
||||
|
||||
## connection_id
|
||||
|
||||
An alias of `connectionId`. Retrieves the connection ID of the client that submitted the current query and returns it as a UInt64 integer.
|
||||
|
||||
**Syntax**
|
||||
|
||||
```sql
|
||||
connection_id()
|
||||
```
|
||||
|
||||
**Parameters**
|
||||
|
||||
None.
|
||||
|
||||
**Returned value**
|
||||
|
||||
Returns an integer of type UInt64.
|
||||
|
||||
**Implementation details**
|
||||
|
||||
This function is most useful in debugging scenarios or for internal purposes within the MySQL handler. It was created for compatibility with [MySQL's `CONNECTION_ID` function](https://dev.mysql.com/doc/refman/8.0/en/information-functions.html#function_connection-id) It is not typically used in production queries.
|
||||
|
||||
**Example**
|
||||
|
||||
Query:
|
||||
|
||||
```sql
|
||||
SELECT connection_id();
|
||||
```
|
||||
|
||||
```response
|
||||
0
|
||||
```
|
||||
|
||||
## getClientHTTPHeader
|
||||
|
||||
Get the value of an HTTP header.
|
||||
|
@ -755,7 +755,7 @@ Result:
|
||||
|
||||
## match {#match}
|
||||
|
||||
Returns whether string `haystack` matches the regular expression `pattern` in [re2 regular syntax](https://github.com/google/re2/wiki/Syntax).
|
||||
Returns whether string `haystack` matches the regular expression `pattern` in [re2 regular expression syntax](https://github.com/google/re2/wiki/Syntax).
|
||||
|
||||
Matching is based on UTF-8, e.g. `.` matches the Unicode code point `¥` which is represented in UTF-8 using two bytes. The regular
|
||||
expression must not contain null bytes. If the haystack or the pattern are not valid UTF-8, then the behavior is undefined.
|
||||
@ -852,9 +852,10 @@ multiFuzzyMatchAllIndices(haystack, distance, \[pattern<sub>1</sub>, pattern<sub
|
||||
|
||||
## extract
|
||||
|
||||
Extracts a fragment of a string using a regular expression. If `haystack` does not match the `pattern` regex, an empty string is returned.
|
||||
Returns the first match of a regular expression in a string.
|
||||
If `haystack` does not match the `pattern` regex, an empty string is returned.
|
||||
|
||||
For regex without subpatterns, the function uses the fragment that matches the entire regex. Otherwise, it uses the fragment that matches the first subpattern.
|
||||
If the regular expression has capturing groups, the function matches the input string against the first capturing group.
|
||||
|
||||
**Syntax**
|
||||
|
||||
@ -862,13 +863,36 @@ For regex without subpatterns, the function uses the fragment that matches the e
|
||||
extract(haystack, pattern)
|
||||
```
|
||||
|
||||
*Arguments**
|
||||
|
||||
- `haystack` — Input string. [String](../data-types/string.md).
|
||||
- `pattern` — Regular expression with [re2 regular expression syntax](https://github.com/google/re2/wiki/Syntax).
|
||||
|
||||
**Returned value**
|
||||
|
||||
- The first match of the regular expression in the haystack string. [String](../data-types/string.md).
|
||||
|
||||
**Example**
|
||||
|
||||
Query:
|
||||
|
||||
```sql
|
||||
SELECT extract('number: 1, number: 2, number: 3', '\\d+') AS result;
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```response
|
||||
┌─result─┐
|
||||
│ 1 │
|
||||
└────────┘
|
||||
```
|
||||
|
||||
## extractAll
|
||||
|
||||
Extracts all fragments of a string using a regular expression. If `haystack` does not match the `pattern` regex, an empty string is returned.
|
||||
Returns an array of all matches of a regular expression in a string. If `haystack` does not match the `pattern` regex, an empty string is returned.
|
||||
|
||||
Returns an array of strings consisting of all matches of the regex.
|
||||
|
||||
The behavior with respect to subpatterns is the same as in function `extract`.
|
||||
The behavior with respect to sub-patterns is the same as in function [`extract`](#extract).
|
||||
|
||||
**Syntax**
|
||||
|
||||
@ -876,6 +900,31 @@ The behavior with respect to subpatterns is the same as in function `extract`.
|
||||
extractAll(haystack, pattern)
|
||||
```
|
||||
|
||||
*Arguments**
|
||||
|
||||
- `haystack` — Input string. [String](../data-types/string.md).
|
||||
- `pattern` — Regular expression with [re2 regular expression syntax](https://github.com/google/re2/wiki/Syntax).
|
||||
|
||||
**Returned value**
|
||||
|
||||
- Array of matches of the regular expression in the haystack string. [Array](../data-types/array.md)([String](../data-types/string.md)).
|
||||
|
||||
**Example**
|
||||
|
||||
Query:
|
||||
|
||||
```sql
|
||||
SELECT extractAll('number: 1, number: 2, number: 3', '\\d+') AS result;
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```response
|
||||
┌─result────────┐
|
||||
│ ['1','2','3'] │
|
||||
└───────────────┘
|
||||
```
|
||||
|
||||
## extractAllGroupsHorizontal
|
||||
|
||||
Matches all groups of the `haystack` string using the `pattern` regular expression. Returns an array of arrays, where the first array includes all fragments matching the first group, the second array - matching the second group, etc.
|
||||
@ -891,7 +940,7 @@ extractAllGroupsHorizontal(haystack, pattern)
|
||||
**Arguments**
|
||||
|
||||
- `haystack` — Input string. [String](../data-types/string.md).
|
||||
- `pattern` — Regular expression with [re2 syntax](https://github.com/google/re2/wiki/Syntax). Must contain groups, each group enclosed in parentheses. If `pattern` contains no groups, an exception is thrown. [String](../data-types/string.md).
|
||||
- `pattern` — Regular expression with [re2 regular expression syntax](https://github.com/google/re2/wiki/Syntax). Must contain groups, each group enclosed in parentheses. If `pattern` contains no groups, an exception is thrown. [String](../data-types/string.md).
|
||||
|
||||
**Returned value**
|
||||
|
||||
@ -915,6 +964,39 @@ Result:
|
||||
└──────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## extractGroups
|
||||
|
||||
Match all groups of given input string with a given regular expression, returns an array of arrays of matches.
|
||||
|
||||
**Syntax**
|
||||
|
||||
``` sql
|
||||
extractGroups(haystack, pattern)
|
||||
```
|
||||
|
||||
**Arguments**
|
||||
|
||||
- `haystack` — Input string. [String](../data-types/string.md).
|
||||
- `pattern` — Regular expression with [re2 regular expression syntax](https://github.com/google/re2/wiki/Syntax). Must contain groups, each group enclosed in parentheses. If `pattern` contains no groups, an exception is thrown. [String](../data-types/string.md).
|
||||
|
||||
**Returned value**
|
||||
|
||||
- Array of arrays of matches. [Array](../data-types/array.md).
|
||||
|
||||
**Example**
|
||||
|
||||
``` sql
|
||||
SELECT extractGroups('hello abc=111 world', '("[^"]+"|\\w+)=("[^"]+"|\\w+)') AS result;
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
``` text
|
||||
┌─result────────┐
|
||||
│ ['abc','111'] │
|
||||
└───────────────┘
|
||||
```
|
||||
|
||||
## extractAllGroupsVertical
|
||||
|
||||
Matches all groups of the `haystack` string using the `pattern` regular expression. Returns an array of arrays, where each array includes matching fragments from every group. Fragments are grouped in order of appearance in the `haystack`.
|
||||
@ -928,7 +1010,7 @@ extractAllGroupsVertical(haystack, pattern)
|
||||
**Arguments**
|
||||
|
||||
- `haystack` — Input string. [String](../data-types/string.md).
|
||||
- `pattern` — Regular expression with [re2 syntax](https://github.com/google/re2/wiki/Syntax). Must contain groups, each group enclosed in parentheses. If `pattern` contains no groups, an exception is thrown. [String](../data-types/string.md).
|
||||
- `pattern` — Regular expression with [re2 regular expression syntax](https://github.com/google/re2/wiki/Syntax). Must contain groups, each group enclosed in parentheses. If `pattern` contains no groups, an exception is thrown. [String](../data-types/string.md).
|
||||
|
||||
**Returned value**
|
||||
|
||||
@ -1484,7 +1566,7 @@ countMatches(haystack, pattern)
|
||||
**Arguments**
|
||||
|
||||
- `haystack` — The string to search in. [String](../../sql-reference/syntax.md#syntax-string-literal).
|
||||
- `pattern` — The regular expression with [re2 syntax](https://github.com/google/re2/wiki/Syntax). [String](../data-types/string.md).
|
||||
- `pattern` — The regular expression with [re2 regular expression syntax](https://github.com/google/re2/wiki/Syntax). [String](../data-types/string.md).
|
||||
|
||||
**Returned value**
|
||||
|
||||
@ -1529,7 +1611,7 @@ countMatchesCaseInsensitive(haystack, pattern)
|
||||
**Arguments**
|
||||
|
||||
- `haystack` — The string to search in. [String](../../sql-reference/syntax.md#syntax-string-literal).
|
||||
- `pattern` — The regular expression with [re2 syntax](https://github.com/google/re2/wiki/Syntax). [String](../data-types/string.md).
|
||||
- `pattern` — The regular expression with [re2 regular expression syntax](https://github.com/google/re2/wiki/Syntax). [String](../data-types/string.md).
|
||||
|
||||
**Returned value**
|
||||
|
||||
|
@ -29,7 +29,7 @@ The condition could be any expression based on your requirements.
|
||||
Here is a simple example that intersects the numbers 1 to 10 with the numbers 3 to 8:
|
||||
|
||||
```sql
|
||||
SELECT number FROM numbers(1,10) INTERSECT SELECT number FROM numbers(3,6);
|
||||
SELECT number FROM numbers(1,10) INTERSECT SELECT number FROM numbers(3,8);
|
||||
```
|
||||
|
||||
Result:
|
||||
|
@ -351,11 +351,15 @@ Shows privileges for a user.
|
||||
**Syntax**
|
||||
|
||||
``` sql
|
||||
SHOW GRANTS [FOR user1 [, user2 ...]]
|
||||
SHOW GRANTS [FOR user1 [, user2 ...]] [WITH IMPLICIT] [FINAL]
|
||||
```
|
||||
|
||||
If user is not specified, the query returns privileges for the current user.
|
||||
|
||||
The `WITH IMPLICIT` modifier allows to show the implicit grants (e.g., `GRANT SELECT ON system.one`)
|
||||
|
||||
The `FINAL` modifier merges all grants from the user and its granted roles (with inheritance)
|
||||
|
||||
## SHOW CREATE USER
|
||||
|
||||
Shows parameters that were used at a [user creation](../../sql-reference/statements/create/user.md).
|
||||
|
@ -6,7 +6,7 @@ sidebar_label: "Настройки пользователей"
|
||||
|
||||
# Настройки пользователей {#nastroiki-polzovatelei}
|
||||
|
||||
Раздел `users` конфигурационного файла `user.xml` содержит настройки для пользователей.
|
||||
Раздел `users` конфигурационного файла `users.xml` содержит настройки для пользователей.
|
||||
|
||||
:::note Информация
|
||||
Для управления пользователями рекомендуется использовать [SQL-ориентированный воркфлоу](../access-rights.md#access-control), который также поддерживается в ClickHouse.
|
||||
|
@ -29,7 +29,7 @@ FROM table2
|
||||
Запрос:
|
||||
|
||||
``` sql
|
||||
SELECT number FROM numbers(1,10) INTERSECT SELECT number FROM numbers(3,6);
|
||||
SELECT number FROM numbers(1,10) INTERSECT SELECT number FROM numbers(3,8);
|
||||
```
|
||||
|
||||
Результат:
|
||||
|
@ -234,11 +234,14 @@ SHOW DICTIONARIES FROM db LIKE '%reg%' LIMIT 2
|
||||
### Синтаксис {#show-grants-syntax}
|
||||
|
||||
``` sql
|
||||
SHOW GRANTS [FOR user]
|
||||
SHOW GRANTS [FOR user1 [, user2 ...]] [WITH IMPLICIT] [FINAL]
|
||||
```
|
||||
|
||||
Если пользователь не задан, запрос возвращает привилегии текущего пользователя.
|
||||
|
||||
`WITH IMPLICIT` добавляет неявные привилегии (например `GRANT SELECT ON system.one`).
|
||||
|
||||
`FINAL` объединяет все текущие привилегии с привилегиями всех ролей пользователя (с наследованием).
|
||||
|
||||
|
||||
## SHOW CREATE USER {#show-create-user-statement}
|
||||
|
@ -8,7 +8,7 @@ sidebar_label: "\u7528\u6237\u8BBE\u7F6E"
|
||||
|
||||
# 用户设置 {#user-settings}
|
||||
|
||||
`user.xml` 中的 `users` 配置段包含了用户配置
|
||||
`users.xml` 中的 `users` 配置段包含了用户配置
|
||||
|
||||
:::note
|
||||
ClickHouse还支持 [SQL驱动的工作流](/docs/en/operations/access-rights#access-control) 用于管理用户。 我们建议使用它。
|
||||
|
@ -110,7 +110,7 @@ SHOW DICTIONARIES FROM db LIKE '%reg%' LIMIT 2
|
||||
### 语法 {#show-grants-syntax}
|
||||
|
||||
``` sql
|
||||
SHOW GRANTS [FOR user]
|
||||
SHOW GRANTS [FOR user1 [, user2 ...]] [WITH IMPLICIT] [FINAL]
|
||||
```
|
||||
|
||||
如果未指定用户,输出当前用户的权限
|
||||
|
@ -155,7 +155,7 @@ function _clickhouse_quote()
|
||||
function _clickhouse_get_options()
|
||||
{
|
||||
# By default --help will not print all settings, this is done only under --verbose
|
||||
"$@" --help --verbose 2>&1 | awk -F '[ ,=<>.]' '{ for (i=1; i <= NF; ++i) { if (substr($i, 1, 1) == "-" && length($i) > 1) print $i; } }' | sort -u
|
||||
"$@" --help --verbose 2>&1 | LANG=c awk -F '[ ,=<>.]' '{ for (i=1; i <= NF; ++i) { if (substr($i, 1, 1) == "-" && length($i) > 1) print $i; } }' | sort -u
|
||||
}
|
||||
|
||||
function _complete_for_clickhouse_generic_bin_impl()
|
||||
|
@ -445,15 +445,13 @@ private:
|
||||
shutdown = true;
|
||||
throw;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << getCurrentExceptionMessage(print_stacktrace,
|
||||
true /*check embedded stack trace*/) << std::endl;
|
||||
|
||||
size_t info_index = round_robin ? 0 : connection_index;
|
||||
++comparison_info_per_interval[info_index]->errors;
|
||||
++comparison_info_total[info_index]->errors;
|
||||
}
|
||||
std::cerr << getCurrentExceptionMessage(print_stacktrace,
|
||||
true /*check embedded stack trace*/) << std::endl;
|
||||
|
||||
size_t info_index = round_robin ? 0 : connection_index;
|
||||
++comparison_info_per_interval[info_index]->errors;
|
||||
++comparison_info_total[info_index]->errors;
|
||||
}
|
||||
// Count failed queries toward executed, so that we'd reach
|
||||
// max_iterations even if every run fails.
|
||||
|
@ -480,27 +480,23 @@ void Client::connect()
|
||||
}
|
||||
catch (const Exception & e)
|
||||
{
|
||||
/// This problem can't be fixed with reconnection so it is not attempted
|
||||
if (e.code() == DB::ErrorCodes::AUTHENTICATION_FAILED)
|
||||
{
|
||||
/// This problem can't be fixed with reconnection so it is not attempted
|
||||
throw;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (attempted_address_index == hosts_and_ports.size() - 1)
|
||||
throw;
|
||||
|
||||
if (is_interactive)
|
||||
{
|
||||
std::cerr << "Connection attempt to database at "
|
||||
<< connection_parameters.host << ":" << connection_parameters.port
|
||||
<< " resulted in failure"
|
||||
<< std::endl
|
||||
<< getExceptionMessage(e, false)
|
||||
<< std::endl
|
||||
<< "Attempting connection to the next provided address"
|
||||
<< std::endl;
|
||||
}
|
||||
if (attempted_address_index == hosts_and_ports.size() - 1)
|
||||
throw;
|
||||
|
||||
if (is_interactive)
|
||||
{
|
||||
std::cerr << "Connection attempt to database at "
|
||||
<< connection_parameters.host << ":" << connection_parameters.port
|
||||
<< " resulted in failure"
|
||||
<< std::endl
|
||||
<< getExceptionMessage(e, false)
|
||||
<< std::endl
|
||||
<< "Attempting connection to the next provided address"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ public:
|
||||
path_from,
|
||||
disk_from.getDisk()->getName());
|
||||
}
|
||||
else if (disk_from.getDisk()->isFile(path_from))
|
||||
if (disk_from.getDisk()->isFile(path_from))
|
||||
{
|
||||
auto target_location = getTargetLocation(path_from, disk_to, path_to);
|
||||
if (!disk_to.getDisk()->exists(target_location) || disk_to.getDisk()->isFile(target_location))
|
||||
@ -77,7 +77,7 @@ public:
|
||||
{
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "cannot overwrite non-directory {} with directory {}", path_to, target_location);
|
||||
}
|
||||
else if (!disk_to.getDisk()->exists(target_location))
|
||||
if (!disk_to.getDisk()->exists(target_location))
|
||||
{
|
||||
disk_to.getDisk()->createDirectory(target_location);
|
||||
}
|
||||
|
@ -72,13 +72,9 @@ private:
|
||||
auto path = [&]() -> String
|
||||
{
|
||||
if (relative_path.ends_with("/"))
|
||||
{
|
||||
return relative_path + file_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
return relative_path + "/" + file_name;
|
||||
}
|
||||
|
||||
return relative_path + "/" + file_name;
|
||||
}();
|
||||
if (disk.isDirectory(path))
|
||||
{
|
||||
|
@ -53,10 +53,8 @@ public:
|
||||
{
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "cannot move '{}' to '{}': Directory not empty", path_from, target_location);
|
||||
}
|
||||
else
|
||||
{
|
||||
disk.getDisk()->moveDirectory(path_from, target_location);
|
||||
}
|
||||
|
||||
disk.getDisk()->moveDirectory(path_from, target_location);
|
||||
}
|
||||
}
|
||||
else if (!disk.getDisk()->exists(path_from))
|
||||
|
@ -32,16 +32,14 @@ public:
|
||||
{
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Path {} on disk {} doesn't exist", path, disk.getDisk()->getName());
|
||||
}
|
||||
else if (disk.getDisk()->isDirectory(path))
|
||||
if (disk.getDisk()->isDirectory(path))
|
||||
{
|
||||
if (!recursive)
|
||||
{
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "cannot remove '{}': Is a directory", path);
|
||||
}
|
||||
else
|
||||
{
|
||||
disk.getDisk()->removeRecursive(path);
|
||||
}
|
||||
|
||||
disk.getDisk()->removeRecursive(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -33,14 +33,10 @@ public:
|
||||
auto in = [&]() -> std::unique_ptr<ReadBufferFromFileBase>
|
||||
{
|
||||
if (!path_from.has_value())
|
||||
{
|
||||
return std::make_unique<ReadBufferFromFileDescriptor>(STDIN_FILENO);
|
||||
}
|
||||
else
|
||||
{
|
||||
String relative_path_from = disk.getRelativeFromRoot(path_from.value());
|
||||
return disk.getDisk()->readFile(relative_path_from, getReadSettings());
|
||||
}
|
||||
|
||||
String relative_path_from = disk.getRelativeFromRoot(path_from.value());
|
||||
return disk.getDisk()->readFile(relative_path_from, getReadSettings());
|
||||
}();
|
||||
|
||||
auto out = disk.getDisk()->writeFile(path_to);
|
||||
|
@ -127,68 +127,58 @@ std::vector<String> DisksApp::getCompletions(const String & prefix) const
|
||||
}
|
||||
return getEmptyCompletion(command->command_name);
|
||||
}
|
||||
else if (arguments.size() == 1)
|
||||
if (arguments.size() == 1)
|
||||
{
|
||||
String command_prefix = arguments[0];
|
||||
return getCommandsToComplete(command_prefix);
|
||||
}
|
||||
else
|
||||
{
|
||||
String last_token = arguments.back();
|
||||
CommandPtr command;
|
||||
try
|
||||
{
|
||||
command = getCommandByName(arguments[0]);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return {last_token};
|
||||
}
|
||||
std::vector<String> answer = {};
|
||||
if (command->command_name == "help")
|
||||
{
|
||||
return getCommandsToComplete(last_token);
|
||||
}
|
||||
else
|
||||
{
|
||||
answer = [&]() -> std::vector<String>
|
||||
{
|
||||
if (multidisk_commands.contains(command->command_name))
|
||||
{
|
||||
return client->getAllFilesByPatternFromAllDisks(last_token);
|
||||
}
|
||||
else
|
||||
{
|
||||
return client->getCurrentDiskWithPath().getAllFilesByPattern(last_token);
|
||||
}
|
||||
}();
|
||||
|
||||
for (const auto & disk_name : client->getAllDiskNames())
|
||||
{
|
||||
if (disk_name.starts_with(last_token))
|
||||
{
|
||||
answer.push_back(disk_name);
|
||||
}
|
||||
}
|
||||
for (const auto & option : command->options_description.options())
|
||||
{
|
||||
String option_sign = "--" + option->long_name();
|
||||
if (option_sign.starts_with(last_token))
|
||||
{
|
||||
answer.push_back(option_sign);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!answer.empty())
|
||||
String last_token = arguments.back();
|
||||
CommandPtr command;
|
||||
try
|
||||
{
|
||||
command = getCommandByName(arguments[0]);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return {last_token};
|
||||
}
|
||||
|
||||
std::vector<String> answer = {};
|
||||
if (command->command_name == "help")
|
||||
return getCommandsToComplete(last_token);
|
||||
|
||||
answer = [&]() -> std::vector<String>
|
||||
{
|
||||
if (multidisk_commands.contains(command->command_name))
|
||||
return client->getAllFilesByPatternFromAllDisks(last_token);
|
||||
|
||||
return client->getCurrentDiskWithPath().getAllFilesByPattern(last_token);
|
||||
}();
|
||||
|
||||
for (const auto & disk_name : client->getAllDiskNames())
|
||||
{
|
||||
if (disk_name.starts_with(last_token))
|
||||
{
|
||||
std::sort(answer.begin(), answer.end());
|
||||
return answer;
|
||||
}
|
||||
else
|
||||
{
|
||||
return {last_token};
|
||||
answer.push_back(disk_name);
|
||||
}
|
||||
}
|
||||
for (const auto & option : command->options_description.options())
|
||||
{
|
||||
String option_sign = "--" + option->long_name();
|
||||
if (option_sign.starts_with(last_token))
|
||||
{
|
||||
answer.push_back(option_sign);
|
||||
}
|
||||
}
|
||||
|
||||
if (!answer.empty())
|
||||
{
|
||||
std::sort(answer.begin(), answer.end());
|
||||
return answer;
|
||||
}
|
||||
|
||||
return {last_token};
|
||||
}
|
||||
|
||||
bool DisksApp::processQueryText(const String & text)
|
||||
@ -210,11 +200,11 @@ bool DisksApp::processQueryText(const String & text)
|
||||
catch (DB::Exception & err)
|
||||
{
|
||||
int code = getCurrentExceptionCode();
|
||||
|
||||
if (code == ErrorCodes::LOGICAL_ERROR)
|
||||
{
|
||||
throw std::move(err);
|
||||
}
|
||||
else if (code == ErrorCodes::BAD_ARGUMENTS)
|
||||
|
||||
if (code == ErrorCodes::BAD_ARGUMENTS)
|
||||
{
|
||||
std::cerr << err.message() << "\n"
|
||||
<< "\n";
|
||||
|
@ -49,10 +49,8 @@ std::vector<String> DiskWithPath::listAllFilesByPath(const String & any_path) co
|
||||
disk->listFiles(getRelativeFromRoot(any_path), file_names);
|
||||
return file_names;
|
||||
}
|
||||
else
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<String> DiskWithPath::getAllFilesByPattern(const String & pattern) const
|
||||
@ -61,39 +59,30 @@ std::vector<String> DiskWithPath::getAllFilesByPattern(const String & pattern) c
|
||||
{
|
||||
auto slash_pos = pattern.find_last_of('/');
|
||||
if (slash_pos >= pattern.size())
|
||||
{
|
||||
return {"", pattern};
|
||||
}
|
||||
else
|
||||
{
|
||||
return {pattern.substr(0, slash_pos + 1), pattern.substr(slash_pos + 1, pattern.size() - slash_pos - 1)};
|
||||
}
|
||||
|
||||
return {pattern.substr(0, slash_pos + 1), pattern.substr(slash_pos + 1, pattern.size() - slash_pos - 1)};
|
||||
}();
|
||||
|
||||
if (!isDirectory(path_before))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
else
|
||||
|
||||
std::vector<String> file_names = listAllFilesByPath(path_before);
|
||||
std::vector<String> answer;
|
||||
|
||||
for (const auto & file_name : file_names)
|
||||
{
|
||||
std::vector<String> file_names = listAllFilesByPath(path_before);
|
||||
|
||||
std::vector<String> answer;
|
||||
|
||||
for (const auto & file_name : file_names)
|
||||
if (file_name.starts_with(path_after))
|
||||
{
|
||||
if (file_name.starts_with(path_after))
|
||||
String file_pattern = path_before + file_name;
|
||||
if (isDirectory(file_pattern))
|
||||
{
|
||||
String file_pattern = path_before + file_name;
|
||||
if (isDirectory(file_pattern))
|
||||
{
|
||||
file_pattern = file_pattern + "/";
|
||||
}
|
||||
answer.push_back(file_pattern);
|
||||
file_pattern = file_pattern + "/";
|
||||
}
|
||||
answer.push_back(file_pattern);
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
return answer;
|
||||
};
|
||||
|
||||
void DiskWithPath::setPath(const String & any_path)
|
||||
|
@ -39,13 +39,9 @@ DiskWithPath & ICommand::getDiskWithPath(DisksClient & client, const CommandLine
|
||||
{
|
||||
auto disk_name = getValueFromCommandLineOptionsWithOptional<String>(options, name);
|
||||
if (disk_name.has_value())
|
||||
{
|
||||
return client.getDiskWithPath(disk_name.value());
|
||||
}
|
||||
else
|
||||
{
|
||||
return client.getCurrentDiskWithPath();
|
||||
}
|
||||
|
||||
return client.getCurrentDiskWithPath();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -63,39 +63,27 @@ protected:
|
||||
static T getValueFromCommandLineOptionsThrow(const CommandLineOptions & options, const String & name)
|
||||
{
|
||||
if (options.count(name))
|
||||
{
|
||||
return getValueFromCommandLineOptions<T>(options, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw DB::Exception(ErrorCodes::BAD_ARGUMENTS, "Mandatory argument '{}' is missing", name);
|
||||
}
|
||||
|
||||
throw DB::Exception(ErrorCodes::BAD_ARGUMENTS, "Mandatory argument '{}' is missing", name);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T getValueFromCommandLineOptionsWithDefault(const CommandLineOptions & options, const String & name, const T & default_value)
|
||||
{
|
||||
if (options.count(name))
|
||||
{
|
||||
return getValueFromCommandLineOptions<T>(options, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
return default_value;
|
||||
}
|
||||
|
||||
return default_value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static std::optional<T> getValueFromCommandLineOptionsWithOptional(const CommandLineOptions & options, const String & name)
|
||||
{
|
||||
if (options.count(name))
|
||||
{
|
||||
return std::optional{getValueFromCommandLineOptions<T>(options, name)};
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
DiskWithPath & getDiskWithPath(DisksClient & client, const CommandLineOptions & options, const String & name);
|
||||
|
@ -110,8 +110,8 @@ static auto executeScript(const std::string & command, bool throw_on_error = fal
|
||||
sh->wait();
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return sh->tryWait();
|
||||
|
||||
return sh->tryWait();
|
||||
}
|
||||
|
||||
static bool ask(std::string question)
|
||||
|
@ -26,17 +26,15 @@ CatBoostLibraryHandlerPtr CatBoostLibraryHandlerFactory::tryGetModel(const Strin
|
||||
|
||||
if (found)
|
||||
return handler->second;
|
||||
else
|
||||
|
||||
if (create_if_not_found)
|
||||
{
|
||||
if (create_if_not_found)
|
||||
{
|
||||
auto new_handler = std::make_shared<CatBoostLibraryHandler>(library_path, model_path);
|
||||
library_handlers.emplace(model_path, new_handler);
|
||||
LOG_DEBUG(log, "Loaded catboost library handler for model path '{}'", model_path);
|
||||
return new_handler;
|
||||
}
|
||||
return nullptr;
|
||||
auto new_handler = std::make_shared<CatBoostLibraryHandler>(library_path, model_path);
|
||||
library_handlers.emplace(model_path, new_handler);
|
||||
LOG_DEBUG(log, "Loaded catboost library handler for model path '{}'", model_path);
|
||||
return new_handler;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CatBoostLibraryHandlerFactory::removeModel(const String & model_path)
|
||||
|
@ -25,7 +25,7 @@ std::unique_ptr<HTTPRequestHandler> LibraryBridgeHandlerFactory::createRequestHa
|
||||
{
|
||||
if (uri.getPath() == "/extdict_ping")
|
||||
return std::make_unique<ExternalDictionaryLibraryBridgeExistsHandler>(getContext());
|
||||
else if (uri.getPath() == "/catboost_ping")
|
||||
if (uri.getPath() == "/catboost_ping")
|
||||
return std::make_unique<CatBoostLibraryBridgeExistsHandler>(getContext());
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ std::unique_ptr<HTTPRequestHandler> LibraryBridgeHandlerFactory::createRequestHa
|
||||
{
|
||||
if (uri.getPath() == "/extdict_request")
|
||||
return std::make_unique<ExternalDictionaryLibraryBridgeRequestHandler>(getContext());
|
||||
else if (uri.getPath() == "/catboost_request")
|
||||
if (uri.getPath() == "/catboost_request")
|
||||
return std::make_unique<CatBoostLibraryBridgeRequestHandler>(getContext());
|
||||
}
|
||||
|
||||
|
@ -158,11 +158,9 @@ void ExternalDictionaryLibraryBridgeRequestHandler::handleRequest(HTTPServerRequ
|
||||
out.finalize();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_TRACE(log, "Cannot clone from dictionary with id: {}, will call extDict_libNew instead", from_dictionary_id);
|
||||
lib_new = true;
|
||||
}
|
||||
|
||||
LOG_TRACE(log, "Cannot clone from dictionary with id: {}, will call extDict_libNew instead", from_dictionary_id);
|
||||
lib_new = true;
|
||||
}
|
||||
if (lib_new)
|
||||
{
|
||||
|
@ -231,8 +231,8 @@ static Int64 transformSigned(Int64 x, UInt64 seed)
|
||||
{
|
||||
if (x >= 0)
|
||||
return transform(x, seed);
|
||||
else
|
||||
return -transform(-x, seed); /// It works Ok even for minimum signed number.
|
||||
|
||||
return -transform(-x, seed); /// It works Ok even for minimum signed number.
|
||||
}
|
||||
|
||||
|
||||
@ -1105,8 +1105,8 @@ public:
|
||||
{
|
||||
if (isUInt(data_type))
|
||||
return std::make_unique<UnsignedIntegerModel>(seed);
|
||||
else
|
||||
return std::make_unique<SignedIntegerModel>(seed);
|
||||
|
||||
return std::make_unique<SignedIntegerModel>(seed);
|
||||
}
|
||||
|
||||
if (typeid_cast<const DataTypeFloat32 *>(&data_type))
|
||||
|
@ -39,13 +39,13 @@ IdentifierQuotingStyle getQuotingStyle(nanodbc::ConnectionHolderPtr connection)
|
||||
auto identifier_quote = getIdentifierQuote(connection);
|
||||
if (identifier_quote.empty())
|
||||
return IdentifierQuotingStyle::Backticks;
|
||||
else if (identifier_quote[0] == '`')
|
||||
if (identifier_quote[0] == '`')
|
||||
return IdentifierQuotingStyle::Backticks;
|
||||
else if (identifier_quote[0] == '"')
|
||||
if (identifier_quote[0] == '"')
|
||||
return IdentifierQuotingStyle::DoubleQuotes;
|
||||
else
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
|
||||
"Can not map quote identifier '{}' to IdentifierQuotingStyle value", identifier_quote);
|
||||
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
|
||||
"Can not map quote identifier '{}' to IdentifierQuotingStyle value", identifier_quote);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -127,8 +127,8 @@ std::string validateODBCConnectionString(const std::string & connection_string)
|
||||
|
||||
if (*pos == '{')
|
||||
return read_escaped_value();
|
||||
else
|
||||
return read_plain_value();
|
||||
|
||||
return read_plain_value();
|
||||
};
|
||||
|
||||
std::map<std::string, std::string> parameters;
|
||||
@ -206,12 +206,10 @@ std::string validateODBCConnectionString(const std::string & connection_string)
|
||||
reconstructed_connection_string.append(value_pos, next_pos - value_pos);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
reconstructed_connection_string.append(value_pos, next_pos - value_pos);
|
||||
reconstructed_connection_string.append("}}");
|
||||
value_pos = next_pos + 1;
|
||||
}
|
||||
|
||||
reconstructed_connection_string.append(value_pos, next_pos - value_pos);
|
||||
reconstructed_connection_string.append("}}");
|
||||
value_pos = next_pos + 1;
|
||||
}
|
||||
|
||||
reconstructed_connection_string += '}';
|
||||
|
@ -69,6 +69,7 @@
|
||||
#include <Interpreters/registerInterpreters.h>
|
||||
#include <Interpreters/JIT/CompiledExpressionCache.h>
|
||||
#include <Access/AccessControl.h>
|
||||
#include <Storages/MaterializedView/RefreshSet.h>
|
||||
#include <Storages/MergeTree/MergeTreeSettings.h>
|
||||
#include <Storages/StorageReplicatedMergeTree.h>
|
||||
#include <Storages/System/attachSystemTables.h>
|
||||
@ -2083,6 +2084,12 @@ try
|
||||
|
||||
try
|
||||
{
|
||||
/// Don't run background queries until we loaded tables.
|
||||
/// (In particular things would break if a background drop query happens before the
|
||||
/// loadMarkedAsDroppedTables() call below - it'll see dropped table metadata and try to
|
||||
/// drop the table a second time and throw an exception.)
|
||||
global_context->getRefreshSet().setRefreshesStopped(true);
|
||||
|
||||
auto & database_catalog = DatabaseCatalog::instance();
|
||||
/// We load temporary database first, because projections need it.
|
||||
database_catalog.initializeAndLoadTemporaryDatabase();
|
||||
@ -2122,6 +2129,8 @@ try
|
||||
database_catalog.assertDatabaseExists(default_database);
|
||||
/// Load user-defined SQL functions.
|
||||
global_context->getUserDefinedSQLObjectsStorage().loadObjects();
|
||||
|
||||
global_context->getRefreshSet().setRefreshesStopped(false);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
@ -116,16 +116,14 @@ namespace
|
||||
reading_dependents = false;
|
||||
continue;
|
||||
}
|
||||
else if (line == "DEPENDENTS")
|
||||
if (line == "DEPENDENTS")
|
||||
{
|
||||
reading_dependents = true;
|
||||
reading_dependencies = false;
|
||||
continue;
|
||||
}
|
||||
else if (line.empty())
|
||||
{
|
||||
if (line.empty())
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t separator1 = line.find('\t');
|
||||
size_t separator2 = line.find('\t', separator1 + 1);
|
||||
|
@ -134,8 +134,8 @@ public:
|
||||
"' registered for user-defined settings",
|
||||
String{setting_name}, boost::algorithm::join(registered_prefixes, "' or '"));
|
||||
}
|
||||
else
|
||||
throw Exception(ErrorCodes::UNKNOWN_SETTING, "Unknown setting '{}'", String{setting_name});
|
||||
|
||||
throw Exception(ErrorCodes::UNKNOWN_SETTING, "Unknown setting '{}'", String{setting_name});
|
||||
}
|
||||
|
||||
private:
|
||||
@ -830,8 +830,7 @@ std::shared_ptr<const EnabledQuota> AccessControl::getAuthenticationQuota(
|
||||
quota_key,
|
||||
throw_if_client_key_empty);
|
||||
}
|
||||
else
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1155,9 +1155,6 @@ private:
|
||||
|
||||
calculateMinMaxFlags();
|
||||
|
||||
if (!isLeaf())
|
||||
return;
|
||||
|
||||
auto new_flags = function(flags, min_flags_with_children, max_flags_with_children, level, grant_option);
|
||||
|
||||
if (new_flags != flags)
|
||||
@ -1483,17 +1480,17 @@ bool AccessRights::isGrantedImplHelper(const AccessRightsElement & element) cons
|
||||
{
|
||||
if (element.anyParameter())
|
||||
return isGrantedImpl<grant_option, wildcard>(element.access_flags);
|
||||
else
|
||||
return isGrantedImpl<grant_option, wildcard>(element.access_flags, element.parameter);
|
||||
|
||||
return isGrantedImpl<grant_option, wildcard>(element.access_flags, element.parameter);
|
||||
}
|
||||
else if (element.anyDatabase())
|
||||
if (element.anyDatabase())
|
||||
return isGrantedImpl<grant_option, wildcard>(element.access_flags);
|
||||
else if (element.anyTable())
|
||||
if (element.anyTable())
|
||||
return isGrantedImpl<grant_option, wildcard>(element.access_flags, element.database);
|
||||
else if (element.anyColumn())
|
||||
if (element.anyColumn())
|
||||
return isGrantedImpl<grant_option, wildcard>(element.access_flags, element.database, element.table);
|
||||
else
|
||||
return isGrantedImpl<grant_option, wildcard>(element.access_flags, element.database, element.table, element.columns);
|
||||
|
||||
return isGrantedImpl<grant_option, wildcard>(element.access_flags, element.database, element.table, element.columns);
|
||||
}
|
||||
|
||||
template <bool grant_option, bool wildcard>
|
||||
@ -1503,16 +1500,14 @@ bool AccessRights::isGrantedImpl(const AccessRightsElement & element) const
|
||||
{
|
||||
if (element.grant_option)
|
||||
return isGrantedImplHelper<true, true>(element);
|
||||
else
|
||||
return isGrantedImplHelper<grant_option, true>(element);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (element.grant_option)
|
||||
return isGrantedImplHelper<true, wildcard>(element);
|
||||
else
|
||||
return isGrantedImplHelper<grant_option, wildcard>(element);
|
||||
|
||||
return isGrantedImplHelper<grant_option, true>(element);
|
||||
}
|
||||
|
||||
if (element.grant_option)
|
||||
return isGrantedImplHelper<true, wildcard>(element);
|
||||
|
||||
return isGrantedImplHelper<grant_option, wildcard>(element);
|
||||
}
|
||||
|
||||
template <bool grant_option, bool wildcard>
|
||||
|
@ -501,10 +501,9 @@ AuthenticationData AuthenticationData::fromAST(const ASTAuthenticationData & que
|
||||
auth_data.setPasswordHashBinary(AuthenticationData::Util::stringToDigest(value));
|
||||
return auth_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
auth_data.setPasswordHashHex(value);
|
||||
}
|
||||
|
||||
auth_data.setPasswordHashHex(value);
|
||||
|
||||
|
||||
if (query.type == AuthenticationType::SHA256_PASSWORD && args_size == 2)
|
||||
{
|
||||
|
@ -247,8 +247,7 @@ namespace
|
||||
const auto & unused_node = *(owned_nodes.begin()->second);
|
||||
if (unused_node.node_type == UNKNOWN)
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Parent group '{}' not found", unused_node.keyword);
|
||||
else
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Access type '{}' should have parent group", unused_node.keyword);
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Access type '{}' should have parent group", unused_node.keyword);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ namespace
|
||||
{
|
||||
if (addr.family() == IPAddress::Family::IPv4 && addr_v6 == toIPv6(addr))
|
||||
return true;
|
||||
else if (addr.family() == IPAddress::Family::IPv6 && addr_v6 == addr)
|
||||
if (addr.family() == IPAddress::Family::IPv6 && addr_v6 == addr)
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -267,10 +267,9 @@ String AllowedClientHosts::IPSubnet::toString() const
|
||||
unsigned int prefix_length = mask.prefixLength();
|
||||
if (isMaskAllBitsOne())
|
||||
return prefix.toString();
|
||||
else if (IPAddress{prefix_length, mask.family()} == mask)
|
||||
if (IPAddress{prefix_length, mask.family()} == mask)
|
||||
return fs::path(prefix.toString()) / std::to_string(prefix_length);
|
||||
else
|
||||
return fs::path(prefix.toString()) / mask.toString();
|
||||
return fs::path(prefix.toString()) / mask.toString();
|
||||
}
|
||||
|
||||
bool AllowedClientHosts::IPSubnet::isMaskAllBitsOne() const
|
||||
@ -575,12 +574,11 @@ bool AllowedClientHosts::contains(const IPAddress & client_address) const
|
||||
parseLikePattern(pattern, subnet, name, name_regexp);
|
||||
if (subnet)
|
||||
return check_subnet(*subnet);
|
||||
else if (name)
|
||||
if (name)
|
||||
return check_name(*name);
|
||||
else if (name_regexp)
|
||||
if (name_regexp)
|
||||
return check_name_regexp(*name_regexp);
|
||||
else
|
||||
return false;
|
||||
return false;
|
||||
};
|
||||
|
||||
for (const String & like_pattern : like_patterns)
|
||||
|
@ -28,16 +28,14 @@ String QuotaTypeInfo::valueToString(QuotaValue value) const
|
||||
{
|
||||
if (!(value % output_denominator))
|
||||
return std::to_string(value / output_denominator);
|
||||
else
|
||||
return toString(static_cast<double>(value) / output_denominator);
|
||||
return toString(static_cast<double>(value) / output_denominator);
|
||||
}
|
||||
|
||||
QuotaValue QuotaTypeInfo::stringToValue(const String & str) const
|
||||
{
|
||||
if (output_denominator == 1)
|
||||
return static_cast<QuotaValue>(parse<UInt64>(str));
|
||||
else
|
||||
return static_cast<QuotaValue>(parse<Float64>(str) * output_denominator);
|
||||
return static_cast<QuotaValue>(parse<Float64>(str) * output_denominator);
|
||||
}
|
||||
|
||||
String QuotaTypeInfo::valueToStringWithName(QuotaValue value) const
|
||||
|
@ -64,196 +64,6 @@ namespace
|
||||
}
|
||||
|
||||
|
||||
AccessRights addImplicitAccessRights(const AccessRights & access, const AccessControl & access_control)
|
||||
{
|
||||
AccessFlags max_flags;
|
||||
|
||||
auto modifier = [&](const AccessFlags & flags,
|
||||
const AccessFlags & min_flags_with_children,
|
||||
const AccessFlags & max_flags_with_children,
|
||||
const size_t level,
|
||||
bool /* grant_option */) -> AccessFlags
|
||||
{
|
||||
AccessFlags res = flags;
|
||||
|
||||
/// CREATE_TABLE => CREATE_VIEW, DROP_TABLE => DROP_VIEW, ALTER_TABLE => ALTER_VIEW
|
||||
static const AccessFlags create_table = AccessType::CREATE_TABLE;
|
||||
static const AccessFlags create_view = AccessType::CREATE_VIEW;
|
||||
static const AccessFlags drop_table = AccessType::DROP_TABLE;
|
||||
static const AccessFlags drop_view = AccessType::DROP_VIEW;
|
||||
static const AccessFlags alter_table = AccessType::ALTER_TABLE;
|
||||
static const AccessFlags alter_view = AccessType::ALTER_VIEW;
|
||||
|
||||
if (res & create_table)
|
||||
res |= create_view;
|
||||
|
||||
if (res & drop_table)
|
||||
res |= drop_view;
|
||||
|
||||
if (res & alter_table)
|
||||
res |= alter_view;
|
||||
|
||||
/// CREATE TABLE (on any database/table) => CREATE_TEMPORARY_TABLE (global)
|
||||
static const AccessFlags create_temporary_table = AccessType::CREATE_TEMPORARY_TABLE;
|
||||
if ((level == 0) && (max_flags_with_children & create_table))
|
||||
res |= create_temporary_table;
|
||||
|
||||
/// CREATE TABLE (on any database/table) => CREATE_ARBITRARY_TEMPORARY_TABLE (global)
|
||||
static const AccessFlags create_arbitrary_temporary_table = AccessType::CREATE_ARBITRARY_TEMPORARY_TABLE;
|
||||
if ((level == 0) && (max_flags_with_children & create_table))
|
||||
res |= create_arbitrary_temporary_table;
|
||||
|
||||
/// ALTER_TTL => ALTER_MATERIALIZE_TTL
|
||||
static const AccessFlags alter_ttl = AccessType::ALTER_TTL;
|
||||
static const AccessFlags alter_materialize_ttl = AccessType::ALTER_MATERIALIZE_TTL;
|
||||
if (res & alter_ttl)
|
||||
res |= alter_materialize_ttl;
|
||||
|
||||
/// RELOAD_DICTIONARY (global) => RELOAD_EMBEDDED_DICTIONARIES (global)
|
||||
static const AccessFlags reload_dictionary = AccessType::SYSTEM_RELOAD_DICTIONARY;
|
||||
static const AccessFlags reload_embedded_dictionaries = AccessType::SYSTEM_RELOAD_EMBEDDED_DICTIONARIES;
|
||||
if ((level == 0) && (min_flags_with_children & reload_dictionary))
|
||||
res |= reload_embedded_dictionaries;
|
||||
|
||||
/// any column flag => SHOW_COLUMNS => SHOW_TABLES => SHOW_DATABASES
|
||||
/// any table flag => SHOW_TABLES => SHOW_DATABASES
|
||||
/// any dictionary flag => SHOW_DICTIONARIES => SHOW_DATABASES
|
||||
/// any database flag => SHOW_DATABASES
|
||||
static const AccessFlags show_columns = AccessType::SHOW_COLUMNS;
|
||||
static const AccessFlags show_tables = AccessType::SHOW_TABLES;
|
||||
static const AccessFlags show_dictionaries = AccessType::SHOW_DICTIONARIES;
|
||||
static const AccessFlags show_tables_or_dictionaries = show_tables | show_dictionaries;
|
||||
static const AccessFlags show_databases = AccessType::SHOW_DATABASES;
|
||||
|
||||
if (res & AccessFlags::allColumnFlags())
|
||||
res |= show_columns;
|
||||
|
||||
if ((res & AccessFlags::allTableFlags())
|
||||
|| (level <= 2 && (res & show_columns))
|
||||
|| (level == 2 && (max_flags_with_children & show_columns)))
|
||||
{
|
||||
res |= show_tables;
|
||||
}
|
||||
|
||||
if (res & AccessFlags::allDictionaryFlags())
|
||||
res |= show_dictionaries;
|
||||
|
||||
if ((res & AccessFlags::allDatabaseFlags())
|
||||
|| (level <= 1 && (res & show_tables_or_dictionaries))
|
||||
|| (level == 1 && (max_flags_with_children & show_tables_or_dictionaries)))
|
||||
{
|
||||
res |= show_databases;
|
||||
}
|
||||
|
||||
max_flags |= res;
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
AccessRights res = access;
|
||||
res.modifyFlags(modifier);
|
||||
|
||||
/// If "select_from_system_db_requires_grant" is enabled we provide implicit grants only for a few tables in the system database.
|
||||
if (access_control.doesSelectFromSystemDatabaseRequireGrant())
|
||||
{
|
||||
const char * always_accessible_tables[] = {
|
||||
/// Constant tables
|
||||
"one",
|
||||
|
||||
/// "numbers", "numbers_mt", "zeros", "zeros_mt" were excluded because they can generate lots of values and
|
||||
/// that can decrease performance in some cases.
|
||||
|
||||
"contributors",
|
||||
"licenses",
|
||||
"time_zones",
|
||||
"collations",
|
||||
|
||||
"formats",
|
||||
"privileges",
|
||||
"data_type_families",
|
||||
"database_engines",
|
||||
"table_engines",
|
||||
"table_functions",
|
||||
"aggregate_function_combinators",
|
||||
|
||||
"functions", /// Can contain user-defined functions
|
||||
|
||||
/// The following tables hide some rows if the current user doesn't have corresponding SHOW privileges.
|
||||
"databases",
|
||||
"tables",
|
||||
"columns",
|
||||
|
||||
/// Specific to the current session
|
||||
"settings",
|
||||
"current_roles",
|
||||
"enabled_roles",
|
||||
"quota_usage"
|
||||
};
|
||||
|
||||
for (const auto * table_name : always_accessible_tables)
|
||||
res.grant(AccessType::SELECT, DatabaseCatalog::SYSTEM_DATABASE, table_name);
|
||||
|
||||
if (max_flags.contains(AccessType::SHOW_USERS))
|
||||
res.grant(AccessType::SELECT, DatabaseCatalog::SYSTEM_DATABASE, "users");
|
||||
|
||||
if (max_flags.contains(AccessType::SHOW_ROLES))
|
||||
res.grant(AccessType::SELECT, DatabaseCatalog::SYSTEM_DATABASE, "roles");
|
||||
|
||||
if (max_flags.contains(AccessType::SHOW_ROW_POLICIES))
|
||||
res.grant(AccessType::SELECT, DatabaseCatalog::SYSTEM_DATABASE, "row_policies");
|
||||
|
||||
if (max_flags.contains(AccessType::SHOW_SETTINGS_PROFILES))
|
||||
res.grant(AccessType::SELECT, DatabaseCatalog::SYSTEM_DATABASE, "settings_profiles");
|
||||
|
||||
if (max_flags.contains(AccessType::SHOW_QUOTAS))
|
||||
res.grant(AccessType::SELECT, DatabaseCatalog::SYSTEM_DATABASE, "quotas");
|
||||
}
|
||||
else
|
||||
{
|
||||
res.grant(AccessType::SELECT, DatabaseCatalog::SYSTEM_DATABASE);
|
||||
}
|
||||
|
||||
/// If "select_from_information_schema_requires_grant" is enabled we don't provide implicit grants for the information_schema database.
|
||||
if (!access_control.doesSelectFromInformationSchemaRequireGrant())
|
||||
{
|
||||
res.grant(AccessType::SELECT, DatabaseCatalog::INFORMATION_SCHEMA);
|
||||
res.grant(AccessType::SELECT, DatabaseCatalog::INFORMATION_SCHEMA_UPPERCASE);
|
||||
}
|
||||
|
||||
/// There is overlap between AccessType sources and table engines, so the following code avoids user granting twice.
|
||||
|
||||
/// Sync SOURCE and TABLE_ENGINE, so only need to check TABLE_ENGINE later.
|
||||
if (access_control.doesTableEnginesRequireGrant())
|
||||
{
|
||||
for (const auto & source_and_table_engine : source_and_table_engines)
|
||||
{
|
||||
const auto & source = std::get<0>(source_and_table_engine);
|
||||
if (res.isGranted(source))
|
||||
{
|
||||
const auto & table_engine = std::get<1>(source_and_table_engine);
|
||||
res.grant(AccessType::TABLE_ENGINE, table_engine);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Add TABLE_ENGINE on * and then remove TABLE_ENGINE on particular engines.
|
||||
res.grant(AccessType::TABLE_ENGINE);
|
||||
for (const auto & source_and_table_engine : source_and_table_engines)
|
||||
{
|
||||
const auto & source = std::get<0>(source_and_table_engine);
|
||||
if (!res.isGranted(source))
|
||||
{
|
||||
const auto & table_engine = std::get<1>(source_and_table_engine);
|
||||
res.revoke(AccessType::TABLE_ENGINE, table_engine);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
std::array<UUID, 1> to_array(const UUID & id)
|
||||
{
|
||||
std::array<UUID, 1> ids;
|
||||
@ -274,6 +84,196 @@ namespace
|
||||
}
|
||||
|
||||
|
||||
AccessRights ContextAccess::addImplicitAccessRights(const AccessRights & access, const AccessControl & access_control)
|
||||
{
|
||||
AccessFlags max_flags;
|
||||
|
||||
auto modifier = [&](const AccessFlags & flags,
|
||||
const AccessFlags & min_flags_with_children,
|
||||
const AccessFlags & max_flags_with_children,
|
||||
const size_t level,
|
||||
bool /* grant_option */) -> AccessFlags
|
||||
{
|
||||
AccessFlags res = flags;
|
||||
|
||||
/// CREATE_TABLE => CREATE_VIEW, DROP_TABLE => DROP_VIEW, ALTER_TABLE => ALTER_VIEW
|
||||
static const AccessFlags create_table = AccessType::CREATE_TABLE;
|
||||
static const AccessFlags create_view = AccessType::CREATE_VIEW;
|
||||
static const AccessFlags drop_table = AccessType::DROP_TABLE;
|
||||
static const AccessFlags drop_view = AccessType::DROP_VIEW;
|
||||
static const AccessFlags alter_table = AccessType::ALTER_TABLE;
|
||||
static const AccessFlags alter_view = AccessType::ALTER_VIEW;
|
||||
|
||||
if (res & create_table)
|
||||
res |= create_view;
|
||||
|
||||
if (res & drop_table)
|
||||
res |= drop_view;
|
||||
|
||||
if (res & alter_table)
|
||||
res |= alter_view;
|
||||
|
||||
/// CREATE TABLE (on any database/table) => CREATE_TEMPORARY_TABLE (global)
|
||||
static const AccessFlags create_temporary_table = AccessType::CREATE_TEMPORARY_TABLE;
|
||||
if ((level == 0) && (max_flags_with_children & create_table))
|
||||
res |= create_temporary_table;
|
||||
|
||||
/// CREATE TABLE (on any database/table) => CREATE_ARBITRARY_TEMPORARY_TABLE (global)
|
||||
static const AccessFlags create_arbitrary_temporary_table = AccessType::CREATE_ARBITRARY_TEMPORARY_TABLE;
|
||||
if ((level == 0) && (max_flags_with_children & create_table))
|
||||
res |= create_arbitrary_temporary_table;
|
||||
|
||||
/// ALTER_TTL => ALTER_MATERIALIZE_TTL
|
||||
static const AccessFlags alter_ttl = AccessType::ALTER_TTL;
|
||||
static const AccessFlags alter_materialize_ttl = AccessType::ALTER_MATERIALIZE_TTL;
|
||||
if (res & alter_ttl)
|
||||
res |= alter_materialize_ttl;
|
||||
|
||||
/// RELOAD_DICTIONARY (global) => RELOAD_EMBEDDED_DICTIONARIES (global)
|
||||
static const AccessFlags reload_dictionary = AccessType::SYSTEM_RELOAD_DICTIONARY;
|
||||
static const AccessFlags reload_embedded_dictionaries = AccessType::SYSTEM_RELOAD_EMBEDDED_DICTIONARIES;
|
||||
if ((level == 0) && (min_flags_with_children & reload_dictionary))
|
||||
res |= reload_embedded_dictionaries;
|
||||
|
||||
/// any column flag => SHOW_COLUMNS => SHOW_TABLES => SHOW_DATABASES
|
||||
/// any table flag => SHOW_TABLES => SHOW_DATABASES
|
||||
/// any dictionary flag => SHOW_DICTIONARIES => SHOW_DATABASES
|
||||
/// any database flag => SHOW_DATABASES
|
||||
static const AccessFlags show_columns = AccessType::SHOW_COLUMNS;
|
||||
static const AccessFlags show_tables = AccessType::SHOW_TABLES;
|
||||
static const AccessFlags show_dictionaries = AccessType::SHOW_DICTIONARIES;
|
||||
static const AccessFlags show_tables_or_dictionaries = show_tables | show_dictionaries;
|
||||
static const AccessFlags show_databases = AccessType::SHOW_DATABASES;
|
||||
|
||||
if (res & AccessFlags::allColumnFlags())
|
||||
res |= show_columns;
|
||||
|
||||
if ((res & AccessFlags::allTableFlags())
|
||||
|| (level <= 2 && (res & show_columns))
|
||||
|| (level == 2 && (max_flags_with_children & show_columns)))
|
||||
{
|
||||
res |= show_tables;
|
||||
}
|
||||
|
||||
if (res & AccessFlags::allDictionaryFlags())
|
||||
res |= show_dictionaries;
|
||||
|
||||
if ((res & AccessFlags::allDatabaseFlags())
|
||||
|| (level <= 1 && (res & show_tables_or_dictionaries))
|
||||
|| (level == 1 && (max_flags_with_children & show_tables_or_dictionaries)))
|
||||
{
|
||||
res |= show_databases;
|
||||
}
|
||||
|
||||
max_flags |= res;
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
AccessRights res = access;
|
||||
res.modifyFlags(modifier);
|
||||
|
||||
/// If "select_from_system_db_requires_grant" is enabled we provide implicit grants only for a few tables in the system database.
|
||||
if (access_control.doesSelectFromSystemDatabaseRequireGrant())
|
||||
{
|
||||
const char * always_accessible_tables[] = {
|
||||
/// Constant tables
|
||||
"one",
|
||||
|
||||
/// "numbers", "numbers_mt", "zeros", "zeros_mt" were excluded because they can generate lots of values and
|
||||
/// that can decrease performance in some cases.
|
||||
|
||||
"contributors",
|
||||
"licenses",
|
||||
"time_zones",
|
||||
"collations",
|
||||
|
||||
"formats",
|
||||
"privileges",
|
||||
"data_type_families",
|
||||
"database_engines",
|
||||
"table_engines",
|
||||
"table_functions",
|
||||
"aggregate_function_combinators",
|
||||
|
||||
"functions", /// Can contain user-defined functions
|
||||
|
||||
/// The following tables hide some rows if the current user doesn't have corresponding SHOW privileges.
|
||||
"databases",
|
||||
"tables",
|
||||
"columns",
|
||||
|
||||
/// Specific to the current session
|
||||
"settings",
|
||||
"current_roles",
|
||||
"enabled_roles",
|
||||
"quota_usage"
|
||||
};
|
||||
|
||||
for (const auto * table_name : always_accessible_tables)
|
||||
res.grant(AccessType::SELECT, DatabaseCatalog::SYSTEM_DATABASE, table_name);
|
||||
|
||||
if (max_flags.contains(AccessType::SHOW_USERS))
|
||||
res.grant(AccessType::SELECT, DatabaseCatalog::SYSTEM_DATABASE, "users");
|
||||
|
||||
if (max_flags.contains(AccessType::SHOW_ROLES))
|
||||
res.grant(AccessType::SELECT, DatabaseCatalog::SYSTEM_DATABASE, "roles");
|
||||
|
||||
if (max_flags.contains(AccessType::SHOW_ROW_POLICIES))
|
||||
res.grant(AccessType::SELECT, DatabaseCatalog::SYSTEM_DATABASE, "row_policies");
|
||||
|
||||
if (max_flags.contains(AccessType::SHOW_SETTINGS_PROFILES))
|
||||
res.grant(AccessType::SELECT, DatabaseCatalog::SYSTEM_DATABASE, "settings_profiles");
|
||||
|
||||
if (max_flags.contains(AccessType::SHOW_QUOTAS))
|
||||
res.grant(AccessType::SELECT, DatabaseCatalog::SYSTEM_DATABASE, "quotas");
|
||||
}
|
||||
else
|
||||
{
|
||||
res.grant(AccessType::SELECT, DatabaseCatalog::SYSTEM_DATABASE);
|
||||
}
|
||||
|
||||
/// If "select_from_information_schema_requires_grant" is enabled we don't provide implicit grants for the information_schema database.
|
||||
if (!access_control.doesSelectFromInformationSchemaRequireGrant())
|
||||
{
|
||||
res.grant(AccessType::SELECT, DatabaseCatalog::INFORMATION_SCHEMA);
|
||||
res.grant(AccessType::SELECT, DatabaseCatalog::INFORMATION_SCHEMA_UPPERCASE);
|
||||
}
|
||||
|
||||
/// There is overlap between AccessType sources and table engines, so the following code avoids user granting twice.
|
||||
|
||||
/// Sync SOURCE and TABLE_ENGINE, so only need to check TABLE_ENGINE later.
|
||||
if (access_control.doesTableEnginesRequireGrant())
|
||||
{
|
||||
for (const auto & source_and_table_engine : source_and_table_engines)
|
||||
{
|
||||
const auto & source = std::get<0>(source_and_table_engine);
|
||||
if (res.isGranted(source))
|
||||
{
|
||||
const auto & table_engine = std::get<1>(source_and_table_engine);
|
||||
res.grant(AccessType::TABLE_ENGINE, table_engine);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Add TABLE_ENGINE on * and then remove TABLE_ENGINE on particular engines.
|
||||
res.grant(AccessType::TABLE_ENGINE);
|
||||
for (const auto & source_and_table_engine : source_and_table_engines)
|
||||
{
|
||||
const auto & source = std::get<0>(source_and_table_engine);
|
||||
if (!res.isGranted(source))
|
||||
{
|
||||
const auto & table_engine = std::get<1>(source_and_table_engine);
|
||||
res.revoke(AccessType::TABLE_ENGINE, table_engine);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<const ContextAccess> ContextAccess::fromContext(const ContextPtr & context)
|
||||
{
|
||||
return ContextAccessWrapper::fromContext(context)->getAccess();
|
||||
@ -728,8 +728,7 @@ bool ContextAccess::checkAccessImplHelper(const ContextPtr & context, AccessFlag
|
||||
"For queries over HTTP, method GET implies readonly. "
|
||||
"You should use method POST for modifying queries");
|
||||
}
|
||||
else
|
||||
return access_denied(ErrorCodes::READONLY, "{}: Cannot execute query in readonly mode");
|
||||
return access_denied(ErrorCodes::READONLY, "{}: Cannot execute query in readonly mode");
|
||||
}
|
||||
}
|
||||
|
||||
@ -770,17 +769,17 @@ bool ContextAccess::checkAccessImplHelper(const ContextPtr & context, const Acce
|
||||
{
|
||||
if (element.anyParameter())
|
||||
return checkAccessImpl<throw_if_denied, grant_option, wildcard>(context, element.access_flags);
|
||||
else
|
||||
return checkAccessImpl<throw_if_denied, grant_option, wildcard>(context, element.access_flags, element.parameter);
|
||||
|
||||
return checkAccessImpl<throw_if_denied, grant_option, wildcard>(context, element.access_flags, element.parameter);
|
||||
}
|
||||
else if (element.anyDatabase())
|
||||
if (element.anyDatabase())
|
||||
return checkAccessImpl<throw_if_denied, grant_option, wildcard>(context, element.access_flags);
|
||||
else if (element.anyTable())
|
||||
if (element.anyTable())
|
||||
return checkAccessImpl<throw_if_denied, grant_option, wildcard>(context, element.access_flags, element.database);
|
||||
else if (element.anyColumn())
|
||||
if (element.anyColumn())
|
||||
return checkAccessImpl<throw_if_denied, grant_option, wildcard>(context, element.access_flags, element.database, element.table);
|
||||
else
|
||||
return checkAccessImpl<throw_if_denied, grant_option, wildcard>(context, element.access_flags, element.database, element.table, element.columns);
|
||||
|
||||
return checkAccessImpl<throw_if_denied, grant_option, wildcard>(context, element.access_flags, element.database, element.table, element.columns);
|
||||
}
|
||||
|
||||
template <bool throw_if_denied, bool grant_option, bool wildcard>
|
||||
@ -790,16 +789,14 @@ bool ContextAccess::checkAccessImpl(const ContextPtr & context, const AccessRigh
|
||||
{
|
||||
if (element.grant_option)
|
||||
return checkAccessImplHelper<throw_if_denied, true, true>(context, element);
|
||||
else
|
||||
return checkAccessImplHelper<throw_if_denied, grant_option, true>(context, element);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (element.grant_option)
|
||||
return checkAccessImplHelper<throw_if_denied, true, wildcard>(context, element);
|
||||
else
|
||||
return checkAccessImplHelper<throw_if_denied, grant_option, wildcard>(context, element);
|
||||
|
||||
return checkAccessImplHelper<throw_if_denied, grant_option, true>(context, element);
|
||||
}
|
||||
|
||||
if (element.grant_option)
|
||||
return checkAccessImplHelper<throw_if_denied, true, wildcard>(context, element);
|
||||
|
||||
return checkAccessImplHelper<throw_if_denied, grant_option, wildcard>(context, element);
|
||||
}
|
||||
|
||||
template <bool throw_if_denied, bool grant_option, bool wildcard>
|
||||
|
@ -132,6 +132,8 @@ public:
|
||||
/// Checks if grantees are allowed for the current user, throws an exception if not.
|
||||
void checkGranteesAreAllowed(const std::vector<UUID> & grantee_ids) const;
|
||||
|
||||
static AccessRights addImplicitAccessRights(const AccessRights & access, const AccessControl & access_control);
|
||||
|
||||
ContextAccess(const AccessControl & access_control_, const Params & params_);
|
||||
~ContextAccess();
|
||||
|
||||
|
@ -89,10 +89,9 @@ bool operator ==(const ContextAccessParams & left, const ContextAccessParams & r
|
||||
{
|
||||
if (!x)
|
||||
return !y;
|
||||
else if (!y)
|
||||
if (!y)
|
||||
return false;
|
||||
else
|
||||
return *x == *y;
|
||||
return *x == *y;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -132,23 +131,21 @@ bool operator <(const ContextAccessParams & left, const ContextAccessParams & ri
|
||||
{
|
||||
if (!x)
|
||||
return y ? -1 : 0;
|
||||
else if (!y)
|
||||
if (!y)
|
||||
return 1;
|
||||
else if (*x == *y)
|
||||
if (*x == *y)
|
||||
return 0;
|
||||
else if (*x < *y)
|
||||
if (*x < *y)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x == y)
|
||||
return 0;
|
||||
else if (x < y)
|
||||
if (x < y)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -166,8 +166,7 @@ void KerberosInit::init(const String & keytab_file, const String & principal, co
|
||||
ret = krb5_get_init_creds_keytab(k5.ctx, &my_creds, k5.me, keytab, 0, nullptr, options);
|
||||
if (ret)
|
||||
throw Exception(ErrorCodes::KERBEROS_ERROR, "Error in getting initial credentials: {}", fmtError(ret));
|
||||
else
|
||||
LOG_TRACE(log,"Got initial credentials");
|
||||
LOG_TRACE(log, "Got initial credentials");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -330,10 +330,7 @@ std::set<String> LDAPAccessStorage::mapExternalRolesNoLock(const LDAPClient::Sea
|
||||
|
||||
for (const auto & external_role : external_role_set)
|
||||
{
|
||||
if (
|
||||
prefix.size() < external_role.size() &&
|
||||
external_role.compare(0, prefix.size(), prefix) == 0
|
||||
)
|
||||
if (prefix.size() < external_role.size() && external_role.starts_with(prefix))
|
||||
{
|
||||
role_names.emplace(external_role, prefix.size());
|
||||
}
|
||||
|
@ -62,8 +62,7 @@ String QuotaCache::QuotaInfo::calculateKey(const EnabledQuota & enabled, bool th
|
||||
"Quota {} (for user {}) requires a client supplied key.",
|
||||
quota->getName(),
|
||||
params.user_name);
|
||||
else
|
||||
return ""; // Authentication quota has no client key at time of authentication.
|
||||
return ""; // Authentication quota has no client key at time of authentication.
|
||||
}
|
||||
case QuotaKeyType::CLIENT_KEY_OR_USER_NAME:
|
||||
{
|
||||
|
@ -80,15 +80,13 @@ void RolesOrUsersSet::init(const ASTRolesOrUsersSet & ast, const AccessControl *
|
||||
return *id;
|
||||
return access_control->getID<Role>(name);
|
||||
}
|
||||
else if (ast.allow_users)
|
||||
if (ast.allow_users)
|
||||
{
|
||||
return access_control->getID<User>(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(ast.allow_roles);
|
||||
return access_control->getID<Role>(name);
|
||||
}
|
||||
|
||||
assert(ast.allow_roles);
|
||||
return access_control->getID<Role>(name);
|
||||
};
|
||||
|
||||
if (!ast.names.empty() && !all)
|
||||
|
@ -28,7 +28,7 @@ SettingsAuthResponseParser::parse(const Poco::Net::HTTPResponse & response, std:
|
||||
try
|
||||
{
|
||||
Poco::Dynamic::Var json = parser.parse(*body_stream);
|
||||
Poco::JSON::Object::Ptr obj = json.extract<Poco::JSON::Object::Ptr>();
|
||||
const Poco::JSON::Object::Ptr & obj = json.extract<Poco::JSON::Object::Ptr>();
|
||||
Poco::JSON::Object::Ptr settings_obj = obj->getObject(settings_key);
|
||||
|
||||
if (settings_obj)
|
||||
|
@ -54,8 +54,7 @@ SettingSourceRestrictions getSettingSourceRestrictions(std::string_view name)
|
||||
auto settingConstraintIter = SETTINGS_SOURCE_RESTRICTIONS.find(name);
|
||||
if (settingConstraintIter != SETTINGS_SOURCE_RESTRICTIONS.end())
|
||||
return settingConstraintIter->second;
|
||||
else
|
||||
return SettingSourceRestrictions(); // allows everything
|
||||
return SettingSourceRestrictions(); // allows everything
|
||||
}
|
||||
|
||||
}
|
||||
@ -310,8 +309,7 @@ bool SettingsConstraints::Checker::check(SettingChange & change,
|
||||
{
|
||||
if (reaction == THROW_ON_VIOLATION)
|
||||
throw Exception(explain, code);
|
||||
else
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string_view setting_name = setting_name_resolver(change.name);
|
||||
@ -335,8 +333,7 @@ bool SettingsConstraints::Checker::check(SettingChange & change,
|
||||
{
|
||||
if (reaction == THROW_ON_VIOLATION)
|
||||
throw Exception(ErrorCodes::SETTING_CONSTRAINT_VIOLATION, "Setting {} should not be changed", setting_name);
|
||||
else
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto & min_value = constraint.min_value;
|
||||
@ -351,8 +348,7 @@ bool SettingsConstraints::Checker::check(SettingChange & change,
|
||||
max_value,
|
||||
min_value,
|
||||
setting_name);
|
||||
else
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!min_value.isNull() && less_or_cannot_compare(new_value, min_value))
|
||||
@ -362,8 +358,7 @@ bool SettingsConstraints::Checker::check(SettingChange & change,
|
||||
throw Exception(ErrorCodes::SETTING_CONSTRAINT_VIOLATION, "Setting {} shouldn't be less than {}",
|
||||
setting_name, applyVisitor(FieldVisitorToString(), min_value));
|
||||
}
|
||||
else
|
||||
change.value = min_value;
|
||||
change.value = min_value;
|
||||
}
|
||||
|
||||
if (!max_value.isNull() && less_or_cannot_compare(max_value, new_value))
|
||||
@ -373,16 +368,14 @@ bool SettingsConstraints::Checker::check(SettingChange & change,
|
||||
throw Exception(ErrorCodes::SETTING_CONSTRAINT_VIOLATION, "Setting {} shouldn't be greater than {}",
|
||||
setting_name, applyVisitor(FieldVisitorToString(), max_value));
|
||||
}
|
||||
else
|
||||
change.value = max_value;
|
||||
change.value = max_value;
|
||||
}
|
||||
|
||||
if (!getSettingSourceRestrictions(setting_name).isSourceAllowed(source))
|
||||
{
|
||||
if (reaction == THROW_ON_VIOLATION)
|
||||
throw Exception(ErrorCodes::READONLY, "Setting {} is not allowed to be set by {}", setting_name, toString(source));
|
||||
else
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -649,8 +649,7 @@ namespace
|
||||
{
|
||||
if (users_without_row_policies_can_read_rows)
|
||||
continue;
|
||||
else
|
||||
filter = "1";
|
||||
filter = "1";
|
||||
}
|
||||
|
||||
auto policy = std::make_shared<RowPolicy>();
|
||||
|
@ -157,13 +157,13 @@ public:
|
||||
d.status = static_cast<Data::Status>(k);
|
||||
if (d.status == Data::Status::NotSet)
|
||||
return;
|
||||
else if (d.status == Data::Status::SetNull)
|
||||
if (d.status == Data::Status::SetNull)
|
||||
{
|
||||
if (!returns_nullable_type)
|
||||
throw Exception(ErrorCodes::INCORRECT_DATA, "Incorrect type (NULL) in non-nullable {}State", getName());
|
||||
return;
|
||||
}
|
||||
else if (d.status == Data::Status::SetOther)
|
||||
if (d.status == Data::Status::SetOther)
|
||||
{
|
||||
serialization->deserializeBinary(d.value, buf, {});
|
||||
return;
|
||||
|
@ -148,9 +148,8 @@ AggregateFunctionPtr createAggregateFunctionDeltaSum(
|
||||
if (isInteger(data_type) || isFloat(data_type))
|
||||
return AggregateFunctionPtr(createWithNumericType<AggregationFunctionDeltaSum>(
|
||||
*data_type, arguments, params));
|
||||
else
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type {} of argument for aggregate function {}",
|
||||
arguments[0]->getName(), name);
|
||||
throw Exception(
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type {} of argument for aggregate function {}", arguments[0]->getName(), name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,13 +137,12 @@ AggregateFunctionFactory::getAssociatedFunctionByNullsAction(const String & name
|
||||
{
|
||||
if (action == NullsAction::RESPECT_NULLS)
|
||||
{
|
||||
if (auto it = respect_nulls.find(name); it == respect_nulls.end())
|
||||
auto it = respect_nulls.find(name);
|
||||
if (it == respect_nulls.end())
|
||||
throw Exception(ErrorCodes::NOT_IMPLEMENTED, "Function {} does not support RESPECT NULLS", name);
|
||||
else if (auto associated_it = aggregate_functions.find(it->second); associated_it != aggregate_functions.end())
|
||||
if (auto associated_it = aggregate_functions.find(it->second); associated_it != aggregate_functions.end())
|
||||
return {associated_it->second};
|
||||
else
|
||||
throw Exception(
|
||||
ErrorCodes::LOGICAL_ERROR, "Unable to find the function {} (equivalent to '{} RESPECT NULLS')", it->second, name);
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Unable to find the function {} (equivalent to '{} RESPECT NULLS')", it->second, name);
|
||||
}
|
||||
|
||||
if (action == NullsAction::IGNORE_NULLS)
|
||||
@ -152,9 +151,8 @@ AggregateFunctionFactory::getAssociatedFunctionByNullsAction(const String & name
|
||||
{
|
||||
if (auto associated_it = aggregate_functions.find(it->second); associated_it != aggregate_functions.end())
|
||||
return {associated_it->second};
|
||||
else
|
||||
throw Exception(
|
||||
ErrorCodes::LOGICAL_ERROR, "Unable to find the function {} (equivalent to '{} IGNORE NULLS')", it->second, name);
|
||||
throw Exception(
|
||||
ErrorCodes::LOGICAL_ERROR, "Unable to find the function {} (equivalent to '{} IGNORE NULLS')", it->second, name);
|
||||
}
|
||||
/// We don't throw for IGNORE NULLS of other functions because that's the default in CH
|
||||
}
|
||||
@ -263,8 +261,7 @@ AggregateFunctionPtr AggregateFunctionFactory::getImpl(
|
||||
if (!hints.empty())
|
||||
throw Exception(ErrorCodes::UNKNOWN_AGGREGATE_FUNCTION,
|
||||
"Unknown aggregate function {}{}. Maybe you meant: {}", name, extra_info, toString(hints));
|
||||
else
|
||||
throw Exception(ErrorCodes::UNKNOWN_AGGREGATE_FUNCTION, "Unknown aggregate function {}{}", name, extra_info);
|
||||
throw Exception(ErrorCodes::UNKNOWN_AGGREGATE_FUNCTION, "Unknown aggregate function {}{}", name, extra_info);
|
||||
}
|
||||
|
||||
std::optional<AggregateFunctionProperties> AggregateFunctionFactory::tryGetProperties(String name, NullsAction action) const
|
||||
|
@ -328,21 +328,19 @@ struct AggregateFunctionFlameGraphData
|
||||
list = list->next;
|
||||
return entry;
|
||||
}
|
||||
else
|
||||
|
||||
Entry * parent = list;
|
||||
while (parent->next && parent->next->size != size)
|
||||
parent = parent->next;
|
||||
|
||||
if (parent->next && parent->next->size == size)
|
||||
{
|
||||
Entry * parent = list;
|
||||
while (parent->next && parent->next->size != size)
|
||||
parent = parent->next;
|
||||
|
||||
if (parent->next && parent->next->size == size)
|
||||
{
|
||||
Entry * entry = parent->next;
|
||||
parent->next = entry->next;
|
||||
return entry;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
Entry * entry = parent->next;
|
||||
parent->next = entry->next;
|
||||
return entry;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void add(UInt64 ptr, Int64 size, const UInt64 * stack, size_t stack_size, Arena * arena)
|
||||
|
@ -90,8 +90,7 @@ struct GroupArraySamplerData
|
||||
/// With a large number of values, we will generate random numbers several times slower.
|
||||
if (lim <= static_cast<UInt64>(pcg32_fast::max()))
|
||||
return rng() % lim;
|
||||
else
|
||||
return (static_cast<UInt64>(rng()) * (static_cast<UInt64>(pcg32::max()) + 1ULL) + static_cast<UInt64>(rng())) % lim;
|
||||
return (static_cast<UInt64>(rng()) * (static_cast<UInt64>(pcg32::max()) + 1ULL) + static_cast<UInt64>(rng())) % lim;
|
||||
}
|
||||
|
||||
void randomShuffle()
|
||||
@ -797,8 +796,8 @@ AggregateFunctionPtr createAggregateFunctionGroupArray(
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "groupArrayLast make sense only with max_elems (groupArrayLast(max_elems)())");
|
||||
return createAggregateFunctionGroupArrayImpl<GroupArrayTrait</* Thas_limit= */ false, Tlast, /* Tsampler= */ Sampler::NONE>>(argument_types[0], parameters, max_elems, std::nullopt);
|
||||
}
|
||||
else
|
||||
return createAggregateFunctionGroupArrayImpl<GroupArrayTrait</* Thas_limit= */ true, Tlast, /* Tsampler= */ Sampler::NONE>>(argument_types[0], parameters, max_elems, std::nullopt);
|
||||
return createAggregateFunctionGroupArrayImpl<GroupArrayTrait</* Thas_limit= */ true, Tlast, /* Tsampler= */ Sampler::NONE>>(
|
||||
argument_types[0], parameters, max_elems, std::nullopt);
|
||||
}
|
||||
|
||||
AggregateFunctionPtr createAggregateFunctionGroupArraySample(
|
||||
|
@ -381,23 +381,22 @@ IAggregateFunction * createWithExtraTypes(const DataTypePtr & argument_type, con
|
||||
{
|
||||
WhichDataType which(argument_type);
|
||||
if (which.idx == TypeIndex::Date) return new AggregateFunctionGroupArrayIntersectDate(argument_type, parameters);
|
||||
else if (which.idx == TypeIndex::DateTime) return new AggregateFunctionGroupArrayIntersectDateTime(argument_type, parameters);
|
||||
else if (which.idx == TypeIndex::Date32) return new AggregateFunctionGroupArrayIntersectDate32(argument_type, parameters);
|
||||
else if (which.idx == TypeIndex::DateTime64)
|
||||
if (which.idx == TypeIndex::DateTime)
|
||||
return new AggregateFunctionGroupArrayIntersectDateTime(argument_type, parameters);
|
||||
if (which.idx == TypeIndex::Date32)
|
||||
return new AggregateFunctionGroupArrayIntersectDate32(argument_type, parameters);
|
||||
if (which.idx == TypeIndex::DateTime64)
|
||||
{
|
||||
const auto * datetime64_type = dynamic_cast<const DataTypeDateTime64 *>(argument_type.get());
|
||||
const auto return_type = std::make_shared<DataTypeArray>(std::make_shared<DataTypeDateTime64>(datetime64_type->getScale()));
|
||||
|
||||
return new AggregateFunctionGroupArrayIntersectGeneric<true>(argument_type, parameters, return_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Check that we can use plain version of AggregateFunctionGroupArrayIntersectGeneric
|
||||
if (argument_type->isValueUnambiguouslyRepresentedInContiguousMemoryRegion())
|
||||
return new AggregateFunctionGroupArrayIntersectGeneric<true>(argument_type, parameters);
|
||||
else
|
||||
return new AggregateFunctionGroupArrayIntersectGeneric<false>(argument_type, parameters);
|
||||
}
|
||||
|
||||
/// Check that we can use plain version of AggregateFunctionGroupArrayIntersectGeneric
|
||||
if (argument_type->isValueUnambiguouslyRepresentedInContiguousMemoryRegion())
|
||||
return new AggregateFunctionGroupArrayIntersectGeneric<true>(argument_type, parameters);
|
||||
return new AggregateFunctionGroupArrayIntersectGeneric<false>(argument_type, parameters);
|
||||
}
|
||||
|
||||
inline AggregateFunctionPtr createAggregateFunctionGroupArrayIntersectImpl(const std::string & name, const DataTypePtr & argument_type, const Array & parameters)
|
||||
|
@ -65,8 +65,7 @@ struct MovingSumData : public MovingData<T>
|
||||
{
|
||||
if (idx < window_size)
|
||||
return this->value[idx];
|
||||
else
|
||||
return this->value[idx] - this->value[idx - window_size];
|
||||
return this->value[idx] - this->value[idx - window_size];
|
||||
}
|
||||
};
|
||||
|
||||
@ -79,8 +78,7 @@ struct MovingAvgData : public MovingData<T>
|
||||
{
|
||||
if (idx < window_size)
|
||||
return this->value[idx] / T(window_size);
|
||||
else
|
||||
return (this->value[idx] - this->value[idx - window_size]) / T(window_size);
|
||||
return (this->value[idx] - this->value[idx - window_size]) / T(window_size);
|
||||
}
|
||||
};
|
||||
|
||||
@ -285,16 +283,12 @@ AggregateFunctionPtr createAggregateFunctionMoving(
|
||||
{
|
||||
if (isDecimal(argument_type))
|
||||
return createAggregateFunctionMovingImpl<Function, std::false_type, std::true_type>(name, argument_type);
|
||||
else
|
||||
return createAggregateFunctionMovingImpl<Function, std::false_type, std::false_type>(name, argument_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isDecimal(argument_type))
|
||||
return createAggregateFunctionMovingImpl<Function, std::true_type, std::true_type>(name, argument_type, max_elems);
|
||||
else
|
||||
return createAggregateFunctionMovingImpl<Function, std::true_type, std::false_type>(name, argument_type, max_elems);
|
||||
return createAggregateFunctionMovingImpl<Function, std::false_type, std::false_type>(name, argument_type);
|
||||
}
|
||||
|
||||
if (isDecimal(argument_type))
|
||||
return createAggregateFunctionMovingImpl<Function, std::true_type, std::true_type>(name, argument_type, max_elems);
|
||||
return createAggregateFunctionMovingImpl<Function, std::true_type, std::false_type>(name, argument_type, max_elems);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -391,21 +391,20 @@ AggregateFunctionPtr createAggregateFunctionGroupArray(
|
||||
{
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Parameter for aggregate function {} should have limit argument", name);
|
||||
}
|
||||
else if (parameters.size() == 1)
|
||||
if (parameters.size() == 1)
|
||||
{
|
||||
auto type = parameters[0].getType();
|
||||
if (type != Field::Types::Int64 && type != Field::Types::UInt64)
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Parameter for aggregate function {} should be positive number", name);
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Parameter for aggregate function {} should be positive number", name);
|
||||
|
||||
if ((type == Field::Types::Int64 && parameters[0].safeGet<Int64>() < 0) ||
|
||||
(type == Field::Types::UInt64 && parameters[0].safeGet<UInt64>() == 0))
|
||||
if ((type == Field::Types::Int64 && parameters[0].safeGet<Int64>() < 0)
|
||||
|| (type == Field::Types::UInt64 && parameters[0].safeGet<UInt64>() == 0))
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Parameter for aggregate function {} should be positive number", name);
|
||||
|
||||
max_elems = parameters[0].safeGet<UInt64>();
|
||||
}
|
||||
else
|
||||
throw Exception(ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH,
|
||||
"Function {} does not support this number of arguments", name);
|
||||
throw Exception(ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH, "Function {} does not support this number of arguments", name);
|
||||
|
||||
if (max_elems > group_array_sorted_sort_strategy_max_elements_threshold)
|
||||
return createAggregateFunctionGroupArraySortedImpl<GroupArraySortedSort>(argument_types[0], parameters, max_elems);
|
||||
|
@ -133,8 +133,7 @@ public:
|
||||
{
|
||||
if (revision >= STATE_VERSION_1_MIN_REVISION)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void serialize(ConstAggregateDataPtr __restrict place, WriteBuffer & buf, std::optional<size_t> version) const override
|
||||
|
@ -88,8 +88,7 @@ public:
|
||||
{
|
||||
if (isSmall())
|
||||
return small.size();
|
||||
else
|
||||
return roaring_bitmap->cardinality();
|
||||
return roaring_bitmap->cardinality();
|
||||
}
|
||||
|
||||
void merge(const RoaringBitmapWithSmallSet & r1)
|
||||
@ -454,8 +453,7 @@ public:
|
||||
|
||||
if (isSmall())
|
||||
return small.find(static_cast<T>(x)) != small.end();
|
||||
else
|
||||
return roaring_bitmap->contains(static_cast<Value>(x));
|
||||
return roaring_bitmap->contains(static_cast<Value>(x));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -554,24 +552,22 @@ public:
|
||||
r1.add(elem);
|
||||
return answer.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt64 count = 0;
|
||||
for (auto it = roaring_bitmap->begin(); it != roaring_bitmap->end(); ++it)
|
||||
{
|
||||
if (*it < range_start)
|
||||
continue;
|
||||
|
||||
if (count < limit)
|
||||
{
|
||||
r1.add(*it);
|
||||
++count;
|
||||
}
|
||||
else
|
||||
break;
|
||||
UInt64 count = 0;
|
||||
for (auto it = roaring_bitmap->begin(); it != roaring_bitmap->end(); ++it)
|
||||
{
|
||||
if (*it < range_start)
|
||||
continue;
|
||||
|
||||
if (count < limit)
|
||||
{
|
||||
r1.add(*it);
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
else
|
||||
break;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
UInt64 rb_offset_limit(UInt64 offset, UInt64 limit, RoaringBitmapWithSmallSet & r1) const /// NOLINT
|
||||
@ -591,18 +587,16 @@ public:
|
||||
r1.add(it->getValue());
|
||||
return count;
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt64 count = 0;
|
||||
UInt64 offset_count = 0;
|
||||
auto it = roaring_bitmap->begin();
|
||||
for (;it != roaring_bitmap->end() && offset_count < offset; ++it)
|
||||
++offset_count;
|
||||
|
||||
for (;it != roaring_bitmap->end() && count < limit; ++it, ++count)
|
||||
r1.add(*it);
|
||||
return count;
|
||||
}
|
||||
UInt64 count = 0;
|
||||
UInt64 offset_count = 0;
|
||||
auto it = roaring_bitmap->begin();
|
||||
for (; it != roaring_bitmap->end() && offset_count < offset; ++it)
|
||||
++offset_count;
|
||||
|
||||
for (; it != roaring_bitmap->end() && count < limit; ++it, ++count)
|
||||
r1.add(*it);
|
||||
return count;
|
||||
}
|
||||
|
||||
UInt64 rb_min() const /// NOLINT
|
||||
@ -620,8 +614,7 @@ public:
|
||||
}
|
||||
return min_val;
|
||||
}
|
||||
else
|
||||
return roaring_bitmap->minimum();
|
||||
return roaring_bitmap->minimum();
|
||||
}
|
||||
|
||||
UInt64 rb_max() const /// NOLINT
|
||||
@ -639,8 +632,7 @@ public:
|
||||
}
|
||||
return max_val;
|
||||
}
|
||||
else
|
||||
return roaring_bitmap->maximum();
|
||||
return roaring_bitmap->maximum();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -275,8 +275,7 @@ AggregateFunctionPtr createAggregateFunctionGroupConcat(
|
||||
|
||||
if (has_limit)
|
||||
return std::make_shared<GroupConcatImpl</* has_limit= */ true>>(argument_types[0], parameters, limit, delimiter);
|
||||
else
|
||||
return std::make_shared<GroupConcatImpl</* has_limit= */ false>>(argument_types[0], parameters, limit, delimiter);
|
||||
return std::make_shared<GroupConcatImpl</* has_limit= */ false>>(argument_types[0], parameters, limit, delimiter);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -276,16 +276,15 @@ IAggregateFunction * createWithExtraTypes(const DataTypePtr & argument_type, TAr
|
||||
{
|
||||
WhichDataType which(argument_type);
|
||||
if (which.idx == TypeIndex::Date) return new AggregateFunctionGroupUniqArrayDate<HasLimit>(argument_type, args...);
|
||||
else if (which.idx == TypeIndex::DateTime) return new AggregateFunctionGroupUniqArrayDateTime<HasLimit>(argument_type, args...);
|
||||
else if (which.idx == TypeIndex::IPv4) return new AggregateFunctionGroupUniqArrayIPv4<HasLimit>(argument_type, args...);
|
||||
else
|
||||
{
|
||||
/// Check that we can use plain version of AggregateFunctionGroupUniqArrayGeneric
|
||||
if (argument_type->isValueUnambiguouslyRepresentedInContiguousMemoryRegion())
|
||||
return new AggregateFunctionGroupUniqArrayGeneric<true, HasLimit>(argument_type, args...);
|
||||
else
|
||||
return new AggregateFunctionGroupUniqArrayGeneric<false, HasLimit>(argument_type, args...);
|
||||
}
|
||||
if (which.idx == TypeIndex::DateTime)
|
||||
return new AggregateFunctionGroupUniqArrayDateTime<HasLimit>(argument_type, args...);
|
||||
if (which.idx == TypeIndex::IPv4)
|
||||
return new AggregateFunctionGroupUniqArrayIPv4<HasLimit>(argument_type, args...);
|
||||
|
||||
/// Check that we can use plain version of AggregateFunctionGroupUniqArrayGeneric
|
||||
if (argument_type->isValueUnambiguouslyRepresentedInContiguousMemoryRegion())
|
||||
return new AggregateFunctionGroupUniqArrayGeneric<true, HasLimit>(argument_type, args...);
|
||||
return new AggregateFunctionGroupUniqArrayGeneric<false, HasLimit>(argument_type, args...);
|
||||
}
|
||||
|
||||
template <typename HasLimit, typename ... TArgs>
|
||||
@ -336,8 +335,7 @@ AggregateFunctionPtr createAggregateFunctionGroupUniqArray(
|
||||
|
||||
if (!limit_size)
|
||||
return createAggregateFunctionGroupUniqArrayImpl<std::false_type>(name, argument_types[0], parameters);
|
||||
else
|
||||
return createAggregateFunctionGroupUniqArrayImpl<std::true_type>(name, argument_types[0], parameters, max_elems);
|
||||
return createAggregateFunctionGroupUniqArrayImpl<std::true_type>(name, argument_types[0], parameters, max_elems);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -87,8 +87,7 @@ public:
|
||||
{
|
||||
if (kind_ == AggregateFunctionIntersectionsKind::Count)
|
||||
return std::make_shared<DataTypeUInt64>();
|
||||
else
|
||||
return std::make_shared<DataTypeNumber<PointType>>();
|
||||
return std::make_shared<DataTypeNumber<PointType>>();
|
||||
}
|
||||
|
||||
/// MaxIntersectionsData::Allocator uses the arena
|
||||
|
@ -138,7 +138,9 @@ public:
|
||||
{
|
||||
if (other.count == 0)
|
||||
return;
|
||||
else if (count == 0)
|
||||
|
||||
/// NOLINTBEGIN(readability-else-after-return)
|
||||
if (count == 0)
|
||||
{
|
||||
compress_threshold = other.compress_threshold;
|
||||
relative_error = other.relative_error;
|
||||
@ -237,6 +239,7 @@ public:
|
||||
doCompress(2 * merged_relative_error * merged_count);
|
||||
compressed = true;
|
||||
}
|
||||
/// NOLINTEND(readability-else-after-return)
|
||||
}
|
||||
|
||||
void write(WriteBuffer & buf) const
|
||||
@ -292,12 +295,10 @@ private:
|
||||
Int64 max_rank = min_rank + curr_sample.delta;
|
||||
if (max_rank - target_error <= rank && rank <= min_rank + target_error)
|
||||
return {i, min_rank, curr_sample.value};
|
||||
else
|
||||
{
|
||||
++i;
|
||||
curr_sample = sampled[i];
|
||||
min_rank += curr_sample.g;
|
||||
}
|
||||
|
||||
++i;
|
||||
curr_sample = sampled[i];
|
||||
min_rank += curr_sample.g;
|
||||
}
|
||||
return {sampled.size() - 1, 0, sampled.back().value};
|
||||
}
|
||||
|
@ -747,7 +747,7 @@ AggregateFunctionPtr createAggregateFunctionSequenceBase(
|
||||
WhichDataType which(argument_types.front().get());
|
||||
if (which.isDateTime())
|
||||
return std::make_shared<AggregateFunction<DataTypeDateTime::FieldType, Data<DataTypeDateTime::FieldType>>>(argument_types, params, pattern);
|
||||
else if (which.isDate())
|
||||
if (which.isDate())
|
||||
return std::make_shared<AggregateFunction<DataTypeDate::FieldType, Data<DataTypeDate::FieldType>>>(argument_types, params, pattern);
|
||||
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
|
||||
|
@ -124,8 +124,7 @@ private:
|
||||
{
|
||||
if (count < 2)
|
||||
return std::numeric_limits<Float64>::infinity();
|
||||
else
|
||||
return m2 / (count - 1);
|
||||
return m2 / (count - 1);
|
||||
}
|
||||
|
||||
static Float64 getStddevSamp(Float64 m2, UInt64 count)
|
||||
@ -137,10 +136,9 @@ private:
|
||||
{
|
||||
if (count == 0)
|
||||
return std::numeric_limits<Float64>::infinity();
|
||||
else if (count == 1)
|
||||
if (count == 1)
|
||||
return 0.0;
|
||||
else
|
||||
return m2 / count;
|
||||
return m2 / count;
|
||||
}
|
||||
|
||||
static Float64 getStddevPop(Float64 m2, UInt64 count)
|
||||
@ -363,26 +361,23 @@ private:
|
||||
{
|
||||
if (count < 2)
|
||||
return std::numeric_limits<Float64>::infinity();
|
||||
else
|
||||
return co_moment / (count - 1);
|
||||
return co_moment / (count - 1);
|
||||
}
|
||||
|
||||
static Float64 getCovarPop(Float64 co_moment, UInt64 count)
|
||||
{
|
||||
if (count == 0)
|
||||
return std::numeric_limits<Float64>::infinity();
|
||||
else if (count == 1)
|
||||
if (count == 1)
|
||||
return 0.0;
|
||||
else
|
||||
return co_moment / count;
|
||||
return co_moment / count;
|
||||
}
|
||||
|
||||
static Float64 getCorr(Float64 co_moment, Float64 left_m2, Float64 right_m2, UInt64 count)
|
||||
{
|
||||
if (count < 2)
|
||||
return std::numeric_limits<Float64>::infinity();
|
||||
else
|
||||
return co_moment / sqrt(left_m2 * right_m2);
|
||||
return co_moment / sqrt(left_m2 * right_m2);
|
||||
}
|
||||
|
||||
Float64 getResult(ConstAggregateDataPtr __restrict place) const
|
||||
|
@ -112,8 +112,7 @@ public:
|
||||
{
|
||||
if (revision >= STATE_VERSION_1_MIN_REVISION)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DataTypePtr createResultType(
|
||||
@ -764,8 +763,7 @@ void registerAggregateFunctionSumMap(AggregateFunctionFactory & factory)
|
||||
auto [keys_type, values_types, tuple_argument] = parseArguments(name, arguments);
|
||||
if (tuple_argument)
|
||||
return std::make_shared<AggregateFunctionSumMap<false, true>>(keys_type, values_types, arguments, params);
|
||||
else
|
||||
return std::make_shared<AggregateFunctionSumMap<false, false>>(keys_type, values_types, arguments, params);
|
||||
return std::make_shared<AggregateFunctionSumMap<false, false>>(keys_type, values_types, arguments, params);
|
||||
});
|
||||
|
||||
factory.registerFunction("minMappedArrays", [](const std::string & name, const DataTypes & arguments, const Array & params, const Settings *) -> AggregateFunctionPtr
|
||||
@ -773,8 +771,7 @@ void registerAggregateFunctionSumMap(AggregateFunctionFactory & factory)
|
||||
auto [keys_type, values_types, tuple_argument] = parseArguments(name, arguments);
|
||||
if (tuple_argument)
|
||||
return std::make_shared<AggregateFunctionMinMap<true>>(keys_type, values_types, arguments, params);
|
||||
else
|
||||
return std::make_shared<AggregateFunctionMinMap<false>>(keys_type, values_types, arguments, params);
|
||||
return std::make_shared<AggregateFunctionMinMap<false>>(keys_type, values_types, arguments, params);
|
||||
});
|
||||
|
||||
factory.registerFunction("maxMappedArrays", [](const std::string & name, const DataTypes & arguments, const Array & params, const Settings *) -> AggregateFunctionPtr
|
||||
@ -782,8 +779,7 @@ void registerAggregateFunctionSumMap(AggregateFunctionFactory & factory)
|
||||
auto [keys_type, values_types, tuple_argument] = parseArguments(name, arguments);
|
||||
if (tuple_argument)
|
||||
return std::make_shared<AggregateFunctionMaxMap<true>>(keys_type, values_types, arguments, params);
|
||||
else
|
||||
return std::make_shared<AggregateFunctionMaxMap<false>>(keys_type, values_types, arguments, params);
|
||||
return std::make_shared<AggregateFunctionMaxMap<false>>(keys_type, values_types, arguments, params);
|
||||
});
|
||||
|
||||
// these functions could be renamed to *MappedArrays too, but it would
|
||||
@ -793,8 +789,7 @@ void registerAggregateFunctionSumMap(AggregateFunctionFactory & factory)
|
||||
auto [keys_type, values_types, tuple_argument] = parseArguments(name, arguments);
|
||||
if (tuple_argument)
|
||||
return std::make_shared<AggregateFunctionSumMap<true, true>>(keys_type, values_types, arguments, params);
|
||||
else
|
||||
return std::make_shared<AggregateFunctionSumMap<true, false>>(keys_type, values_types, arguments, params);
|
||||
return std::make_shared<AggregateFunctionSumMap<true, false>>(keys_type, values_types, arguments, params);
|
||||
});
|
||||
|
||||
factory.registerFunction("sumMapFiltered", [](const std::string & name, const DataTypes & arguments, const Array & params, const Settings *) -> AggregateFunctionPtr
|
||||
@ -802,8 +797,7 @@ void registerAggregateFunctionSumMap(AggregateFunctionFactory & factory)
|
||||
auto [keys_type, values_types, tuple_argument] = parseArguments(name, arguments);
|
||||
if (tuple_argument)
|
||||
return std::make_shared<AggregateFunctionSumMapFiltered<false, true>>(keys_type, values_types, arguments, params);
|
||||
else
|
||||
return std::make_shared<AggregateFunctionSumMapFiltered<false, false>>(keys_type, values_types, arguments, params);
|
||||
return std::make_shared<AggregateFunctionSumMapFiltered<false, false>>(keys_type, values_types, arguments, params);
|
||||
});
|
||||
|
||||
factory.registerFunction("sumMapFilteredWithOverflow", [](const std::string & name, const DataTypes & arguments, const Array & params, const Settings *) -> AggregateFunctionPtr
|
||||
@ -811,8 +805,7 @@ void registerAggregateFunctionSumMap(AggregateFunctionFactory & factory)
|
||||
auto [keys_type, values_types, tuple_argument] = parseArguments(name, arguments);
|
||||
if (tuple_argument)
|
||||
return std::make_shared<AggregateFunctionSumMapFiltered<true, true>>(keys_type, values_types, arguments, params);
|
||||
else
|
||||
return std::make_shared<AggregateFunctionSumMapFiltered<true, false>>(keys_type, values_types, arguments, params);
|
||||
return std::make_shared<AggregateFunctionSumMapFiltered<true, false>>(keys_type, values_types, arguments, params);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -96,25 +96,18 @@ public:
|
||||
std::move(names)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
DataTypes types
|
||||
{
|
||||
std::make_shared<DataTypeNumber<Float64>>(),
|
||||
std::make_shared<DataTypeNumber<Float64>>(),
|
||||
};
|
||||
|
||||
Strings names
|
||||
{
|
||||
"t_statistic",
|
||||
"p_value",
|
||||
};
|
||||
DataTypes types{
|
||||
std::make_shared<DataTypeNumber<Float64>>(),
|
||||
std::make_shared<DataTypeNumber<Float64>>(),
|
||||
};
|
||||
|
||||
return std::make_shared<DataTypeTuple>(
|
||||
std::move(types),
|
||||
std::move(names)
|
||||
);
|
||||
}
|
||||
Strings names{
|
||||
"t_statistic",
|
||||
"p_value",
|
||||
};
|
||||
|
||||
return std::make_shared<DataTypeTuple>(std::move(types), std::move(names));
|
||||
}
|
||||
|
||||
bool allocatesMemoryInArena() const override { return false; }
|
||||
|
@ -79,8 +79,7 @@ public:
|
||||
{
|
||||
if (is_approx_top_k)
|
||||
return is_weighted ? "approx_top_sum" : "approx_top_k";
|
||||
else
|
||||
return is_weighted ? "topKWeighted" : "topK";
|
||||
return is_weighted ? "topKWeighted" : "topK";
|
||||
}
|
||||
|
||||
static DataTypePtr createResultType(const DataTypes & argument_types_, bool include_counts_)
|
||||
@ -106,8 +105,7 @@ public:
|
||||
std::move(names)
|
||||
));
|
||||
}
|
||||
else
|
||||
return std::make_shared<DataTypeArray>(argument_types_[0]);
|
||||
return std::make_shared<DataTypeArray>(argument_types_[0]);
|
||||
}
|
||||
|
||||
bool allocatesMemoryInArena() const override { return false; }
|
||||
@ -226,8 +224,7 @@ public:
|
||||
{
|
||||
if (is_approx_top_k)
|
||||
return is_weighted ? "approx_top_sum" : "approx_top_k";
|
||||
else
|
||||
return is_weighted ? "topKWeighted" : "topK";
|
||||
return is_weighted ? "topKWeighted" : "topK";
|
||||
}
|
||||
|
||||
static DataTypePtr createResultType(const DataTypes & argument_types_, bool include_counts_)
|
||||
@ -253,10 +250,8 @@ public:
|
||||
std::move(names)
|
||||
));
|
||||
|
||||
} else
|
||||
{
|
||||
return std::make_shared<DataTypeArray>(argument_types_[0]);
|
||||
}
|
||||
return std::make_shared<DataTypeArray>(argument_types_[0]);
|
||||
}
|
||||
|
||||
bool allocatesMemoryInArena() const override
|
||||
@ -440,8 +435,8 @@ IAggregateFunction * createWithExtraTypes(const DataTypes & argument_types, UInt
|
||||
/// Check that we can use plain version of AggregateFunctionTopKGeneric
|
||||
if (argument_types[0]->isValueUnambiguouslyRepresentedInContiguousMemoryRegion())
|
||||
return new AggregateFunctionTopKGeneric<true, is_weighted>(threshold, reserved, include_counts, is_approx_top_k, argument_types, params);
|
||||
else
|
||||
return new AggregateFunctionTopKGeneric<false, is_weighted>(threshold, reserved, include_counts, is_approx_top_k, argument_types, params);
|
||||
return new AggregateFunctionTopKGeneric<false, is_weighted>(
|
||||
threshold, reserved, include_counts, is_approx_top_k, argument_types, params);
|
||||
}
|
||||
|
||||
|
||||
|
@ -54,34 +54,32 @@ createAggregateFunctionUniq(const std::string & name, const DataTypes & argument
|
||||
WhichDataType which(argument_type);
|
||||
if (res)
|
||||
return res;
|
||||
else if (which.isDate())
|
||||
if (which.isDate())
|
||||
return std::make_shared<AggregateFunctionUniq<DataTypeDate::FieldType, Data>>(argument_types);
|
||||
else if (which.isDate32())
|
||||
if (which.isDate32())
|
||||
return std::make_shared<AggregateFunctionUniq<DataTypeDate32::FieldType, Data>>(argument_types);
|
||||
else if (which.isDateTime())
|
||||
if (which.isDateTime())
|
||||
return std::make_shared<AggregateFunctionUniq<DataTypeDateTime::FieldType, Data>>(argument_types);
|
||||
else if (which.isStringOrFixedString())
|
||||
if (which.isStringOrFixedString())
|
||||
return std::make_shared<AggregateFunctionUniq<String, Data>>(argument_types);
|
||||
else if (which.isUUID())
|
||||
if (which.isUUID())
|
||||
return std::make_shared<AggregateFunctionUniq<DataTypeUUID::FieldType, Data>>(argument_types);
|
||||
else if (which.isIPv4())
|
||||
if (which.isIPv4())
|
||||
return std::make_shared<AggregateFunctionUniq<DataTypeIPv4::FieldType, Data>>(argument_types);
|
||||
else if (which.isIPv6())
|
||||
if (which.isIPv6())
|
||||
return std::make_shared<AggregateFunctionUniq<DataTypeIPv6::FieldType, Data>>(argument_types);
|
||||
else if (which.isTuple())
|
||||
if (which.isTuple())
|
||||
{
|
||||
if (use_exact_hash_function)
|
||||
return std::make_shared<AggregateFunctionUniqVariadic<DataForVariadic<true, true>>>(argument_types);
|
||||
else
|
||||
return std::make_shared<AggregateFunctionUniqVariadic<DataForVariadic<false, true>>>(argument_types);
|
||||
return std::make_shared<AggregateFunctionUniqVariadic<DataForVariadic<false, true>>>(argument_types);
|
||||
}
|
||||
}
|
||||
|
||||
/// "Variadic" method also works as a fallback generic case for single argument.
|
||||
if (use_exact_hash_function)
|
||||
return std::make_shared<AggregateFunctionUniqVariadic<DataForVariadic<true, false>>>(argument_types);
|
||||
else
|
||||
return std::make_shared<AggregateFunctionUniqVariadic<DataForVariadic<false, false>>>(argument_types);
|
||||
return std::make_shared<AggregateFunctionUniqVariadic<DataForVariadic<false, false>>>(argument_types);
|
||||
}
|
||||
|
||||
template <bool is_exact, template <typename, bool> typename Data, template <bool, bool, bool> typename DataForVariadic, bool is_able_to_parallelize_merge>
|
||||
@ -107,34 +105,46 @@ createAggregateFunctionUniq(const std::string & name, const DataTypes & argument
|
||||
WhichDataType which(argument_type);
|
||||
if (res)
|
||||
return res;
|
||||
else if (which.isDate())
|
||||
return std::make_shared<AggregateFunctionUniq<DataTypeDate::FieldType, Data<DataTypeDate::FieldType, is_able_to_parallelize_merge>>>(argument_types);
|
||||
else if (which.isDate32())
|
||||
return std::make_shared<AggregateFunctionUniq<DataTypeDate32::FieldType, Data<DataTypeDate32::FieldType, is_able_to_parallelize_merge>>>(argument_types);
|
||||
else if (which.isDateTime())
|
||||
return std::make_shared<AggregateFunctionUniq<DataTypeDateTime::FieldType, Data<DataTypeDateTime::FieldType, is_able_to_parallelize_merge>>>(argument_types);
|
||||
else if (which.isStringOrFixedString())
|
||||
if (which.isDate())
|
||||
return std::make_shared<
|
||||
AggregateFunctionUniq<DataTypeDate::FieldType, Data<DataTypeDate::FieldType, is_able_to_parallelize_merge>>>(
|
||||
argument_types);
|
||||
if (which.isDate32())
|
||||
return std::make_shared<
|
||||
AggregateFunctionUniq<DataTypeDate32::FieldType, Data<DataTypeDate32::FieldType, is_able_to_parallelize_merge>>>(
|
||||
argument_types);
|
||||
if (which.isDateTime())
|
||||
return std::make_shared<
|
||||
AggregateFunctionUniq<DataTypeDateTime::FieldType, Data<DataTypeDateTime::FieldType, is_able_to_parallelize_merge>>>(
|
||||
argument_types);
|
||||
if (which.isStringOrFixedString())
|
||||
return std::make_shared<AggregateFunctionUniq<String, Data<String, is_able_to_parallelize_merge>>>(argument_types);
|
||||
else if (which.isUUID())
|
||||
return std::make_shared<AggregateFunctionUniq<DataTypeUUID::FieldType, Data<DataTypeUUID::FieldType, is_able_to_parallelize_merge>>>(argument_types);
|
||||
else if (which.isIPv4())
|
||||
return std::make_shared<AggregateFunctionUniq<DataTypeIPv4::FieldType, Data<DataTypeIPv4::FieldType, is_able_to_parallelize_merge>>>(argument_types);
|
||||
else if (which.isIPv6())
|
||||
return std::make_shared<AggregateFunctionUniq<DataTypeIPv6::FieldType, Data<DataTypeIPv6::FieldType, is_able_to_parallelize_merge>>>(argument_types);
|
||||
else if (which.isTuple())
|
||||
if (which.isUUID())
|
||||
return std::make_shared<
|
||||
AggregateFunctionUniq<DataTypeUUID::FieldType, Data<DataTypeUUID::FieldType, is_able_to_parallelize_merge>>>(
|
||||
argument_types);
|
||||
if (which.isIPv4())
|
||||
return std::make_shared<
|
||||
AggregateFunctionUniq<DataTypeIPv4::FieldType, Data<DataTypeIPv4::FieldType, is_able_to_parallelize_merge>>>(
|
||||
argument_types);
|
||||
if (which.isIPv6())
|
||||
return std::make_shared<
|
||||
AggregateFunctionUniq<DataTypeIPv6::FieldType, Data<DataTypeIPv6::FieldType, is_able_to_parallelize_merge>>>(
|
||||
argument_types);
|
||||
if (which.isTuple())
|
||||
{
|
||||
if (use_exact_hash_function)
|
||||
return std::make_shared<AggregateFunctionUniqVariadic<DataForVariadic<true, true, is_able_to_parallelize_merge>>>(argument_types);
|
||||
else
|
||||
return std::make_shared<AggregateFunctionUniqVariadic<DataForVariadic<false, true, is_able_to_parallelize_merge>>>(argument_types);
|
||||
return std::make_shared<AggregateFunctionUniqVariadic<DataForVariadic<true, true, is_able_to_parallelize_merge>>>(
|
||||
argument_types);
|
||||
return std::make_shared<AggregateFunctionUniqVariadic<DataForVariadic<false, true, is_able_to_parallelize_merge>>>(
|
||||
argument_types);
|
||||
}
|
||||
}
|
||||
|
||||
/// "Variadic" method also works as a fallback generic case for single argument.
|
||||
if (use_exact_hash_function)
|
||||
return std::make_shared<AggregateFunctionUniqVariadic<DataForVariadic<true, false, is_able_to_parallelize_merge>>>(argument_types);
|
||||
else
|
||||
return std::make_shared<AggregateFunctionUniqVariadic<DataForVariadic<false, false, is_able_to_parallelize_merge>>>(argument_types);
|
||||
return std::make_shared<AggregateFunctionUniqVariadic<DataForVariadic<false, false, is_able_to_parallelize_merge>>>(argument_types);
|
||||
}
|
||||
|
||||
}
|
||||
@ -155,9 +165,11 @@ void registerAggregateFunctionsUniq(AggregateFunctionFactory & factory)
|
||||
if (settings && (*settings)[Setting::max_threads] > 1)
|
||||
return createAggregateFunctionUniq<
|
||||
true, AggregateFunctionUniqExactData, AggregateFunctionUniqExactDataForVariadic, true /* is_able_to_parallelize_merge */>(name, argument_types, params, settings);
|
||||
else
|
||||
return createAggregateFunctionUniq<
|
||||
true, AggregateFunctionUniqExactData, AggregateFunctionUniqExactDataForVariadic, false /* is_able_to_parallelize_merge */>(name, argument_types, params, settings);
|
||||
return createAggregateFunctionUniq<
|
||||
true,
|
||||
AggregateFunctionUniqExactData,
|
||||
AggregateFunctionUniqExactDataForVariadic,
|
||||
false /* is_able_to_parallelize_merge */>(name, argument_types, params, settings);
|
||||
};
|
||||
factory.registerFunction("uniqExact", {assign_bool_param, properties});
|
||||
|
||||
|
@ -235,34 +235,40 @@ AggregateFunctionPtr createAggregateFunctionWithK(const DataTypes & argument_typ
|
||||
WhichDataType which(argument_type);
|
||||
if (res)
|
||||
return res;
|
||||
else if (which.isDate())
|
||||
return std::make_shared<typename WithK<K, HashValueType>::template AggregateFunction<DataTypeDate::FieldType>>(argument_types, params);
|
||||
else if (which.isDate32())
|
||||
return std::make_shared<typename WithK<K, HashValueType>::template AggregateFunction<DataTypeDate32::FieldType>>(argument_types, params);
|
||||
else if (which.isDateTime())
|
||||
return std::make_shared<typename WithK<K, HashValueType>::template AggregateFunction<DataTypeDateTime::FieldType>>(argument_types, params);
|
||||
else if (which.isStringOrFixedString())
|
||||
if (which.isDate())
|
||||
return std::make_shared<typename WithK<K, HashValueType>::template AggregateFunction<DataTypeDate::FieldType>>(
|
||||
argument_types, params);
|
||||
if (which.isDate32())
|
||||
return std::make_shared<typename WithK<K, HashValueType>::template AggregateFunction<DataTypeDate32::FieldType>>(
|
||||
argument_types, params);
|
||||
if (which.isDateTime())
|
||||
return std::make_shared<typename WithK<K, HashValueType>::template AggregateFunction<DataTypeDateTime::FieldType>>(
|
||||
argument_types, params);
|
||||
if (which.isStringOrFixedString())
|
||||
return std::make_shared<typename WithK<K, HashValueType>::template AggregateFunction<String>>(argument_types, params);
|
||||
else if (which.isUUID())
|
||||
return std::make_shared<typename WithK<K, HashValueType>::template AggregateFunction<DataTypeUUID::FieldType>>(argument_types, params);
|
||||
else if (which.isIPv4())
|
||||
return std::make_shared<typename WithK<K, HashValueType>::template AggregateFunction<DataTypeIPv4::FieldType>>(argument_types, params);
|
||||
else if (which.isIPv6())
|
||||
return std::make_shared<typename WithK<K, HashValueType>::template AggregateFunction<DataTypeIPv6::FieldType>>(argument_types, params);
|
||||
else if (which.isTuple())
|
||||
if (which.isUUID())
|
||||
return std::make_shared<typename WithK<K, HashValueType>::template AggregateFunction<DataTypeUUID::FieldType>>(
|
||||
argument_types, params);
|
||||
if (which.isIPv4())
|
||||
return std::make_shared<typename WithK<K, HashValueType>::template AggregateFunction<DataTypeIPv4::FieldType>>(
|
||||
argument_types, params);
|
||||
if (which.isIPv6())
|
||||
return std::make_shared<typename WithK<K, HashValueType>::template AggregateFunction<DataTypeIPv6::FieldType>>(
|
||||
argument_types, params);
|
||||
if (which.isTuple())
|
||||
{
|
||||
if (use_exact_hash_function)
|
||||
return std::make_shared<typename WithK<K, HashValueType>::template AggregateFunctionVariadic<true, true>>(argument_types, params);
|
||||
else
|
||||
return std::make_shared<typename WithK<K, HashValueType>::template AggregateFunctionVariadic<false, true>>(argument_types, params);
|
||||
return std::make_shared<typename WithK<K, HashValueType>::template AggregateFunctionVariadic<true, true>>(
|
||||
argument_types, params);
|
||||
return std::make_shared<typename WithK<K, HashValueType>::template AggregateFunctionVariadic<false, true>>(
|
||||
argument_types, params);
|
||||
}
|
||||
}
|
||||
|
||||
/// "Variadic" method also works as a fallback generic case for a single argument.
|
||||
if (use_exact_hash_function)
|
||||
return std::make_shared<typename WithK<K, HashValueType>::template AggregateFunctionVariadic<true, false>>(argument_types, params);
|
||||
else
|
||||
return std::make_shared<typename WithK<K, HashValueType>::template AggregateFunctionVariadic<false, false>>(argument_types, params);
|
||||
return std::make_shared<typename WithK<K, HashValueType>::template AggregateFunctionVariadic<false, false>>(argument_types, params);
|
||||
}
|
||||
|
||||
template <UInt8 K>
|
||||
@ -270,8 +276,7 @@ AggregateFunctionPtr createAggregateFunctionWithHashType(bool use_64_bit_hash, c
|
||||
{
|
||||
if (use_64_bit_hash)
|
||||
return createAggregateFunctionWithK<K, UInt64>(argument_types, params);
|
||||
else
|
||||
return createAggregateFunctionWithK<K, UInt32>(argument_types, params);
|
||||
return createAggregateFunctionWithK<K, UInt32>(argument_types, params);
|
||||
}
|
||||
|
||||
/// Let's instantiate these templates in separate translation units,
|
||||
|
@ -324,30 +324,28 @@ AggregateFunctionPtr createAggregateFunctionUniqUpTo(const std::string & name, c
|
||||
WhichDataType which(argument_type);
|
||||
if (res)
|
||||
return res;
|
||||
else if (which.isDate())
|
||||
if (which.isDate())
|
||||
return std::make_shared<AggregateFunctionUniqUpTo<DataTypeDate::FieldType>>(threshold, argument_types, params);
|
||||
else if (which.isDate32())
|
||||
if (which.isDate32())
|
||||
return std::make_shared<AggregateFunctionUniqUpTo<DataTypeDate32::FieldType>>(threshold, argument_types, params);
|
||||
else if (which.isDateTime())
|
||||
if (which.isDateTime())
|
||||
return std::make_shared<AggregateFunctionUniqUpTo<DataTypeDateTime::FieldType>>(threshold, argument_types, params);
|
||||
else if (which.isStringOrFixedString())
|
||||
if (which.isStringOrFixedString())
|
||||
return std::make_shared<AggregateFunctionUniqUpTo<String>>(threshold, argument_types, params);
|
||||
else if (which.isUUID())
|
||||
if (which.isUUID())
|
||||
return std::make_shared<AggregateFunctionUniqUpTo<DataTypeUUID::FieldType>>(threshold, argument_types, params);
|
||||
else if (which.isTuple())
|
||||
if (which.isTuple())
|
||||
{
|
||||
if (use_exact_hash_function)
|
||||
return std::make_shared<AggregateFunctionUniqUpToVariadic<true, true>>(argument_types, params, threshold);
|
||||
else
|
||||
return std::make_shared<AggregateFunctionUniqUpToVariadic<false, true>>(argument_types, params, threshold);
|
||||
return std::make_shared<AggregateFunctionUniqUpToVariadic<false, true>>(argument_types, params, threshold);
|
||||
}
|
||||
}
|
||||
|
||||
/// "Variadic" method also works as a fallback generic case for single argument.
|
||||
if (use_exact_hash_function)
|
||||
return std::make_shared<AggregateFunctionUniqUpToVariadic<true, false>>(argument_types, params, threshold);
|
||||
else
|
||||
return std::make_shared<AggregateFunctionUniqUpToVariadic<false, false>>(argument_types, params, threshold);
|
||||
return std::make_shared<AggregateFunctionUniqUpToVariadic<false, false>>(argument_types, params, threshold);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -180,10 +180,9 @@ private:
|
||||
{
|
||||
if (first_event)
|
||||
break;
|
||||
else
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
else if (event_idx == 0)
|
||||
if (event_idx == 0)
|
||||
{
|
||||
events_timestamp[0] = std::make_pair(timestamp, timestamp);
|
||||
first_event = true;
|
||||
@ -326,10 +325,11 @@ createAggregateFunctionWindowFunnel(const std::string & name, const DataTypes &
|
||||
WhichDataType which(arguments.front().get());
|
||||
if (res)
|
||||
return res;
|
||||
else if (which.isDate())
|
||||
if (which.isDate())
|
||||
return std::make_shared<AggregateFunctionWindowFunnel<DataTypeDate::FieldType, Data<DataTypeDate::FieldType>>>(arguments, params);
|
||||
else if (which.isDateTime())
|
||||
return std::make_shared<AggregateFunctionWindowFunnel<DataTypeDateTime::FieldType, Data<DataTypeDateTime::FieldType>>>(arguments, params);
|
||||
if (which.isDateTime())
|
||||
return std::make_shared<AggregateFunctionWindowFunnel<DataTypeDateTime::FieldType, Data<DataTypeDateTime::FieldType>>>(
|
||||
arguments, params);
|
||||
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
|
||||
"Illegal type {} of first argument of aggregate function {}, must "
|
||||
|
@ -50,10 +50,8 @@ public:
|
||||
return std::make_shared<
|
||||
AggregateFunctionDistinct<
|
||||
AggregateFunctionDistinctSingleGenericData<true>>>(nested_function, arguments, params);
|
||||
else
|
||||
return std::make_shared<
|
||||
AggregateFunctionDistinct<
|
||||
AggregateFunctionDistinctSingleGenericData<false>>>(nested_function, arguments, params);
|
||||
return std::make_shared<AggregateFunctionDistinct<AggregateFunctionDistinctSingleGenericData<false>>>(
|
||||
nested_function, arguments, params);
|
||||
}
|
||||
|
||||
return std::make_shared<AggregateFunctionDistinct<AggregateFunctionDistinctMultipleGenericData>>(nested_function, arguments, params);
|
||||
|
@ -473,28 +473,20 @@ AggregateFunctionPtr AggregateFunctionIf::getOwnNullAdapter(
|
||||
{
|
||||
return std::make_shared<AggregateFunctionIfNullUnary<true, true>>(nested_function->getName(), nested_func, arguments, params);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (need_to_serialize_flag)
|
||||
return std::make_shared<AggregateFunctionIfNullUnary<false, true>>(nested_function->getName(), nested_func, arguments, params);
|
||||
else
|
||||
return std::make_shared<AggregateFunctionIfNullUnary<false, false>>(nested_function->getName(), nested_func, arguments, params);
|
||||
}
|
||||
|
||||
if (need_to_serialize_flag)
|
||||
return std::make_shared<AggregateFunctionIfNullUnary<false, true>>(nested_function->getName(), nested_func, arguments, params);
|
||||
return std::make_shared<AggregateFunctionIfNullUnary<false, false>>(nested_function->getName(), nested_func, arguments, params);
|
||||
}
|
||||
else
|
||||
|
||||
if (return_type_is_nullable)
|
||||
{
|
||||
if (return_type_is_nullable)
|
||||
{
|
||||
return std::make_shared<AggregateFunctionIfNullVariadic<true, true>>(nested_function, arguments, params);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (need_to_serialize_flag)
|
||||
return std::make_shared<AggregateFunctionIfNullVariadic<false, true>>(nested_function, arguments, params);
|
||||
else
|
||||
return std::make_shared<AggregateFunctionIfNullVariadic<false, false>>(nested_function, arguments, params);
|
||||
}
|
||||
return std::make_shared<AggregateFunctionIfNullVariadic<true, true>>(nested_function, arguments, params);
|
||||
}
|
||||
|
||||
if (need_to_serialize_flag)
|
||||
return std::make_shared<AggregateFunctionIfNullVariadic<false, true>>(nested_function, arguments, params);
|
||||
return std::make_shared<AggregateFunctionIfNullVariadic<false, false>>(nested_function, arguments, params);
|
||||
}
|
||||
|
||||
void registerAggregateFunctionCombinatorIf(AggregateFunctionCombinatorFactory & factory)
|
||||
|
@ -450,9 +450,8 @@ public:
|
||||
auto action = NullsAction::EMPTY;
|
||||
return aggr_func_factory.get(nested_func_name + "MappedArrays", action, arguments, params, out_properties);
|
||||
}
|
||||
else
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Aggregation '{}Map' is not implemented for mapped arrays",
|
||||
nested_func_name);
|
||||
throw Exception(
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Aggregation '{}Map' is not implemented for mapped arrays", nested_func_name);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -112,8 +112,7 @@ public:
|
||||
*/
|
||||
if (properties.returns_default_when_only_null)
|
||||
return std::make_shared<AggregateFunctionNothingUInt64>(arguments, params);
|
||||
else
|
||||
return std::make_shared<AggregateFunctionNothingNull>(arguments, params);
|
||||
return std::make_shared<AggregateFunctionNothingNull>(arguments, params);
|
||||
}
|
||||
|
||||
assert(nested_function);
|
||||
@ -137,23 +136,18 @@ public:
|
||||
{
|
||||
return std::make_shared<AggregateFunctionNullUnary<true, true>>(nested_function, arguments, params);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (serialize_flag)
|
||||
return std::make_shared<AggregateFunctionNullUnary<false, true>>(nested_function, arguments, params);
|
||||
else
|
||||
return std::make_shared<AggregateFunctionNullUnary<false, false>>(nested_function, arguments, params);
|
||||
}
|
||||
|
||||
if (serialize_flag)
|
||||
return std::make_shared<AggregateFunctionNullUnary<false, true>>(nested_function, arguments, params);
|
||||
return std::make_shared<AggregateFunctionNullUnary<false, false>>(nested_function, arguments, params);
|
||||
}
|
||||
else
|
||||
|
||||
if (return_type_is_nullable)
|
||||
{
|
||||
if (return_type_is_nullable)
|
||||
{
|
||||
return std::make_shared<AggregateFunctionNullVariadic<true, true>>(nested_function, arguments, params);
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::make_shared<AggregateFunctionNullVariadic<false, true>>(nested_function, arguments, params);
|
||||
return std::make_shared<AggregateFunctionNullVariadic<true, true>>(nested_function, arguments, params);
|
||||
}
|
||||
|
||||
return std::make_shared<AggregateFunctionNullVariadic<false, true>>(nested_function, arguments, params);
|
||||
#if 0
|
||||
if (serialize_flag)
|
||||
return std::make_shared<AggregateFunctionNullVariadic<false, true>>(nested_function, arguments, params);
|
||||
@ -164,8 +158,6 @@ public:
|
||||
return std::make_shared<AggregateFunctionNullVariadic<false, true>>(nested_function, arguments, params);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -37,8 +37,7 @@ public:
|
||||
{
|
||||
if (kind == Kind::OrNull)
|
||||
return std::make_shared<AggregateFunctionOrFill<true>>(nested_function, arguments, params);
|
||||
else
|
||||
return std::make_shared<AggregateFunctionOrFill<false>>(nested_function, arguments, params);
|
||||
return std::make_shared<AggregateFunctionOrFill<false>>(nested_function, arguments, params);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -120,11 +120,9 @@ public:
|
||||
this->merge(new_sketch);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
DDSketchDenseLogarithmic new_sketch = changeMapping(other.mapping->getGamma());
|
||||
copy(new_sketch);
|
||||
}
|
||||
|
||||
DDSketchDenseLogarithmic new_sketch = changeMapping(other.mapping->getGamma());
|
||||
copy(new_sketch);
|
||||
}
|
||||
|
||||
// If the other sketch is empty, do nothing
|
||||
|
@ -146,7 +146,7 @@ struct QuantileExactExclusive : public QuantileExact<Value>
|
||||
|
||||
if (n >= array.size())
|
||||
return static_cast<Float64>(*std::max_element(array.begin(), array.end()));
|
||||
else if (n < 1)
|
||||
if (n < 1)
|
||||
return static_cast<Float64>(*std::min_element(array.begin(), array.end()));
|
||||
|
||||
::nth_element(array.begin(), array.begin() + n - 1, array.end());
|
||||
@ -211,7 +211,7 @@ struct QuantileExactInclusive : public QuantileExact<Value>
|
||||
|
||||
if (n >= array.size())
|
||||
return static_cast<Float64>(*std::max_element(array.begin(), array.end()));
|
||||
else if (n < 1)
|
||||
if (n < 1)
|
||||
return static_cast<Float64>(*std::min_element(array.begin(), array.end()));
|
||||
::nth_element(array.begin(), array.begin() + n - 1, array.end());
|
||||
auto * nth_elem = std::min_element(array.begin() + n, array.end());
|
||||
|
@ -416,15 +416,10 @@ public:
|
||||
|
||||
if (x <= left)
|
||||
return checkOverflow<ResultType>(prev_mean);
|
||||
else if (x >= right)
|
||||
if (x >= right)
|
||||
return checkOverflow<ResultType>(c.mean);
|
||||
else
|
||||
return checkOverflow<ResultType>(interpolate(
|
||||
static_cast<Value>(x),
|
||||
static_cast<Value>(left),
|
||||
prev_mean,
|
||||
static_cast<Value>(right),
|
||||
c.mean));
|
||||
return checkOverflow<ResultType>(
|
||||
interpolate(static_cast<Value>(x), static_cast<Value>(left), prev_mean, static_cast<Value>(right), c.mean));
|
||||
}
|
||||
|
||||
sum += c.count;
|
||||
|
@ -736,14 +736,12 @@ public:
|
||||
tiny.prepare();
|
||||
return tiny.get(level);
|
||||
}
|
||||
else if (kind == Kind::Medium)
|
||||
if (kind == Kind::Medium)
|
||||
{
|
||||
return medium.get(level);
|
||||
}
|
||||
else
|
||||
{
|
||||
return large->get(level);
|
||||
}
|
||||
|
||||
return large->get(level);
|
||||
}
|
||||
|
||||
/// Get the size values of the quantiles of the `levels` levels. Record `size` results starting with `result` address.
|
||||
|
@ -260,8 +260,7 @@ private:
|
||||
/// With a large number of values, we will generate random numbers several times slower.
|
||||
if (limit <= static_cast<UInt64>(pcg32_fast::max()))
|
||||
return rng() % limit;
|
||||
else
|
||||
return (static_cast<UInt64>(rng()) * (static_cast<UInt64>(pcg32_fast::max()) + 1ULL) + static_cast<UInt64>(rng())) % limit;
|
||||
return (static_cast<UInt64>(rng()) * (static_cast<UInt64>(pcg32_fast::max()) + 1ULL) + static_cast<UInt64>(rng())) % limit;
|
||||
}
|
||||
|
||||
void sortIfNeeded()
|
||||
@ -277,7 +276,6 @@ private:
|
||||
{
|
||||
if (OnEmpty == ReservoirSamplerOnEmpty::THROW)
|
||||
throw DB::Exception(DB::ErrorCodes::LOGICAL_ERROR, "Quantile of empty ReservoirSampler");
|
||||
else
|
||||
return NanLikeValueConstructor<ResultType, std::is_floating_point_v<ResultType>>::getValue();
|
||||
return NanLikeValueConstructor<ResultType, std::is_floating_point_v<ResultType>>::getValue();
|
||||
}
|
||||
};
|
||||
|
@ -271,8 +271,7 @@ private:
|
||||
{
|
||||
if (OnEmpty == ReservoirSamplerDeterministicOnEmpty::THROW)
|
||||
throw DB::Exception(DB::ErrorCodes::LOGICAL_ERROR, "Quantile of empty ReservoirSamplerDeterministic");
|
||||
else
|
||||
return NanLikeValueConstructor<ResultType, std::is_floating_point_v<ResultType>>::getValue();
|
||||
return NanLikeValueConstructor<ResultType, std::is_floating_point_v<ResultType>>::getValue();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -50,15 +50,13 @@ std::optional<size_t> SingleValueDataBase::getSmallestIndex(const IColumn & colu
|
||||
index = i;
|
||||
return {index};
|
||||
}
|
||||
else
|
||||
{
|
||||
constexpr IColumn::PermutationSortDirection direction = IColumn::PermutationSortDirection::Ascending;
|
||||
constexpr IColumn::PermutationSortStability stability = IColumn::PermutationSortStability::Unstable;
|
||||
IColumn::Permutation permutation;
|
||||
constexpr UInt64 limit = 1;
|
||||
column.getPermutation(direction, stability, limit, nan_null_direction_hint, permutation);
|
||||
return {permutation[0]};
|
||||
}
|
||||
|
||||
constexpr IColumn::PermutationSortDirection direction = IColumn::PermutationSortDirection::Ascending;
|
||||
constexpr IColumn::PermutationSortStability stability = IColumn::PermutationSortStability::Unstable;
|
||||
IColumn::Permutation permutation;
|
||||
constexpr UInt64 limit = 1;
|
||||
column.getPermutation(direction, stability, limit, nan_null_direction_hint, permutation);
|
||||
return {permutation[0]};
|
||||
}
|
||||
|
||||
std::optional<size_t> SingleValueDataBase::getGreatestIndex(const IColumn & column, size_t row_begin, size_t row_end) const
|
||||
@ -77,15 +75,13 @@ std::optional<size_t> SingleValueDataBase::getGreatestIndex(const IColumn & colu
|
||||
index = i;
|
||||
return {index};
|
||||
}
|
||||
else
|
||||
{
|
||||
constexpr IColumn::PermutationSortDirection direction = IColumn::PermutationSortDirection::Descending;
|
||||
constexpr IColumn::PermutationSortStability stability = IColumn::PermutationSortStability::Unstable;
|
||||
IColumn::Permutation permutation;
|
||||
constexpr UInt64 limit = 1;
|
||||
column.getPermutation(direction, stability, limit, nan_null_direction_hint, permutation);
|
||||
return {permutation[0]};
|
||||
}
|
||||
|
||||
constexpr IColumn::PermutationSortDirection direction = IColumn::PermutationSortDirection::Descending;
|
||||
constexpr IColumn::PermutationSortStability stability = IColumn::PermutationSortStability::Unstable;
|
||||
IColumn::Permutation permutation;
|
||||
constexpr UInt64 limit = 1;
|
||||
column.getPermutation(direction, stability, limit, nan_null_direction_hint, permutation);
|
||||
return {permutation[0]};
|
||||
}
|
||||
|
||||
std::optional<size_t> SingleValueDataBase::getSmallestIndexNotNullIf(
|
||||
@ -247,8 +243,7 @@ bool SingleValueDataFixed<T>::setIfSmaller(const SingleValueDataFixed<T> & to, A
|
||||
set(to, arena);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -259,8 +254,7 @@ bool SingleValueDataFixed<T>::setIfGreater(const SingleValueDataFixed<T> & to, A
|
||||
set(to, arena);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -271,8 +265,7 @@ bool SingleValueDataFixed<T>::setIfSmaller(const IColumn & column, size_t row_nu
|
||||
set(column, row_num, arena);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -283,8 +276,7 @@ bool SingleValueDataFixed<T>::setIfGreater(const IColumn & column, size_t row_nu
|
||||
set(column, row_num, arena);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -544,7 +536,7 @@ std::optional<size_t> SingleValueDataFixed<T>::getGreatestIndexNotNullIf(
|
||||
}
|
||||
return opt;
|
||||
}
|
||||
else if (!null_map)
|
||||
if (!null_map)
|
||||
{
|
||||
opt = findExtremeMaxIf(vec.getData().data(), if_map, row_begin, row_end);
|
||||
if (!opt.has_value())
|
||||
@ -556,18 +548,17 @@ std::optional<size_t> SingleValueDataFixed<T>::getGreatestIndexNotNullIf(
|
||||
}
|
||||
return opt;
|
||||
}
|
||||
else
|
||||
|
||||
auto final_flags = mergeIfAndNullFlags(null_map, if_map, row_begin, row_end);
|
||||
opt = findExtremeMaxIf(vec.getData().data(), final_flags.get(), row_begin, row_end);
|
||||
if (!opt.has_value())
|
||||
return std::nullopt;
|
||||
for (size_t i = row_begin; i < row_end; i++)
|
||||
{
|
||||
auto final_flags = mergeIfAndNullFlags(null_map, if_map, row_begin, row_end);
|
||||
opt = findExtremeMaxIf(vec.getData().data(), final_flags.get(), row_begin, row_end);
|
||||
if (!opt.has_value())
|
||||
return std::nullopt;
|
||||
for (size_t i = row_begin; i < row_end; i++)
|
||||
{
|
||||
if (final_flags[i] && vec[i] == *opt)
|
||||
return {i};
|
||||
}
|
||||
if (final_flags[i] && vec[i] == *opt)
|
||||
return {i};
|
||||
}
|
||||
|
||||
UNREACHABLE();
|
||||
}
|
||||
else
|
||||
@ -1218,8 +1209,7 @@ bool SingleValueDataString::setIfSmaller(const IColumn & column, size_t row_num,
|
||||
set(column, row_num, arena);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SingleValueDataString::setIfSmaller(const SingleValueDataBase & other, Arena * arena)
|
||||
@ -1230,8 +1220,7 @@ bool SingleValueDataString::setIfSmaller(const SingleValueDataBase & other, Aren
|
||||
changeImpl(to.getStringRef(), arena);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -1243,8 +1232,7 @@ bool SingleValueDataString::setIfGreater(const IColumn & column, size_t row_num,
|
||||
set(column, row_num, arena);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SingleValueDataString::setIfGreater(const SingleValueDataBase & other, Arena * arena)
|
||||
@ -1255,8 +1243,7 @@ bool SingleValueDataString::setIfGreater(const SingleValueDataBase & other, Aren
|
||||
changeImpl(to.getStringRef(), arena);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
void SingleValueDataGeneric::insertResultInto(IColumn & to) const
|
||||
@ -1317,18 +1304,15 @@ bool SingleValueDataGeneric::setIfSmaller(const IColumn & column, size_t row_num
|
||||
set(column, row_num, arena);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
||||
Field new_value;
|
||||
column.get(row_num, new_value);
|
||||
if (new_value < value)
|
||||
{
|
||||
Field new_value;
|
||||
column.get(row_num, new_value);
|
||||
if (new_value < value)
|
||||
{
|
||||
value = new_value;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
value = new_value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SingleValueDataGeneric::setIfSmaller(const SingleValueDataBase & other, Arena *)
|
||||
@ -1339,8 +1323,7 @@ bool SingleValueDataGeneric::setIfSmaller(const SingleValueDataBase & other, Are
|
||||
value = to.value;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SingleValueDataGeneric::setIfGreater(const IColumn & column, size_t row_num, Arena * arena)
|
||||
@ -1350,18 +1333,15 @@ bool SingleValueDataGeneric::setIfGreater(const IColumn & column, size_t row_num
|
||||
set(column, row_num, arena);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
||||
Field new_value;
|
||||
column.get(row_num, new_value);
|
||||
if (new_value > value)
|
||||
{
|
||||
Field new_value;
|
||||
column.get(row_num, new_value);
|
||||
if (new_value > value)
|
||||
{
|
||||
value = new_value;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
value = new_value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SingleValueDataGeneric::setIfGreater(const SingleValueDataBase & other, Arena *)
|
||||
@ -1372,8 +1352,7 @@ bool SingleValueDataGeneric::setIfGreater(const SingleValueDataBase & other, Are
|
||||
value = to.value;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
void generateSingleValueFromTypeIndex(TypeIndex idx, SingleValueDataBaseMemoryBlock & data)
|
||||
|
@ -60,10 +60,9 @@ public:
|
||||
{
|
||||
if (sk_union)
|
||||
return static_cast<UInt64>(sk_union->get_result().get_estimate());
|
||||
else if (sk_update)
|
||||
if (sk_update)
|
||||
return static_cast<UInt64>(sk_update->get_estimate());
|
||||
else
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void merge(const ThetaSketchData & rhs)
|
||||
|
@ -26,8 +26,7 @@ bool isAllArgumentsContiguousInMemory(const DataTypes & argument_types)
|
||||
|
||||
if (single_argument_as_tuple)
|
||||
return check_all_arguments_are_contiguous_in_memory(single_argument_as_tuple->getElements());
|
||||
else
|
||||
return check_all_arguments_are_contiguous_in_memory(argument_types);
|
||||
return check_all_arguments_are_contiguous_in_memory(argument_types);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -163,18 +163,16 @@ void ExceptColumnTransformerNode::dumpTreeImpl(WriteBuffer & buffer, FormatState
|
||||
buffer << ", pattern: " << column_matcher->pattern();
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
buffer << ", identifiers: ";
|
||||
|
||||
size_t except_column_names_size = except_column_names.size();
|
||||
for (size_t i = 0; i < except_column_names_size; ++i)
|
||||
{
|
||||
buffer << ", identifiers: ";
|
||||
buffer << except_column_names[i];
|
||||
|
||||
size_t except_column_names_size = except_column_names.size();
|
||||
for (size_t i = 0; i < except_column_names_size; ++i)
|
||||
{
|
||||
buffer << except_column_names[i];
|
||||
|
||||
if (i + 1 != except_column_names_size)
|
||||
buffer << ", ";
|
||||
}
|
||||
if (i + 1 != except_column_names_size)
|
||||
buffer << ", ";
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,9 +188,9 @@ bool ExceptColumnTransformerNode::isEqualImpl(const IQueryTreeNode & rhs, Compar
|
||||
|
||||
if (!column_matcher && !rhs_column_matcher)
|
||||
return true;
|
||||
else if (column_matcher && !rhs_column_matcher)
|
||||
if (column_matcher && !rhs_column_matcher)
|
||||
return false;
|
||||
else if (!column_matcher && rhs_column_matcher)
|
||||
if (!column_matcher && rhs_column_matcher)
|
||||
return false;
|
||||
|
||||
return column_matcher->pattern() == rhs_column_matcher->pattern();
|
||||
|
@ -173,9 +173,9 @@ bool FunctionNode::isEqualImpl(const IQueryTreeNode & rhs, CompareOptions compar
|
||||
|
||||
if (lhs_result_type && rhs_result_type && !lhs_result_type->equals(*rhs_result_type))
|
||||
return false;
|
||||
else if (lhs_result_type && !rhs_result_type)
|
||||
if (lhs_result_type && !rhs_result_type)
|
||||
return false;
|
||||
else if (!lhs_result_type && rhs_result_type)
|
||||
if (!lhs_result_type && rhs_result_type)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user