From 4695511b58381f24df11c6f6c1119a83b4b5f549 Mon Sep 17 00:00:00 2001 From: Vitaliy Lyudvichenko Date: Thu, 26 Apr 2018 22:21:32 +0300 Subject: [PATCH 01/47] Fixed tests isolation. [#CLICKHOUSE-2] --- ...ptimize_on_nonleader_replica_zookeeper.sql | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/dbms/tests/queries/0_stateless/00620_optimize_on_nonleader_replica_zookeeper.sql b/dbms/tests/queries/0_stateless/00620_optimize_on_nonleader_replica_zookeeper.sql index f66ab550bd4..5e463ede704 100644 --- a/dbms/tests/queries/0_stateless/00620_optimize_on_nonleader_replica_zookeeper.sql +++ b/dbms/tests/queries/0_stateless/00620_optimize_on_nonleader_replica_zookeeper.sql @@ -1,20 +1,21 @@ -DROP TABLE IF EXISTS test.clear_column1; -DROP TABLE IF EXISTS test.clear_column2; -CREATE TABLE test.clear_column1 (p Int64, i Int64, v UInt64) ENGINE = ReplicatedReplacingMergeTree('/clickhouse/tables/test/clear_column', '1', v) PARTITION BY p ORDER BY i; -CREATE TABLE test.clear_column2 (p Int64, i Int64, v UInt64) ENGINE = ReplicatedReplacingMergeTree('/clickhouse/tables/test/clear_column', '2', v) PARTITION BY p ORDER BY i; +DROP TABLE IF EXISTS test.rename1; +DROP TABLE IF EXISTS test.rename2; +CREATE TABLE test.rename1 (p Int64, i Int64, v UInt64) ENGINE = ReplicatedReplacingMergeTree('/clickhouse/test/tables/rename', '1', v) PARTITION BY p ORDER BY i; +CREATE TABLE test.rename2 (p Int64, i Int64, v UInt64) ENGINE = ReplicatedReplacingMergeTree('/clickhouse/test/tables/rename', '2', v) PARTITION BY p ORDER BY i; -INSERT INTO test.clear_column1 VALUES (0, 1, 0); -INSERT INTO test.clear_column1 VALUES (0, 1, 1); +INSERT INTO test.rename1 VALUES (0, 1, 0); +INSERT INTO test.rename1 VALUES (0, 1, 1); -OPTIMIZE TABLE test.clear_column1; -OPTIMIZE TABLE test.clear_column2; -SELECT * FROM test.clear_column1; +OPTIMIZE TABLE test.rename1; +OPTIMIZE TABLE test.rename2; +SELECT * FROM test.rename1; -RENAME TABLE test.clear_column2 TO test.clear_column3; +RENAME TABLE test.rename2 TO test.rename3; -INSERT INTO test.clear_column1 VALUES (0, 1, 2); -OPTIMIZE TABLE test.clear_column3; -SELECT * FROM test.clear_column1; +INSERT INTO test.rename1 VALUES (0, 1, 2); +OPTIMIZE TABLE test.rename3; +SELECT * FROM test.rename1; -DROP TABLE IF EXISTS test.clear_column1; -DROP TABLE IF EXISTS test.clear_column2; \ No newline at end of file +DROP TABLE IF EXISTS test.rename1; +DROP TABLE IF EXISTS test.rename2; +DROP TABLE IF EXISTS test.rename3; \ No newline at end of file From af82c78a45b6a6f136e10bb2e7ca9b936d09a46c Mon Sep 17 00:00:00 2001 From: Vitaliy Lyudvichenko Date: Thu, 26 Apr 2018 22:43:51 +0300 Subject: [PATCH 02/47] Fix nodes leak in case of session expiration. [#CLICKHOUSE-2] --- dbms/src/Common/ZooKeeper/ZooKeeper.cpp | 16 ++++++++++++++++ dbms/src/Common/ZooKeeper/ZooKeeper.h | 7 ++----- dbms/src/Storages/StorageReplicatedMergeTree.cpp | 2 +- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/dbms/src/Common/ZooKeeper/ZooKeeper.cpp b/dbms/src/Common/ZooKeeper/ZooKeeper.cpp index bccfd16b61c..65ba0b9306b 100644 --- a/dbms/src/Common/ZooKeeper/ZooKeeper.cpp +++ b/dbms/src/Common/ZooKeeper/ZooKeeper.cpp @@ -739,6 +739,22 @@ std::future ZooKeeper::asyncMulti(const return future; } +int32_t ZooKeeper::tryMultiNoThrow(const Requests & requests, Responses & responses) +{ + try + { + return multiImpl(requests, responses); + } + catch (ZooKeeperImpl::Exception & e) + { + return e.code; + } + catch (...) + { + throw; + } +} + size_t KeeperMultiException::getFailedOpIndex(int32_t code, const Responses & responses) const { diff --git a/dbms/src/Common/ZooKeeper/ZooKeeper.h b/dbms/src/Common/ZooKeeper/ZooKeeper.h index e91bb20d877..340d0dc2b2c 100644 --- a/dbms/src/Common/ZooKeeper/ZooKeeper.h +++ b/dbms/src/Common/ZooKeeper/ZooKeeper.h @@ -148,11 +148,8 @@ public: /// Throws only if some operation has returned an "unexpected" error /// - an error that would cause the corresponding try- method to throw. int32_t tryMulti(const Requests & requests, Responses & responses); - /// Throws nothing, just alias of multiImpl - int32_t tryMultiNoThrow(const Requests & requests, Responses & responses) - { - return multiImpl(requests, responses); - } + /// Throws nothing (even session expired errors) + int32_t tryMultiNoThrow(const Requests & requests, Responses & responses); Int64 getClientID(); diff --git a/dbms/src/Storages/StorageReplicatedMergeTree.cpp b/dbms/src/Storages/StorageReplicatedMergeTree.cpp index 4dd113bcf0b..8b0935a0188 100644 --- a/dbms/src/Storages/StorageReplicatedMergeTree.cpp +++ b/dbms/src/Storages/StorageReplicatedMergeTree.cpp @@ -3635,7 +3635,7 @@ void StorageReplicatedMergeTree::clearOldPartsAndRemoveFromZK() } catch (...) { - LOG_ERROR(log, "There is a problem with deleting parts from ZooKeeper: " << getCurrentExceptionMessage(false)); + LOG_ERROR(log, "There is a problem with deleting parts from ZooKeeper: " << getCurrentExceptionMessage(true)); } /// Part names that were reliably deleted from ZooKeeper should be deleted from filesystem From 6d854ee6085c3336e5c9051bc7a3bdaf6aea1741 Mon Sep 17 00:00:00 2001 From: Vitaliy Lyudvichenko Date: Thu, 3 May 2018 16:34:19 +0300 Subject: [PATCH 03/47] Fixed incorrect failed OP detection in ZooKeeper. [#CLICKHOUSE-2] --- .gitignore | 1 + dbms/src/Common/ZooKeeper/ZooKeeper.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ac01f15002f..f4e9bab7a7a 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,7 @@ cmake-build-* # Python cache *.pyc __pycache__ +*.pytest_cache # ignore generated files *-metrika-yandex diff --git a/dbms/src/Common/ZooKeeper/ZooKeeper.cpp b/dbms/src/Common/ZooKeeper/ZooKeeper.cpp index 65ba0b9306b..c348a5fab01 100644 --- a/dbms/src/Common/ZooKeeper/ZooKeeper.cpp +++ b/dbms/src/Common/ZooKeeper/ZooKeeper.cpp @@ -775,7 +775,7 @@ size_t KeeperMultiException::getFailedOpIndex(int32_t code, const Responses & re KeeperMultiException::KeeperMultiException(int32_t code, const Requests & requests, const Responses & responses) : KeeperException("Transaction failed at op #" + std::to_string(getFailedOpIndex(code, responses)), code), - requests(requests), responses(responses) + requests(requests), responses(responses), failed_op_index(getFailedOpIndex(code, responses)) { } From 537c564d029b86ac09345fd7e2e58b1b12c1b4a5 Mon Sep 17 00:00:00 2001 From: Vitaliy Lyudvichenko Date: Fri, 18 May 2018 01:57:31 +0300 Subject: [PATCH 04/47] Don't make extra checksums checks when commit a part. [#CLICKHOUSE-2] This patch is very crucial in case of many replicas. --- dbms/src/Storages/StorageReplicatedMergeTree.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dbms/src/Storages/StorageReplicatedMergeTree.cpp b/dbms/src/Storages/StorageReplicatedMergeTree.cpp index 8b0935a0188..bdeff970421 100644 --- a/dbms/src/Storages/StorageReplicatedMergeTree.cpp +++ b/dbms/src/Storages/StorageReplicatedMergeTree.cpp @@ -920,6 +920,14 @@ void StorageReplicatedMergeTree::checkPartChecksumsAndAddCommitOps(const zkutil: if (replica == replica_name) has_been_alredy_added = true; + + /// If we verify checksums in "sequential manner" (i.e. recheck absence of checksums on other replicas when commit) + /// then it is enough to verify checksums on at least one replica since checksums on other replicas must be the same. + if (absent_replicas_paths) + { + absent_replicas_paths->clear(); + break; + } } if (!has_been_alredy_added) From 84532a2a30e5bb897e9fc17b870787860322ccc3 Mon Sep 17 00:00:00 2001 From: robot-metrika-test Date: Fri, 18 May 2018 02:16:00 +0300 Subject: [PATCH 05/47] Auto version update to [54383] --- dbms/cmake/version.cmake | 6 +++--- debian/changelog | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dbms/cmake/version.cmake b/dbms/cmake/version.cmake index edaafe61522..b20fd425726 100644 --- a/dbms/cmake/version.cmake +++ b/dbms/cmake/version.cmake @@ -1,7 +1,7 @@ # This strings autochanged from release_lib.sh: -set(VERSION_DESCRIBE v1.1.54380-testing) -set(VERSION_REVISION 54380) -set(VERSION_GITHASH fb4a44a9132ee6c84aa3b0adff9c8d09a8473a15) +set(VERSION_DESCRIBE v1.1.54383-testing) +set(VERSION_REVISION 54383) +set(VERSION_GITHASH 537c564d029b86ac09345fd7e2e58b1b12c1b4a5) # end of autochange set (VERSION_MAJOR 1) diff --git a/debian/changelog b/debian/changelog index 2c5d782f65a..b8acd348b1f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,5 @@ -clickhouse (1.1.54380) unstable; urgency=low +clickhouse (1.1.54383) unstable; urgency=low * Modified source code - -- Fri, 20 Apr 2018 22:47:20 +0300 + -- Fri, 18 May 2018 02:16:00 +0300 From ce12f0b37cc5ab3100fa41476521cd25e53be8cc Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Thu, 31 May 2018 22:26:21 +0300 Subject: [PATCH 06/47] Fixed error in ZK library [#CLICKHOUSE-3753] --- dbms/src/Common/ZooKeeper/ZooKeeperImpl.cpp | 16 +++++++++------- dbms/src/Common/ZooKeeper/ZooKeeperImpl.h | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/dbms/src/Common/ZooKeeper/ZooKeeperImpl.cpp b/dbms/src/Common/ZooKeeper/ZooKeeperImpl.cpp index bca15656eda..0222dd1aed5 100644 --- a/dbms/src/Common/ZooKeeper/ZooKeeperImpl.cpp +++ b/dbms/src/Common/ZooKeeper/ZooKeeperImpl.cpp @@ -996,13 +996,14 @@ void ZooKeeper::receiveEvent() void ZooKeeper::finalize(bool error_send, bool error_receive) { - std::unique_lock lock(finalize_mutex, std::defer_lock); - if (!lock.try_lock()) - return; + { + /// Will wait for pushRequest method. + std::unique_lock lock(expired_mutex); - if (expired) - return; - expired = true; + if (expired) + return; + expired = true; + } active_session_metric_increment.destroy(); @@ -1020,6 +1021,7 @@ void ZooKeeper::finalize(bool error_send, bool error_receive) /// This happens for example, when "Cannot push request to queue within operation timeout". tryLogCurrentException(__PRETTY_FUNCTION__); } + send_thread.join(); } @@ -1348,7 +1350,7 @@ void ZooKeeper::pushRequest(RequestInfo && info) /// to avoid forgotten operations in the queue when session is expired. /// Invariant: when expired, no new operations will be pushed to the queue in 'pushRequest' /// and the queue will be drained in 'finalize'. - std::lock_guard lock(finalize_mutex); + std::lock_guard lock(expired_mutex); if (expired) throw Exception("Session expired", ZSESSIONEXPIRED); diff --git a/dbms/src/Common/ZooKeeper/ZooKeeperImpl.h b/dbms/src/Common/ZooKeeper/ZooKeeperImpl.h index ad5facf7f6d..7b17b581403 100644 --- a/dbms/src/Common/ZooKeeper/ZooKeeperImpl.h +++ b/dbms/src/Common/ZooKeeper/ZooKeeperImpl.h @@ -573,7 +573,7 @@ private: std::atomic xid {1}; std::atomic expired {false}; - std::mutex finalize_mutex; + std::mutex expired_mutex; using clock = std::chrono::steady_clock; From 81a505ad64f428a00cfcdfb7e317e0d0fd913ac2 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Thu, 31 May 2018 22:28:30 +0300 Subject: [PATCH 07/47] Better name [#CLICKHOUSE-3753] --- dbms/src/Common/ZooKeeper/ZooKeeperImpl.cpp | 5 ++--- dbms/src/Common/ZooKeeper/ZooKeeperImpl.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/dbms/src/Common/ZooKeeper/ZooKeeperImpl.cpp b/dbms/src/Common/ZooKeeper/ZooKeeperImpl.cpp index 0222dd1aed5..6d543b4af6b 100644 --- a/dbms/src/Common/ZooKeeper/ZooKeeperImpl.cpp +++ b/dbms/src/Common/ZooKeeper/ZooKeeperImpl.cpp @@ -997,8 +997,7 @@ void ZooKeeper::receiveEvent() void ZooKeeper::finalize(bool error_send, bool error_receive) { { - /// Will wait for pushRequest method. - std::unique_lock lock(expired_mutex); + std::unique_lock lock(push_request_mutex); if (expired) return; @@ -1350,7 +1349,7 @@ void ZooKeeper::pushRequest(RequestInfo && info) /// to avoid forgotten operations in the queue when session is expired. /// Invariant: when expired, no new operations will be pushed to the queue in 'pushRequest' /// and the queue will be drained in 'finalize'. - std::lock_guard lock(expired_mutex); + std::lock_guard lock(push_request_mutex); if (expired) throw Exception("Session expired", ZSESSIONEXPIRED); diff --git a/dbms/src/Common/ZooKeeper/ZooKeeperImpl.h b/dbms/src/Common/ZooKeeper/ZooKeeperImpl.h index 7b17b581403..170458e930f 100644 --- a/dbms/src/Common/ZooKeeper/ZooKeeperImpl.h +++ b/dbms/src/Common/ZooKeeper/ZooKeeperImpl.h @@ -573,7 +573,7 @@ private: std::atomic xid {1}; std::atomic expired {false}; - std::mutex expired_mutex; + std::mutex push_request_mutex; using clock = std::chrono::steady_clock; From ba48e31507199b79a2b67c9a8e45d68605c2915b Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Thu, 31 May 2018 22:30:08 +0300 Subject: [PATCH 08/47] Miscellaneous [#CLICKHOUSE-3753] --- dbms/src/Common/ZooKeeper/ZooKeeperImpl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbms/src/Common/ZooKeeper/ZooKeeperImpl.cpp b/dbms/src/Common/ZooKeeper/ZooKeeperImpl.cpp index 6d543b4af6b..0d8bc8de725 100644 --- a/dbms/src/Common/ZooKeeper/ZooKeeperImpl.cpp +++ b/dbms/src/Common/ZooKeeper/ZooKeeperImpl.cpp @@ -997,7 +997,7 @@ void ZooKeeper::receiveEvent() void ZooKeeper::finalize(bool error_send, bool error_receive) { { - std::unique_lock lock(push_request_mutex); + std::lock_guard lock(push_request_mutex); if (expired) return; From 6a57f55f0c1c7c8fee2e3e2673350a9f9f8daf26 Mon Sep 17 00:00:00 2001 From: robot-metrika-test Date: Fri, 1 Jun 2018 15:43:56 +0300 Subject: [PATCH 09/47] Auto version update to [54385] --- dbms/cmake/version.cmake | 6 +++--- debian/changelog | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dbms/cmake/version.cmake b/dbms/cmake/version.cmake index b20fd425726..8e821596b81 100644 --- a/dbms/cmake/version.cmake +++ b/dbms/cmake/version.cmake @@ -1,7 +1,7 @@ # This strings autochanged from release_lib.sh: -set(VERSION_DESCRIBE v1.1.54383-testing) -set(VERSION_REVISION 54383) -set(VERSION_GITHASH 537c564d029b86ac09345fd7e2e58b1b12c1b4a5) +set(VERSION_DESCRIBE v1.1.54385-testing) +set(VERSION_REVISION 54385) +set(VERSION_GITHASH ba48e31507199b79a2b67c9a8e45d68605c2915b) # end of autochange set (VERSION_MAJOR 1) diff --git a/debian/changelog b/debian/changelog index b8acd348b1f..b09cba656d9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,5 @@ -clickhouse (1.1.54383) unstable; urgency=low +clickhouse (1.1.54385) unstable; urgency=low * Modified source code - -- Fri, 18 May 2018 02:16:00 +0300 + -- Fri, 01 Jun 2018 15:43:56 +0300 From c89c62f9291c1ac572711c2a73340f7c076e39d2 Mon Sep 17 00:00:00 2001 From: Olga Khvostikova Date: Sat, 9 Jun 2018 06:56:10 +0000 Subject: [PATCH 10/47] Draft --- dbms/src/Server/HTTPHandler.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/dbms/src/Server/HTTPHandler.cpp b/dbms/src/Server/HTTPHandler.cpp index fba60c5c12b..7fa01e5e4e8 100644 --- a/dbms/src/Server/HTTPHandler.cpp +++ b/dbms/src/Server/HTTPHandler.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -421,13 +422,32 @@ void HTTPHandler::processQuery( std::unique_ptr in; + std::cout << "params before parsing:\n"; + for (const auto & it : params) + { + std::cout << it.first << " " << it.second << "\n"; + } + /// Support for "external data for query processing". if (startsWith(request.getContentType().data(), "multipart/form-data")) { - in = std::move(in_param); ExternalTablesHandler handler(context, params); params.load(request, istr, handler); + // Params are form params of POST + std::cout << "params after parsing:\n"; + std::string full_query = ""; + for (const auto & it : params) + { + std::cout << it.first << " " << it.second << "\n"; + if (it.first == "query") + { + full_query += it.second; + } + } + std::cout << "full query:\n" << full_query; + in = std::make_unique(full_query); + /// Erase unneeded parameters to avoid confusing them later with context settings or query /// parameters. From 7b8c31eb505a51e8a6d2defae4c4229566fd310e Mon Sep 17 00:00:00 2001 From: Olga Khvostikova Date: Sat, 9 Jun 2018 06:59:12 +0000 Subject: [PATCH 11/47] Fix --- dbms/src/Server/HTTPHandler.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/dbms/src/Server/HTTPHandler.cpp b/dbms/src/Server/HTTPHandler.cpp index 7fa01e5e4e8..0b41950a49f 100644 --- a/dbms/src/Server/HTTPHandler.cpp +++ b/dbms/src/Server/HTTPHandler.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include @@ -422,30 +421,22 @@ void HTTPHandler::processQuery( std::unique_ptr in; - std::cout << "params before parsing:\n"; - for (const auto & it : params) - { - std::cout << it.first << " " << it.second << "\n"; - } - /// Support for "external data for query processing". if (startsWith(request.getContentType().data(), "multipart/form-data")) { ExternalTablesHandler handler(context, params); + /// Params are of both form params POST and uri (GET params) params.load(request, istr, handler); - // Params are form params of POST - std::cout << "params after parsing:\n"; + std::string full_query = ""; for (const auto & it : params) { - std::cout << it.first << " " << it.second << "\n"; if (it.first == "query") { full_query += it.second; } } - std::cout << "full query:\n" << full_query; in = std::make_unique(full_query); From 15cc44d894d8772f82e4b8dcbb447499dee30441 Mon Sep 17 00:00:00 2001 From: Olga Khvostikova Date: Sat, 9 Jun 2018 07:18:59 +0000 Subject: [PATCH 12/47] Fix possible memeory problem --- dbms/src/Server/HTTPHandler.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dbms/src/Server/HTTPHandler.cpp b/dbms/src/Server/HTTPHandler.cpp index 0b41950a49f..0284efebfc3 100644 --- a/dbms/src/Server/HTTPHandler.cpp +++ b/dbms/src/Server/HTTPHandler.cpp @@ -421,6 +421,9 @@ void HTTPHandler::processQuery( std::unique_ptr in; + // Used in case of POST request with form-data, but it not to be expectd to be deleted after that scope + std::string full_query = ""; + /// Support for "external data for query processing". if (startsWith(request.getContentType().data(), "multipart/form-data")) { @@ -429,7 +432,6 @@ void HTTPHandler::processQuery( /// Params are of both form params POST and uri (GET params) params.load(request, istr, handler); - std::string full_query = ""; for (const auto & it : params) { if (it.first == "query") From b159bf160555406d47ef2f7bd629c7d849e171ca Mon Sep 17 00:00:00 2001 From: alexey-milovidov Date: Sat, 9 Jun 2018 15:24:18 +0300 Subject: [PATCH 13/47] Update HTTPHandler.cpp --- dbms/src/Server/HTTPHandler.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dbms/src/Server/HTTPHandler.cpp b/dbms/src/Server/HTTPHandler.cpp index 0284efebfc3..f2a114c4702 100644 --- a/dbms/src/Server/HTTPHandler.cpp +++ b/dbms/src/Server/HTTPHandler.cpp @@ -422,7 +422,7 @@ void HTTPHandler::processQuery( std::unique_ptr in; // Used in case of POST request with form-data, but it not to be expectd to be deleted after that scope - std::string full_query = ""; + std::string full_query; /// Support for "external data for query processing". if (startsWith(request.getContentType().data(), "multipart/form-data")) @@ -441,7 +441,6 @@ void HTTPHandler::processQuery( } in = std::make_unique(full_query); - /// Erase unneeded parameters to avoid confusing them later with context settings or query /// parameters. for (const auto & it : handler.names) From 8eee32cdd250d34499a60fb90eb72a528695c8b2 Mon Sep 17 00:00:00 2001 From: Alexey Zatelepin Date: Thu, 14 Jun 2018 17:47:46 +0300 Subject: [PATCH 14/47] add ru changelog draft for the upcoming release --- CHANGELOG.draft.md | 11 --------- CHANGELOG_RU.md | 57 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 11 deletions(-) delete mode 100644 CHANGELOG.draft.md diff --git a/CHANGELOG.draft.md b/CHANGELOG.draft.md deleted file mode 100644 index ccef5afadf6..00000000000 --- a/CHANGELOG.draft.md +++ /dev/null @@ -1,11 +0,0 @@ -en: - -## Improvements: -* `clickhouse-client`: option --ask-password for interactively ask for credentials #1044 - - - -ru: - -## Улучшения: -* `clickhouse-client`: опция --ask-password для интерактивного ввода пароля #1044 diff --git a/CHANGELOG_RU.md b/CHANGELOG_RU.md index c05bfcdb4fb..09087467692 100644 --- a/CHANGELOG_RU.md +++ b/CHANGELOG_RU.md @@ -1,3 +1,60 @@ +# ClickHouse release 1.1.5438x, 2018-06-xx + +## Новые возможности: +* Добавлена возможность вычислять аргументы функции `and` только там, где они нужны ([Анастасия Царькова](https://github.com/yandex/ClickHouse/pull/2272)) +* Добавлена возможность JIT-компиляции в нативный код некоторых выражений ([pyos](https://github.com/yandex/ClickHouse/pull/2277)). +* Добавлена агрегатная функция `windowFunnel` ([sundy-li](https://github.com/yandex/ClickHouse/pull/2352)). +* Добавлена возможность записи в таблицу с движком MySQL и соответствующую табличную функцию ([sundy-li](https://github.com/yandex/ClickHouse/pull/2294)). +* Добавлена поддержка запроса `ALTER TABLE t DELETE WHERE` для реплицированных таблиц и таблица `system.mutations`. +* Добавлена поддержка запроса `ALTER TABLE t [REPLACE|ATTACH] PARTITION` для реплицированных таблиц. +* Добавлена возможность интерактивного ввода пароля в `clickhouse-client`. +* Добавлена возможность отправки логов сервера в syslog ([Александр Крашенинников](https://github.com/yandex/ClickHouse/pull/2459)). +* Добавлено несколько новых `SYSTEM`-запросов для реплицированных таблиц (`RESTART REPLICAS`, `SYNC REPLICA`, `[STOP|START] [MERGES|FETCHES|REPLICATED SENDS|REPLICATION QUEUES]`). +* Добавлены функции `startsWith` и `endsWith` для строк ([Вадим Плахтинский](https://github.com/yandex/ClickHouse/pull/2429)). +* Добавлена поддержка запроса `TRUNCATE TABLE` ([Winter Zhang](https://github.com/yandex/ClickHouse/pull/2260)) +* Добавлена поддержка логирования в словарях с источником shared library ([Александр Сапин](https://github.com/yandex/ClickHouse/pull/2472)). +* Добавлена поддержка произвольного разделителя в формате CSV ([Иван Жуков](https://github.com/yandex/ClickHouse/pull/2263)) +* Добавлена настройка `date_time_input_format`. Если переключить эту настройку в значение `'best_effort'`, значения DateTime будут читаться в широком диапазоне форматов. + +## Исправление ошибок: +* Исправлена ошибка при чтении столбца-массива из Nested-структуры ([#2066](https://github.com/yandex/ClickHouse/issues/2066)). +* Исправлено соответствие типов в табличной функции ODBC ([sundy-li](https://github.com/yandex/ClickHouse/pull/2268)). +* Исправлено применение настроек из параметров командной строки в программе clickhouse-local. +* Исправлена ошибка при анализе запросов с секцией HAVING вида `HAVING tuple IN (...)`. +* Исправлена ошибка при анализе запросов с рекурсивными алиасами. +* Запросы с `ARRAY JOIN` и `arrayFilter` возвращали некорректный результат. +* Исправлено некорректное сравнение типов `DateTime` с таймзоной и без неё ([Александр Бочаров](https://github.com/yandex/ClickHouse/pull/2400)). +* После `CLEAR COLUMN IN PARTITION` в соответствующей партиции теперь возможны слияния ([#2315](https://github.com/yandex/ClickHouse/issues/2315)). +* Исправлено появление дублей в запросе с `DISTINCT` и `ORDER BY`. +* Исправлена вставка в материализованное представление в случае, если движок таблицы представления - Distributed ([Babacar Diassé](https://github.com/yandex/ClickHouse/pull/2411)). +* Исправлено отсечение ненужных кусков при запросе с условием на столбцы ключа партиционирования ([#2342](https://github.com/yandex/ClickHouse/issues/2342)). +* Настройки профиля пользователя не применялись при использовании сессий в HTTP-интерфейсе. +* Исправлена SSRF в табличной функции remote(). +* Клиентская библиотека ZooKeeper теперь использует таймаут сессии, полученный от сервера. +* Исправлен синтаксический разбор и форматирование оператора `CAST`. +* Исправлен race condition при записи данных из движка `Kafka` в материализованные представления ([Yangkuan Liu](https://github.com/yandex/ClickHouse/pull/2448)). + +## Улучшения: +* Сервер с реплицированными таблицами теперь может стартовать, даже если не сконфигурирован ZooKeeper. +* При расчёте количества доступных ядер CPU теперь учитываются ограничения cgroups ([Atri Sharma](https://github.com/yandex/ClickHouse/pull/2325)). +* DNS-кэш теперь автоматически обновляется при большом числе сетевых ошибок. +* Фоновые задачи в реплицированных таблицах теперь выполняются не в отдельных потоках, а в пуле потоков ([Silviu Caragea](https://github.com/yandex/ClickHouse/pull/1722)) +* Вставка в таблицу теперь не происходит, если вставка в одно из её материализованных представлений невозможна из-за того, что в нём много кусков. +* Разрешены выражения вида `tuple IN (SELECT tuple)`, если типы кортежей совпадают. +* Ускорен анализ запроса с большим числом JOIN-ов и подзапросов. +* Исправлено несоответствие в значениях счётчиков событий `Query`, `SelectQuery`, `InsertQuery`. + +## Изменения сборки: +* Используемая версия библиотеки librdkafka обновлена до v0.11.4. +* Исправлена сборка с использованием библиотеки vectorclass ([Babacar Diassé](https://github.com/yandex/ClickHouse/pull/2274)). +* Добавлена возможность сборки компилятором gcc8. +* Добавлена возможность сборки llvm из submodule. +* Cmake теперь по умолчанию генерирует файлы для ninja (как при использовании `-G Ninja`). + +## Обратно несовместимые изменения: +* Убран escaping в форматах `Vertical` и `Pretty*`. + + # ClickHouse release 1.1.54385, 2018-06-01 ## Исправление ошибок: * Исправлена ошибка, которая в некоторых случаях приводила к блокировке операций с ZooKeeper. From 91c9906c889cd338bb4df2ccc570c8f189ae3c00 Mon Sep 17 00:00:00 2001 From: Nikolai Kochetov Date: Mon, 25 Jun 2018 13:48:11 +0300 Subject: [PATCH 15/47] Fixed reading from ReplacingMergeTree from emprty row set after prewhere. #2525 --- dbms/src/DataStreams/ReplacingSortedBlockInputStream.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dbms/src/DataStreams/ReplacingSortedBlockInputStream.cpp b/dbms/src/DataStreams/ReplacingSortedBlockInputStream.cpp index 8fcfdfe2d58..db8efcd162f 100644 --- a/dbms/src/DataStreams/ReplacingSortedBlockInputStream.cpp +++ b/dbms/src/DataStreams/ReplacingSortedBlockInputStream.cpp @@ -109,7 +109,8 @@ void ReplacingSortedBlockInputStream::merge(MutableColumns & merged_columns, std } /// We will write the data for the last primary key. - insertRow(merged_columns, merged_rows); + if (!selected_row.empty()) + insertRow(merged_columns, merged_rows); finished = true; } From 7c95d153745f988a39143fbacc9e90299f86aa77 Mon Sep 17 00:00:00 2001 From: Nikolai Kochetov Date: Mon, 25 Jun 2018 13:57:28 +0300 Subject: [PATCH 16/47] Added test. #2525 --- .../00648_replacing_emtpy_set_from_prewhere.reference | 0 .../0_stateless/00648_replacing_emtpy_set_from_prewhere.sql | 5 +++++ 2 files changed, 5 insertions(+) create mode 100644 dbms/tests/queries/0_stateless/00648_replacing_emtpy_set_from_prewhere.reference create mode 100644 dbms/tests/queries/0_stateless/00648_replacing_emtpy_set_from_prewhere.sql diff --git a/dbms/tests/queries/0_stateless/00648_replacing_emtpy_set_from_prewhere.reference b/dbms/tests/queries/0_stateless/00648_replacing_emtpy_set_from_prewhere.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dbms/tests/queries/0_stateless/00648_replacing_emtpy_set_from_prewhere.sql b/dbms/tests/queries/0_stateless/00648_replacing_emtpy_set_from_prewhere.sql new file mode 100644 index 00000000000..aba76207d1d --- /dev/null +++ b/dbms/tests/queries/0_stateless/00648_replacing_emtpy_set_from_prewhere.sql @@ -0,0 +1,5 @@ +DROP TABLE IF EXISTS test.final_test; +CREATE TABLE test.final_test (id String, version Date) ENGINE = ReplacingMergeTree(version, id, 8192); +INSERT INTO test.final_test (id, version) VALUES ('2018-01-01', '2018-01-01'); +SELECT * FROM test.final_test FINAL PREWHERE id == '2018-01-02'; +DROP TABLE test.final_test; From ea59cb0b057fdeaa8178ce26b21417e93c6f5f48 Mon Sep 17 00:00:00 2001 From: KochetovNicolai Date: Mon, 25 Jun 2018 16:24:42 +0300 Subject: [PATCH 17/47] Update CHANGELOG.draft.md --- CHANGELOG.draft.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.draft.md b/CHANGELOG.draft.md index ccef5afadf6..f59be82471f 100644 --- a/CHANGELOG.draft.md +++ b/CHANGELOG.draft.md @@ -1,11 +1,17 @@ -en: +# en: ## Improvements: * `clickhouse-client`: option --ask-password for interactively ask for credentials #1044 +## Bug fixes: +* Fixed a crash that occurred while reading from ReplacingMergeTree with prewhere condition which filters all rows. #2525 -ru: + +# ru: ## Улучшения: * `clickhouse-client`: опция --ask-password для интерактивного ввода пароля #1044 + +## Исправление ошибок: +* Исправлено падение при чтении из ReplacingMergeTree с условием в prewhere, фильтрующим все строки. #2525 From 6e273978c573fabf3e7511a5aba47655d55614c0 Mon Sep 17 00:00:00 2001 From: Max Vetrov Date: Sun, 24 Jun 2018 23:48:16 +0200 Subject: [PATCH 18/47] Update mutator.cpp Don't check variable res twice. --- utils/compressor/mutator.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/utils/compressor/mutator.cpp b/utils/compressor/mutator.cpp index 94c99807b9b..89a5d1d45c8 100644 --- a/utils/compressor/mutator.cpp +++ b/utils/compressor/mutator.cpp @@ -106,9 +106,11 @@ static void mutate(pcg64 & generator, void * src, size_t length) && isAlphaASCII(pos[2])) { auto res = rand(generator, 0, 3); - if (res == 2) + if (res == 2) + { std::swap(pos[0], pos[1]); - if (res == 3) + } + else if (res == 3) std::swap(pos[1], pos[2]); pos += 3; @@ -124,7 +126,7 @@ static void mutate(pcg64 & generator, void * src, size_t length) std::swap(pos[1], pos[2]); std::swap(pos[0], pos[1]); } - if (res == 3) + else if (res == 3) { std::swap(pos[3], pos[2]); std::swap(pos[4], pos[3]); From 49d524244f9d56a438b8a9806476052a889acdf0 Mon Sep 17 00:00:00 2001 From: zhang2014 Date: Sat, 23 Jun 2018 00:31:53 +0800 Subject: [PATCH 19/47] ISSUES-2533 add numbers table function document --- docs/en/table_functions/numbers.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/en/table_functions/numbers.md b/docs/en/table_functions/numbers.md index 9b98d8747b6..4486fece3d1 100644 --- a/docs/en/table_functions/numbers.md +++ b/docs/en/table_functions/numbers.md @@ -1,13 +1,15 @@ # numbers `numbers(N)` – Returns a table with the single 'number' column (UInt64) that contains integers from 0 to N-1. +`numbers(N, M)` - Returns a table with the single 'number' column (UInt64) that contains integers from N to (N + M - 1). -Similar to the `system.numbers` table, it can be used for testing and generating successive values. +Similar to the `system.numbers` table, it can be used for testing and generating successive values, `numbers(N, M)` more efficient than `system.numbers`. -The following two queries are equivalent: +The following queries are equivalent: ```sql SELECT * FROM numbers(10); +SELECT * FROM numbers(0, 10); SELECT * FROM system.numbers LIMIT 10; ``` From e1cd4d22db2ef85667a9a5204bd940178002ca73 Mon Sep 17 00:00:00 2001 From: stavrolia Date: Mon, 25 Jun 2018 20:46:52 +0300 Subject: [PATCH 20/47] Add test (#2490) --- .../queries/0_stateless/00625_query_in_form_data.reference | 1 + dbms/tests/queries/0_stateless/00625_query_in_form_data.sh | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100755 dbms/tests/queries/0_stateless/00625_query_in_form_data.reference create mode 100755 dbms/tests/queries/0_stateless/00625_query_in_form_data.sh diff --git a/dbms/tests/queries/0_stateless/00625_query_in_form_data.reference b/dbms/tests/queries/0_stateless/00625_query_in_form_data.reference new file mode 100755 index 00000000000..d00491fd7e5 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00625_query_in_form_data.reference @@ -0,0 +1 @@ +1 diff --git a/dbms/tests/queries/0_stateless/00625_query_in_form_data.sh b/dbms/tests/queries/0_stateless/00625_query_in_form_data.sh new file mode 100755 index 00000000000..bc387394cd0 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00625_query_in_form_data.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +set -e + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +. $CURDIR/../shell_config.sh + +${CLICKHOUSE_CURL} ${CLICKHOUSE_URL}?query="select" -X POST -F "query= 1;" 2>/dev/null From 0eed697623afd251c1908073c4a2850a9bfc9cdc Mon Sep 17 00:00:00 2001 From: Nikolai Kochetov Date: Tue, 26 Jun 2018 14:28:24 +0300 Subject: [PATCH 21/47] Fixed typo. --- ...eference => 00648_replacing_empty_set_from_prewhere.reference} | 0 ...m_prewhere.sql => 00648_replacing_empty_set_from_prewhere.sql} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename dbms/tests/queries/0_stateless/{00648_replacing_emtpy_set_from_prewhere.reference => 00648_replacing_empty_set_from_prewhere.reference} (100%) rename dbms/tests/queries/0_stateless/{00648_replacing_emtpy_set_from_prewhere.sql => 00648_replacing_empty_set_from_prewhere.sql} (100%) diff --git a/dbms/tests/queries/0_stateless/00648_replacing_emtpy_set_from_prewhere.reference b/dbms/tests/queries/0_stateless/00648_replacing_empty_set_from_prewhere.reference similarity index 100% rename from dbms/tests/queries/0_stateless/00648_replacing_emtpy_set_from_prewhere.reference rename to dbms/tests/queries/0_stateless/00648_replacing_empty_set_from_prewhere.reference diff --git a/dbms/tests/queries/0_stateless/00648_replacing_emtpy_set_from_prewhere.sql b/dbms/tests/queries/0_stateless/00648_replacing_empty_set_from_prewhere.sql similarity index 100% rename from dbms/tests/queries/0_stateless/00648_replacing_emtpy_set_from_prewhere.sql rename to dbms/tests/queries/0_stateless/00648_replacing_empty_set_from_prewhere.sql From 2ed5a7c2dd693a4f3d7c4b378cd8283ee57516f9 Mon Sep 17 00:00:00 2001 From: "Dmitry S..ky / skype: dvska-at-skype" Date: Tue, 26 Jun 2018 12:04:38 +0300 Subject: [PATCH 22/47] typo fixed --- docs/ru/table_functions/numbers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ru/table_functions/numbers.md b/docs/ru/table_functions/numbers.md index bd5d566f78e..62da54b8d2b 100644 --- a/docs/ru/table_functions/numbers.md +++ b/docs/ru/table_functions/numbers.md @@ -11,6 +11,6 @@ SELECT * FROM system.numbers LIMIT 10; ``` Примеры: ```sql --- генарация последовательности всех дат от 2010-01-01 до 2010-12-31 +-- генерация последовательности всех дат от 2010-01-01 до 2010-12-31 select toDate('2010-01-01') + number as d FROM numbers(365); ``` From 225539bac21529316581efdb9e66656c23d40cef Mon Sep 17 00:00:00 2001 From: Ivan Blinkov Date: Tue, 26 Jun 2018 08:26:45 +0300 Subject: [PATCH 23/47] Temporary fix for #2558 --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 56b4c993981..adaea133aee 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ ## Technical info Developer guide for writing code for ClickHouse is published on official website alongside the usage and operations documentation: -https://clickhouse.yandex/docs/en/development/index.html +https://clickhouse.yandex/docs/en/development/architecture/ ## Legal info From 2b3282f18616de9ef3fe934681edcdb6e8fce24e Mon Sep 17 00:00:00 2001 From: Alexey Zatelepin Date: Tue, 26 Jun 2018 16:50:36 +0300 Subject: [PATCH 24/47] update changelog up to v1.1.54387 tag --- CHANGELOG_RU.md | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/CHANGELOG_RU.md b/CHANGELOG_RU.md index 09087467692..24c16c54535 100644 --- a/CHANGELOG_RU.md +++ b/CHANGELOG_RU.md @@ -1,12 +1,10 @@ -# ClickHouse release 1.1.5438x, 2018-06-xx +# ClickHouse release 1.1.54387, 2018-06-26 ## Новые возможности: -* Добавлена возможность вычислять аргументы функции `and` только там, где они нужны ([Анастасия Царькова](https://github.com/yandex/ClickHouse/pull/2272)) -* Добавлена возможность JIT-компиляции в нативный код некоторых выражений ([pyos](https://github.com/yandex/ClickHouse/pull/2277)). * Добавлена агрегатная функция `windowFunnel` ([sundy-li](https://github.com/yandex/ClickHouse/pull/2352)). * Добавлена возможность записи в таблицу с движком MySQL и соответствующую табличную функцию ([sundy-li](https://github.com/yandex/ClickHouse/pull/2294)). * Добавлена поддержка запроса `ALTER TABLE t DELETE WHERE` для реплицированных таблиц и таблица `system.mutations`. -* Добавлена поддержка запроса `ALTER TABLE t [REPLACE|ATTACH] PARTITION` для реплицированных таблиц. +* Добавлена поддержка запроса `ALTER TABLE t [REPLACE|ATTACH] PARTITION` для *MergeTree-таблиц. * Добавлена возможность интерактивного ввода пароля в `clickhouse-client`. * Добавлена возможность отправки логов сервера в syslog ([Александр Крашенинников](https://github.com/yandex/ClickHouse/pull/2459)). * Добавлено несколько новых `SYSTEM`-запросов для реплицированных таблиц (`RESTART REPLICAS`, `SYNC REPLICA`, `[STOP|START] [MERGES|FETCHES|REPLICATED SENDS|REPLICATION QUEUES]`). @@ -15,6 +13,13 @@ * Добавлена поддержка логирования в словарях с источником shared library ([Александр Сапин](https://github.com/yandex/ClickHouse/pull/2472)). * Добавлена поддержка произвольного разделителя в формате CSV ([Иван Жуков](https://github.com/yandex/ClickHouse/pull/2263)) * Добавлена настройка `date_time_input_format`. Если переключить эту настройку в значение `'best_effort'`, значения DateTime будут читаться в широком диапазоне форматов. +* Добавлена утилита `clickhouse-obfuscator` для обфускации данных. Пример использования: публикация данных, используемых в тестах производительности. +* Добавлена табличная функция `url()` и движок таблиц `URL` ([Александр Сапин](https://github.com/yandex/ClickHouse/pull/2501)). +* В табличной функции `numbers()` добавлена возможность указывать offset ([Winter Zhang](https://github.com/yandex/ClickHouse/pull/2535)). + +## Экспериментальные возможности: +* Добавлена возможность вычислять аргументы функции `and` только там, где они нужны ([Анастасия Царькова](https://github.com/yandex/ClickHouse/pull/2272)) +* Добавлена возможность JIT-компиляции в нативный код некоторых выражений ([pyos](https://github.com/yandex/ClickHouse/pull/2277)). ## Исправление ошибок: * Исправлена ошибка при чтении столбца-массива из Nested-структуры ([#2066](https://github.com/yandex/ClickHouse/issues/2066)). @@ -33,6 +38,8 @@ * Клиентская библиотека ZooKeeper теперь использует таймаут сессии, полученный от сервера. * Исправлен синтаксический разбор и форматирование оператора `CAST`. * Исправлен race condition при записи данных из движка `Kafka` в материализованные представления ([Yangkuan Liu](https://github.com/yandex/ClickHouse/pull/2448)). +* Исправлен выход из `clickhouse-client` в multiline-режиме ([#2510](https://github.com/yandex/ClickHouse/issues/2510)). +* Исправлена ошибка в клиентской библиотеке ZooKeeper, из-за которой ожидание ответа от сервера могло длиться дольше таймаута. ## Улучшения: * Сервер с реплицированными таблицами теперь может стартовать, даже если не сконфигурирован ZooKeeper. @@ -43,6 +50,8 @@ * Разрешены выражения вида `tuple IN (SELECT tuple)`, если типы кортежей совпадают. * Ускорен анализ запроса с большим числом JOIN-ов и подзапросов. * Исправлено несоответствие в значениях счётчиков событий `Query`, `SelectQuery`, `InsertQuery`. +* Добавлен chown директорий конфигов в конфигурационном файле systemd ([Михаил Ширяев](https://github.com/yandex/ClickHouse/pull/2421)). +* Улучшена производительность разжатия LZ4. ## Изменения сборки: * Используемая версия библиотеки librdkafka обновлена до v0.11.4. @@ -50,9 +59,12 @@ * Добавлена возможность сборки компилятором gcc8. * Добавлена возможность сборки llvm из submodule. * Cmake теперь по умолчанию генерирует файлы для ninja (как при использовании `-G Ninja`). +* Добавлена возможность использования библиотеки libtinfo вместо libtermcap ([Георгий Кондратьев](https://github.com/yandex/ClickHouse/pull/2519)). +* Исправлен конфликт заголовочных файлов в Fedora Rawhide ([#2520](https://github.com/yandex/ClickHouse/issues/2520)). +* Добавлена возможность использования библиотеки libcpuid из системы, используемая версия библиотеки обновлена до 0.4.0. ## Обратно несовместимые изменения: -* Убран escaping в форматах `Vertical` и `Pretty*`. +* Убран escaping в форматах `Vertical` и `Pretty*`, удалён формат `VerticalRaw`. # ClickHouse release 1.1.54385, 2018-06-01 From 497c635260ff973f350c3712e0fc48870bef83d7 Mon Sep 17 00:00:00 2001 From: Alexey Zatelepin Date: Tue, 26 Jun 2018 20:21:05 +0300 Subject: [PATCH 25/47] Update CHANGELOG_RU.md --- CHANGELOG_RU.md | 58 ++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/CHANGELOG_RU.md b/CHANGELOG_RU.md index 24c16c54535..e68c48b071d 100644 --- a/CHANGELOG_RU.md +++ b/CHANGELOG_RU.md @@ -1,67 +1,67 @@ # ClickHouse release 1.1.54387, 2018-06-26 ## Новые возможности: -* Добавлена агрегатная функция `windowFunnel` ([sundy-li](https://github.com/yandex/ClickHouse/pull/2352)). -* Добавлена возможность записи в таблицу с движком MySQL и соответствующую табличную функцию ([sundy-li](https://github.com/yandex/ClickHouse/pull/2294)). * Добавлена поддержка запроса `ALTER TABLE t DELETE WHERE` для реплицированных таблиц и таблица `system.mutations`. * Добавлена поддержка запроса `ALTER TABLE t [REPLACE|ATTACH] PARTITION` для *MergeTree-таблиц. +* Добавлена поддержка запроса `TRUNCATE TABLE` ([Winter Zhang](https://github.com/yandex/ClickHouse/pull/2260)) +* Добавлено несколько новых `SYSTEM`-запросов для реплицированных таблиц (`RESTART REPLICAS`, `SYNC REPLICA`, `[STOP|START] [MERGES|FETCHES|REPLICATED SENDS|REPLICATION QUEUES]`). +* Добавлена возможность записи в таблицу с движком MySQL и соответствующую табличную функцию ([sundy-li](https://github.com/yandex/ClickHouse/pull/2294)). +* Добавлена табличная функция `url()` и движок таблиц `URL` ([Александр Сапин](https://github.com/yandex/ClickHouse/pull/2501)). +* Добавлена агрегатная функция `windowFunnel` ([sundy-li](https://github.com/yandex/ClickHouse/pull/2352)). +* Добавлены функции `startsWith` и `endsWith` для строк ([Вадим Плахтинский](https://github.com/yandex/ClickHouse/pull/2429)). +* В табличной функции `numbers()` добавлена возможность указывать offset ([Winter Zhang](https://github.com/yandex/ClickHouse/pull/2535)). * Добавлена возможность интерактивного ввода пароля в `clickhouse-client`. * Добавлена возможность отправки логов сервера в syslog ([Александр Крашенинников](https://github.com/yandex/ClickHouse/pull/2459)). -* Добавлено несколько новых `SYSTEM`-запросов для реплицированных таблиц (`RESTART REPLICAS`, `SYNC REPLICA`, `[STOP|START] [MERGES|FETCHES|REPLICATED SENDS|REPLICATION QUEUES]`). -* Добавлены функции `startsWith` и `endsWith` для строк ([Вадим Плахтинский](https://github.com/yandex/ClickHouse/pull/2429)). -* Добавлена поддержка запроса `TRUNCATE TABLE` ([Winter Zhang](https://github.com/yandex/ClickHouse/pull/2260)) * Добавлена поддержка логирования в словарях с источником shared library ([Александр Сапин](https://github.com/yandex/ClickHouse/pull/2472)). * Добавлена поддержка произвольного разделителя в формате CSV ([Иван Жуков](https://github.com/yandex/ClickHouse/pull/2263)) * Добавлена настройка `date_time_input_format`. Если переключить эту настройку в значение `'best_effort'`, значения DateTime будут читаться в широком диапазоне форматов. * Добавлена утилита `clickhouse-obfuscator` для обфускации данных. Пример использования: публикация данных, используемых в тестах производительности. -* Добавлена табличная функция `url()` и движок таблиц `URL` ([Александр Сапин](https://github.com/yandex/ClickHouse/pull/2501)). -* В табличной функции `numbers()` добавлена возможность указывать offset ([Winter Zhang](https://github.com/yandex/ClickHouse/pull/2535)). ## Экспериментальные возможности: * Добавлена возможность вычислять аргументы функции `and` только там, где они нужны ([Анастасия Царькова](https://github.com/yandex/ClickHouse/pull/2272)) * Добавлена возможность JIT-компиляции в нативный код некоторых выражений ([pyos](https://github.com/yandex/ClickHouse/pull/2277)). ## Исправление ошибок: +* Исправлено появление дублей в запросе с `DISTINCT` и `ORDER BY`. +* Запросы с `ARRAY JOIN` и `arrayFilter` раньше возвращали некорректный результат. * Исправлена ошибка при чтении столбца-массива из Nested-структуры ([#2066](https://github.com/yandex/ClickHouse/issues/2066)). -* Исправлено соответствие типов в табличной функции ODBC ([sundy-li](https://github.com/yandex/ClickHouse/pull/2268)). -* Исправлено применение настроек из параметров командной строки в программе clickhouse-local. * Исправлена ошибка при анализе запросов с секцией HAVING вида `HAVING tuple IN (...)`. * Исправлена ошибка при анализе запросов с рекурсивными алиасами. -* Запросы с `ARRAY JOIN` и `arrayFilter` возвращали некорректный результат. -* Исправлено некорректное сравнение типов `DateTime` с таймзоной и без неё ([Александр Бочаров](https://github.com/yandex/ClickHouse/pull/2400)). -* После `CLEAR COLUMN IN PARTITION` в соответствующей партиции теперь возможны слияния ([#2315](https://github.com/yandex/ClickHouse/issues/2315)). -* Исправлено появление дублей в запросе с `DISTINCT` и `ORDER BY`. -* Исправлена вставка в материализованное представление в случае, если движок таблицы представления - Distributed ([Babacar Diassé](https://github.com/yandex/ClickHouse/pull/2411)). -* Исправлено отсечение ненужных кусков при запросе с условием на столбцы ключа партиционирования ([#2342](https://github.com/yandex/ClickHouse/issues/2342)). * Настройки профиля пользователя не применялись при использовании сессий в HTTP-интерфейсе. -* Исправлена SSRF в табличной функции remote(). +* Исправлено применение настроек из параметров командной строки в программе clickhouse-local. * Клиентская библиотека ZooKeeper теперь использует таймаут сессии, полученный от сервера. -* Исправлен синтаксический разбор и форматирование оператора `CAST`. -* Исправлен race condition при записи данных из движка `Kafka` в материализованные представления ([Yangkuan Liu](https://github.com/yandex/ClickHouse/pull/2448)). -* Исправлен выход из `clickhouse-client` в multiline-режиме ([#2510](https://github.com/yandex/ClickHouse/issues/2510)). * Исправлена ошибка в клиентской библиотеке ZooKeeper, из-за которой ожидание ответа от сервера могло длиться дольше таймаута. +* Исправлено отсечение ненужных кусков при запросе с условием на столбцы ключа партиционирования ([#2342](https://github.com/yandex/ClickHouse/issues/2342)). +* После `CLEAR COLUMN IN PARTITION` в соответствующей партиции теперь возможны слияния ([#2315](https://github.com/yandex/ClickHouse/issues/2315)). +* Исправлено соответствие типов в табличной функции ODBC ([sundy-li](https://github.com/yandex/ClickHouse/pull/2268)). +* Исправлено некорректное сравнение типов `DateTime` с таймзоной и без неё ([Александр Бочаров](https://github.com/yandex/ClickHouse/pull/2400)). +* Исправлен синтаксический разбор и форматирование оператора `CAST`. +* Исправлена вставка в материализованное представление в случае, если движок таблицы представления - Distributed ([Babacar Diassé](https://github.com/yandex/ClickHouse/pull/2411)). +* Исправлен race condition при записи данных из движка `Kafka` в материализованные представления ([Yangkuan Liu](https://github.com/yandex/ClickHouse/pull/2448)). +* Исправлена SSRF в табличной функции remote(). +* Исправлен выход из `clickhouse-client` в multiline-режиме ([#2510](https://github.com/yandex/ClickHouse/issues/2510)). ## Улучшения: +* Фоновые задачи в реплицированных таблицах теперь выполняются не в отдельных потоках, а в пуле потоков ([Silviu Caragea](https://github.com/yandex/ClickHouse/pull/1722)) +* Улучшена производительность разжатия LZ4. +* Ускорен анализ запроса с большим числом JOIN-ов и подзапросов. +* DNS-кэш теперь автоматически обновляется при большом числе сетевых ошибок. +* Вставка в таблицу теперь не происходит, если вставка в одно из её материализованных представлений невозможна из-за того, что в нём много кусков. +* Исправлено несоответствие в значениях счётчиков событий `Query`, `SelectQuery`, `InsertQuery`. +* Разрешены выражения вида `tuple IN (SELECT tuple)`, если типы кортежей совпадают. * Сервер с реплицированными таблицами теперь может стартовать, даже если не сконфигурирован ZooKeeper. * При расчёте количества доступных ядер CPU теперь учитываются ограничения cgroups ([Atri Sharma](https://github.com/yandex/ClickHouse/pull/2325)). -* DNS-кэш теперь автоматически обновляется при большом числе сетевых ошибок. -* Фоновые задачи в реплицированных таблицах теперь выполняются не в отдельных потоках, а в пуле потоков ([Silviu Caragea](https://github.com/yandex/ClickHouse/pull/1722)) -* Вставка в таблицу теперь не происходит, если вставка в одно из её материализованных представлений невозможна из-за того, что в нём много кусков. -* Разрешены выражения вида `tuple IN (SELECT tuple)`, если типы кортежей совпадают. -* Ускорен анализ запроса с большим числом JOIN-ов и подзапросов. -* Исправлено несоответствие в значениях счётчиков событий `Query`, `SelectQuery`, `InsertQuery`. * Добавлен chown директорий конфигов в конфигурационном файле systemd ([Михаил Ширяев](https://github.com/yandex/ClickHouse/pull/2421)). -* Улучшена производительность разжатия LZ4. ## Изменения сборки: -* Используемая версия библиотеки librdkafka обновлена до v0.11.4. -* Исправлена сборка с использованием библиотеки vectorclass ([Babacar Diassé](https://github.com/yandex/ClickHouse/pull/2274)). * Добавлена возможность сборки компилятором gcc8. * Добавлена возможность сборки llvm из submodule. +* Используемая версия библиотеки librdkafka обновлена до v0.11.4. +* Добавлена возможность использования библиотеки libcpuid из системы, используемая версия библиотеки обновлена до 0.4.0. +* Исправлена сборка с использованием библиотеки vectorclass ([Babacar Diassé](https://github.com/yandex/ClickHouse/pull/2274)). * Cmake теперь по умолчанию генерирует файлы для ninja (как при использовании `-G Ninja`). * Добавлена возможность использования библиотеки libtinfo вместо libtermcap ([Георгий Кондратьев](https://github.com/yandex/ClickHouse/pull/2519)). * Исправлен конфликт заголовочных файлов в Fedora Rawhide ([#2520](https://github.com/yandex/ClickHouse/issues/2520)). -* Добавлена возможность использования библиотеки libcpuid из системы, используемая версия библиотеки обновлена до 0.4.0. ## Обратно несовместимые изменения: * Убран escaping в форматах `Vertical` и `Pretty*`, удалён формат `VerticalRaw`. From 2447755700f40af317cb80ba8800b94d6350d148 Mon Sep 17 00:00:00 2001 From: Alexey Zatelepin Date: Wed, 27 Jun 2018 13:30:13 +0300 Subject: [PATCH 26/47] BackgroundSchedulePool: remove task from delayed even it it is currently executing If the task was left in the delayed_tasks set, it could lead to a nasty bug: delayExecutionThreadFunction() would schedule the task, then it would immediately go on a next iteration and schedule the same task again. Thus this task would be continually executing, and other delayed tasks would have no chance to run. --- dbms/src/Common/BackgroundSchedulePool.cpp | 12 ++++++------ dbms/src/Common/BackgroundSchedulePool.h | 3 +++ .../MergeTree/ReplicatedMergeTreeCleanupThread.cpp | 1 - 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/dbms/src/Common/BackgroundSchedulePool.cpp b/dbms/src/Common/BackgroundSchedulePool.cpp index 80caf14e748..21e3211ea1f 100644 --- a/dbms/src/Common/BackgroundSchedulePool.cpp +++ b/dbms/src/Common/BackgroundSchedulePool.cpp @@ -42,13 +42,14 @@ bool BackgroundSchedulePool::TaskInfo::schedule() scheduled = true; - if (!executing) - { - if (delayed) - pool.cancelDelayedTask(shared_from_this(), lock); + if (delayed) + pool.cancelDelayedTask(shared_from_this(), lock); + /// If the task is not executing at the moment, enqueue it for immediate execution. + /// But if it is currently executing, do nothing because it will be enqueued + /// at the end of the execute() method. + if (!executing) pool.queue.enqueueNotification(new TaskNotification(shared_from_this())); - } return true; } @@ -123,7 +124,6 @@ void BackgroundSchedulePool::TaskInfo::execute() if (scheduled) pool.queue.enqueueNotification(new TaskNotification(shared_from_this())); } - } zkutil::WatchCallback BackgroundSchedulePool::TaskInfo::getWatchCallback() diff --git a/dbms/src/Common/BackgroundSchedulePool.h b/dbms/src/Common/BackgroundSchedulePool.h index 2fda381b111..0ebcc207b2c 100644 --- a/dbms/src/Common/BackgroundSchedulePool.h +++ b/dbms/src/Common/BackgroundSchedulePool.h @@ -70,6 +70,9 @@ public: std::mutex exec_mutex; std::mutex schedule_mutex; + /// Invariants: + /// * If deactivated is true then scheduled, delayed and executing are all false. + /// * scheduled and delayed cannot be true at the same time. bool deactivated = false; bool scheduled = false; bool delayed = false; diff --git a/dbms/src/Storages/MergeTree/ReplicatedMergeTreeCleanupThread.cpp b/dbms/src/Storages/MergeTree/ReplicatedMergeTreeCleanupThread.cpp index 05d5c1b9477..df8de692488 100644 --- a/dbms/src/Storages/MergeTree/ReplicatedMergeTreeCleanupThread.cpp +++ b/dbms/src/Storages/MergeTree/ReplicatedMergeTreeCleanupThread.cpp @@ -46,7 +46,6 @@ void ReplicatedMergeTreeCleanupThread::run() } task->scheduleAfter(CLEANUP_SLEEP_MS); - } From e03d523f191e97907e2252199c71e89291a79e7f Mon Sep 17 00:00:00 2001 From: robot-metrika-test Date: Wed, 27 Jun 2018 16:10:59 +0300 Subject: [PATCH 27/47] Auto version update to [54388] --- dbms/cmake/version.cmake | 6 +++--- debian/changelog | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dbms/cmake/version.cmake b/dbms/cmake/version.cmake index b89e32968bb..29abf098b26 100644 --- a/dbms/cmake/version.cmake +++ b/dbms/cmake/version.cmake @@ -1,7 +1,7 @@ # This strings autochanged from release_lib.sh: -set(VERSION_DESCRIBE v1.1.54387-testing) -set(VERSION_REVISION 54387) -set(VERSION_GITHASH 7ce4ebf1e1a5fefd3161b6f615eec0730d75ec34) +set(VERSION_DESCRIBE v1.1.54388-testing) +set(VERSION_REVISION 54388) +set(VERSION_GITHASH 2447755700f40af317cb80ba8800b94d6350d148) # end of autochange set (VERSION_MAJOR 1) diff --git a/debian/changelog b/debian/changelog index 867c80c4dbb..dc05db4aa45 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,5 @@ -clickhouse (1.1.54387) unstable; urgency=low +clickhouse (1.1.54388) unstable; urgency=low * Modified source code - -- Fri, 22 Jun 2018 21:10:11 +0300 + -- Wed, 27 Jun 2018 16:10:59 +0300 From e0afb1fab147ee2b091591522fb3b00b881d6157 Mon Sep 17 00:00:00 2001 From: Alexey Zatelepin Date: Wed, 27 Jun 2018 18:55:35 +0300 Subject: [PATCH 28/47] update changelog for v1.1.54388 --- CHANGELOG.draft.md | 7 ------- CHANGELOG_RU.md | 3 ++- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.draft.md b/CHANGELOG.draft.md index 614915a5523..811a7c2bb4e 100644 --- a/CHANGELOG.draft.md +++ b/CHANGELOG.draft.md @@ -1,11 +1,4 @@ # en: -## Bug fixes: -* Fixed a crash that occurred while reading from ReplacingMergeTree with prewhere condition which filters all rows. #2525 - - # ru: - -## Исправление ошибок: -* Исправлено падение при чтении из ReplacingMergeTree с условием в prewhere, фильтрующим все строки. #2525 diff --git a/CHANGELOG_RU.md b/CHANGELOG_RU.md index e68c48b071d..2fe43529a5a 100644 --- a/CHANGELOG_RU.md +++ b/CHANGELOG_RU.md @@ -1,4 +1,4 @@ -# ClickHouse release 1.1.54387, 2018-06-26 +# ClickHouse release 1.1.54388, 2018-06-28 ## Новые возможности: * Добавлена поддержка запроса `ALTER TABLE t DELETE WHERE` для реплицированных таблиц и таблица `system.mutations`. @@ -27,6 +27,7 @@ * Исправлена ошибка при чтении столбца-массива из Nested-структуры ([#2066](https://github.com/yandex/ClickHouse/issues/2066)). * Исправлена ошибка при анализе запросов с секцией HAVING вида `HAVING tuple IN (...)`. * Исправлена ошибка при анализе запросов с рекурсивными алиасами. +* Исправлена ошибка при чтении из ReplacingMergeTree с условием в PREWHERE, фильтрующим все строки ([#2525](https://github.com/yandex/ClickHouse/issues/2525)). * Настройки профиля пользователя не применялись при использовании сессий в HTTP-интерфейсе. * Исправлено применение настроек из параметров командной строки в программе clickhouse-local. * Клиентская библиотека ZooKeeper теперь использует таймаут сессии, полученный от сервера. From 5966b78d411013a76861f35474ea98dfa4503993 Mon Sep 17 00:00:00 2001 From: stavrolia Date: Wed, 27 Jun 2018 21:53:11 +0300 Subject: [PATCH 29/47] add case with external file --- .../queries/0_stateless/00625_query_in_form_data.reference | 2 ++ dbms/tests/queries/0_stateless/00625_query_in_form_data.sh | 3 +++ 2 files changed, 5 insertions(+) diff --git a/dbms/tests/queries/0_stateless/00625_query_in_form_data.reference b/dbms/tests/queries/0_stateless/00625_query_in_form_data.reference index d00491fd7e5..65ab8440601 100755 --- a/dbms/tests/queries/0_stateless/00625_query_in_form_data.reference +++ b/dbms/tests/queries/0_stateless/00625_query_in_form_data.reference @@ -1 +1,3 @@ 1 +1 Hello +2 World diff --git a/dbms/tests/queries/0_stateless/00625_query_in_form_data.sh b/dbms/tests/queries/0_stateless/00625_query_in_form_data.sh index bc387394cd0..901da66c05a 100755 --- a/dbms/tests/queries/0_stateless/00625_query_in_form_data.sh +++ b/dbms/tests/queries/0_stateless/00625_query_in_form_data.sh @@ -5,3 +5,6 @@ CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) . $CURDIR/../shell_config.sh ${CLICKHOUSE_CURL} ${CLICKHOUSE_URL}?query="select" -X POST -F "query= 1;" 2>/dev/null + + +echo -ne '1,Hello\n2,World\n' | ${CLICKHOUSE_CURL} -sSF 'file=@-' "${CLICKHOUSE_URL}?file_format=CSV&file_types=UInt8,String&query=SELE" -X POST -F "query=CT * FROM file" 2>/dev/null From c7a305eca379d719d38404b41374ce9238538df9 Mon Sep 17 00:00:00 2001 From: Mikhail Surin Date: Mon, 25 Jun 2018 10:29:53 +0300 Subject: [PATCH 30/47] fix float transform --- dbms/src/Common/RadixSort.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbms/src/Common/RadixSort.h b/dbms/src/Common/RadixSort.h index dd75477cf30..0a5861b30eb 100644 --- a/dbms/src/Common/RadixSort.h +++ b/dbms/src/Common/RadixSort.h @@ -54,7 +54,7 @@ struct RadixSortFloatTransform static KeyBits forward(KeyBits x) { - return x ^ (-(x >> (sizeof(KeyBits) * 8 - 1) | (KeyBits(1) << (sizeof(KeyBits) * 8 - 1)))); + return x ^ ((-(x >> (sizeof(KeyBits) * 8 - 1))) | (KeyBits(1) << (sizeof(KeyBits) * 8 - 1))); } static KeyBits backward(KeyBits x) From b8c4a0ba8e6f82d7243d023e3dbc2d7a24c4e2cf Mon Sep 17 00:00:00 2001 From: Alexey Zatelepin Date: Thu, 28 Jun 2018 16:52:00 +0300 Subject: [PATCH 31/47] add docs draft for mutations [#CLICKHOUSE-3687] --- docs/ru/query_language/queries.md | 42 +++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/docs/ru/query_language/queries.md b/docs/ru/query_language/queries.md index 58bc73bc44a..661c5864311 100644 --- a/docs/ru/query_language/queries.md +++ b/docs/ru/query_language/queries.md @@ -436,6 +436,48 @@ ALTER TABLE [db.]table FETCH PARTITION 'name' FROM 'path-in-zookeeper' +### Мутации + +Мутации - разновидность запроса ALTER, позволяющая изменять или удалять данные в таблице. В отличие от стандартных запросов `DELETE` и `UPDATE`, рассчитанных на точечное изменение данных, область применения мутаций - достаточно тяжёлые изменения, затрагивающие много строк в таблице. + +Функциональность находится в состоянии beta и доступна начиная с версии 1.1.54388. Реализована поддержка Replicated*MergeTree таблиц (в скором времени будет добавлена поддержка и для нереплицированных MergeTree). + +Конвертировать существующие таблицы для работы с мутациями не нужно. Но после применения первой мутации формат данных таблицы становится несовместимым с предыдущими версиями и откатиться на предыдущую версию уже не получится. + +На данный момент доступна команда `ALTER DELETE`: + +```sql +ALTER TABLE [db.]table DELETE WHERE expr +``` + +Выражение `expr` должно иметь тип UInt8. Запрос удаляет строки таблицы, для которых это выражение принимает ненулевое значение. + +В одном запросе можно указать несколько команд через запятую. + +Для *MergeTree-таблиц мутации выполняются, перезаписывая данные по кускам (parts). При этом атомарности нет - куски заменяются на помутированные по мере выполнения и запрос `SELECT`, заданный во время выполнения мутации, увидит данные как из измененных кусков, так и из кусков, которые еще не были изменены. + +Мутации линейно упорядочены между собой и накладываются на каждый кусок в порядке добавления. Мутации также упорядочены со вставками - гарантируется, что данные, вставленные в таблицу до начала выполнения запроса мутации, будут изменены, а данные, вставленные после окончания запроса мутации, изменены не будут. При этом мутации никак не блокируют вставки. + +Для реплицированных таблиц запрос завершается немедленно после добавления информации о мутации в ZooKeeper. Сама мутация выполняется асинхронно, следить за ходом её выполнения можно по таблице `system.mutations`. Добавленные мутации будут выполняться до конца даже в случае перезапуска серверов ClickHouse. Откатить мутацию после её добавления нельзя. + +#### Сиситемная таблица system.mutations + +Таблица содержит информацию о ходе выполнения мутаций MergeTree-таблиц. Каждой команде мутации соответствует одна строка. В таблице есть следующие столбцы: + +**database**, **table** - имя БД и таблицы, к которой была применена мутация. + +**mutation_id** - ID запроса. Для реплицированных таблиц эти ID соответствуют именам записей в директории `/mutations/` в ZooKeeper. + +**command** - Команда мутации (часть запроса после `ALTER TABLE [db.]table`). + +**create_time** - Время создания мутации. + +**block_numbers.partition_id**, **block_numbers.number** - Nested-столбец, для каждой партиции содержащий номер блока, полученный этой мутацией (в каждой партиции будут изменены только куски, содержащие блоки с номерами, меньшими номера, полученного мутацией в этой партиции). + +**parts_to_do** - Количество кусков таблицы, которые ещё предстоит изменить. + +**is_done** - Завершена ли мутация. Замечание: даже если `parts_to_do = 0`, возможна ситуация, когда мутация ещё не завершена из-за долго выполняющейся вставки, которая добавляет данные, которые нужно будет мутировать. + ## SHOW DATABASES ```sql From ebde528506e52a7e22c05b89e2b245e6e7681c1f Mon Sep 17 00:00:00 2001 From: Nikolai Kochetov Date: Thu, 28 Jun 2018 17:07:53 +0300 Subject: [PATCH 32/47] Create default macros in global context. [#CLICKHOUSE-3793] --- dbms/src/Interpreters/Context.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbms/src/Interpreters/Context.cpp b/dbms/src/Interpreters/Context.cpp index 49a984e948c..2ae105ff7f4 100644 --- a/dbms/src/Interpreters/Context.cpp +++ b/dbms/src/Interpreters/Context.cpp @@ -191,7 +191,7 @@ struct ContextShared Context::ConfigReloadCallback config_reload_callback; ContextShared(std::shared_ptr runtime_components_factory_) - : runtime_components_factory(std::move(runtime_components_factory_)) + : runtime_components_factory(std::move(runtime_components_factory_)), macros(std::make_unique()) { /// TODO: make it singleton (?) static std::atomic num_calls{0}; From d2e399f6884851b619cf757306358fd2f8b41060 Mon Sep 17 00:00:00 2001 From: alexey-milovidov Date: Thu, 28 Jun 2018 18:13:29 +0300 Subject: [PATCH 33/47] Update index.md --- docs/en/operations/settings/index.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/en/operations/settings/index.md b/docs/en/operations/settings/index.md index 0c5ca5d5171..2321519f9d9 100644 --- a/docs/en/operations/settings/index.md +++ b/docs/en/operations/settings/index.md @@ -7,9 +7,9 @@ Settings are configured in layers, so each subsequent layer redefines the previo Ways to configure settings, in order of priority: -- Settings in the server config file. +- Settings in the server config file `users.xml`. - Settings from user profiles. +- Settings from user profiles. - Session settings. @@ -21,4 +21,3 @@ Similarly, you can use ClickHouse sessions in the HTTP protocol. To do this, you - When using the HTTP API, pass CGI parameters (`URL?setting_1=value&setting_2=value...`). Settings that can only be made in the server config file are not covered in this section. - From b06801a3d37354d95cfe97cd7a3cef9428e812ac Mon Sep 17 00:00:00 2001 From: alexey-milovidov Date: Thu, 28 Jun 2018 18:15:37 +0300 Subject: [PATCH 34/47] Update index.md --- docs/en/operations/settings/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/operations/settings/index.md b/docs/en/operations/settings/index.md index 2321519f9d9..0a72ebac128 100644 --- a/docs/en/operations/settings/index.md +++ b/docs/en/operations/settings/index.md @@ -9,7 +9,7 @@ Ways to configure settings, in order of priority: - Settings in the server config file `users.xml`. -- Settings from user profiles. + Set it in user profile in `` element. - Session settings. From 493b67d051d13ff0ea0d0b7cb05b3ae56200f890 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Thu, 28 Jun 2018 18:59:39 +0300 Subject: [PATCH 35/47] Removed useless file [#CLICKHOUSE-2] --- dbms/tests/queries/0_stateless/99999_prepare.reference | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 dbms/tests/queries/0_stateless/99999_prepare.reference diff --git a/dbms/tests/queries/0_stateless/99999_prepare.reference b/dbms/tests/queries/0_stateless/99999_prepare.reference deleted file mode 100644 index e69de29bb2d..00000000000 From 6f21706f65ae8397086455622e3387c717376ad5 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Thu, 28 Jun 2018 19:05:41 +0300 Subject: [PATCH 36/47] Added test #2553 --- .../0_stateless/00649_quantile_tdigest_negative.reference | 1 + .../queries/0_stateless/00649_quantile_tdigest_negative.sql | 1 + 2 files changed, 2 insertions(+) create mode 100644 dbms/tests/queries/0_stateless/00649_quantile_tdigest_negative.reference create mode 100644 dbms/tests/queries/0_stateless/00649_quantile_tdigest_negative.sql diff --git a/dbms/tests/queries/0_stateless/00649_quantile_tdigest_negative.reference b/dbms/tests/queries/0_stateless/00649_quantile_tdigest_negative.reference new file mode 100644 index 00000000000..3fbedf693b5 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00649_quantile_tdigest_negative.reference @@ -0,0 +1 @@ +-2 diff --git a/dbms/tests/queries/0_stateless/00649_quantile_tdigest_negative.sql b/dbms/tests/queries/0_stateless/00649_quantile_tdigest_negative.sql new file mode 100644 index 00000000000..7e5e78a2b5d --- /dev/null +++ b/dbms/tests/queries/0_stateless/00649_quantile_tdigest_negative.sql @@ -0,0 +1 @@ +SELECT quantileTDigest(0.5)(arrayJoin([-1, -2, -3])); From acd6c8fafd01f5a80bf27bb1373e6be7c5ecd951 Mon Sep 17 00:00:00 2001 From: Nikolai Kochetov Date: Thu, 28 Jun 2018 17:51:21 +0300 Subject: [PATCH 37/47] Supported array(tuple) arguments for arrayEnumerateUniq function. [#CLICKHOUSE-3794] --- dbms/src/Functions/FunctionsArray.cpp | 29 +++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/dbms/src/Functions/FunctionsArray.cpp b/dbms/src/Functions/FunctionsArray.cpp index 3eef9754e3b..1563e6b20ee 100644 --- a/dbms/src/Functions/FunctionsArray.cpp +++ b/dbms/src/Functions/FunctionsArray.cpp @@ -1304,11 +1304,9 @@ DataTypePtr FunctionArrayEnumerateUniq::getReturnTypeImpl(const DataTypes & argu void FunctionArrayEnumerateUniq::executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) { - Columns array_columns(arguments.size()); const ColumnArray::Offsets * offsets = nullptr; - ColumnRawPtrs data_columns(arguments.size()); - ColumnRawPtrs original_data_columns(arguments.size()); - ColumnRawPtrs null_maps(arguments.size()); + ColumnRawPtrs data_columns; + data_columns.reserve(arguments.size()); bool has_nullable_columns = false; @@ -1327,7 +1325,7 @@ void FunctionArrayEnumerateUniq::executeImpl(Block & block, const ColumnNumbers array_ptr = const_array->convertToFullColumn(); array = checkAndGetColumn(array_ptr.get()); } - array_columns[i] = array_ptr; + const ColumnArray::Offsets & offsets_i = array->getOffsets(); if (i == 0) offsets = &offsets_i; @@ -1335,7 +1333,22 @@ void FunctionArrayEnumerateUniq::executeImpl(Block & block, const ColumnNumbers throw Exception("Lengths of all arrays passed to " + getName() + " must be equal.", ErrorCodes::SIZES_OF_ARRAYS_DOESNT_MATCH); - data_columns[i] = &array->getData(); + auto * array_data = &array->getData(); + if (auto * tuple_column = checkAndGetColumn(array_data)) + { + for (const auto & element : tuple_column->getColumns()) + data_columns.push_back(element.get()); + } + else + data_columns.push_back(array_data); + } + + size_t num_columns = data_columns.size(); + ColumnRawPtrs original_data_columns(num_columns); + ColumnRawPtrs null_maps(num_columns); + + for (size_t i = 0; i < num_columns; ++i) + { original_data_columns[i] = data_columns[i]; if (data_columns[i]->isColumnNullable()) @@ -1349,7 +1362,7 @@ void FunctionArrayEnumerateUniq::executeImpl(Block & block, const ColumnNumbers null_maps[i] = nullptr; } - const ColumnArray * first_array = checkAndGetColumn(array_columns[0].get()); + const ColumnArray * first_array = checkAndGetColumn(block.getByPosition(arguments.at(0)).column.get()); const IColumn * first_null_map = null_maps[0]; auto res_nested = ColumnUInt32::create(); @@ -1357,7 +1370,7 @@ void FunctionArrayEnumerateUniq::executeImpl(Block & block, const ColumnNumbers if (!offsets->empty()) res_values.resize(offsets->back()); - if (arguments.size() == 1) + if (num_columns == 1) { if (!( executeNumber(first_array, first_null_map, res_values) || executeNumber(first_array, first_null_map, res_values) From 29ef36a270df208d969d40a6d21cdfb5a1e80234 Mon Sep 17 00:00:00 2001 From: Nikolai Kochetov Date: Thu, 28 Jun 2018 18:11:05 +0300 Subject: [PATCH 38/47] Added test. [#CLICKHOUSE-3794] --- ...array_enumerate_uniq_with_tuples.reference | 12 +++++++++++ ...00742_array_enumerate_uniq_with_tuples.sql | 20 +++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 dbms/tests/queries/0_stateless/00742_array_enumerate_uniq_with_tuples.reference create mode 100644 dbms/tests/queries/0_stateless/00742_array_enumerate_uniq_with_tuples.sql diff --git a/dbms/tests/queries/0_stateless/00742_array_enumerate_uniq_with_tuples.reference b/dbms/tests/queries/0_stateless/00742_array_enumerate_uniq_with_tuples.reference new file mode 100644 index 00000000000..e6cf6494ed0 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00742_array_enumerate_uniq_with_tuples.reference @@ -0,0 +1,12 @@ +[1,1,2,3,2,4] +[1,2,1,3,2,3] +[1,1,1,2,1,2] +[1,1,1,2,1,2] +[1,1,1,2,1,2] +[1,1,1,2,1,2] +[1,1,1,2,3,2,4,2,3] +[1,2,3,1,4,2,3,4,5] +[1,1,1,1,2,1,2,1,2] +[1,1,1,1,2,1,2,1,2] +[1,1,1,1,2,1,2,1,2] +[1,1,1,1,2,1,2,1,2] diff --git a/dbms/tests/queries/0_stateless/00742_array_enumerate_uniq_with_tuples.sql b/dbms/tests/queries/0_stateless/00742_array_enumerate_uniq_with_tuples.sql new file mode 100644 index 00000000000..43cf154d25c --- /dev/null +++ b/dbms/tests/queries/0_stateless/00742_array_enumerate_uniq_with_tuples.sql @@ -0,0 +1,20 @@ +drop table if exists test.tab; +create table test.tab (val UInt32, n Nested(x UInt8, y String)) engine = Memory; +insert into test.tab values (1, [1, 2, 1, 1, 2, 1], ['a', 'a', 'b', 'a', 'b', 'b']); +select arrayEnumerateUniq(n.x) from test.tab; +select arrayEnumerateUniq(n.y) from test.tab; +select arrayEnumerateUniq(n.x, n.y) from test.tab; +select arrayEnumerateUniq(arrayMap((a, b) -> (a, b), n.x, n.y)) from test.tab; +select arrayEnumerateUniq(arrayMap((a, b) -> (a, b), n.x, n.y), n.x) from test.tab; +select arrayEnumerateUniq(arrayMap((a, b) -> (a, b), n.x, n.y), arrayMap((a, b) -> (b, a), n.x, n.y)) from test.tab; + +drop table test.tab; +create table test.tab (val UInt32, n Nested(x Nullable(UInt8), y String)) engine = Memory; +insert into test.tab values (1, [1, Null, 2, 1, 1, 2, 1, Null, Null], ['a', 'a', 'a', 'b', 'a', 'b', 'b', 'b', 'a']); +select arrayEnumerateUniq(n.x) from test.tab; +select arrayEnumerateUniq(n.y) from test.tab; +select arrayEnumerateUniq(n.x, n.y) from test.tab; +select arrayEnumerateUniq(arrayMap((a, b) -> (a, b), n.x, n.y)) from test.tab; +select arrayEnumerateUniq(arrayMap((a, b) -> (a, b), n.x, n.y), n.x) from test.tab; +select arrayEnumerateUniq(arrayMap((a, b) -> (a, b), n.x, n.y), arrayMap((a, b) -> (b, a), n.x, n.y)) from test.tab; + From bd4a899dd3fa25e3b9eb88ace2e97bd3794090a3 Mon Sep 17 00:00:00 2001 From: Nikolai Kochetov Date: Wed, 27 Jun 2018 16:16:12 +0300 Subject: [PATCH 39/47] Reduced the number of IAST::getColumnName() calls in ExpressionAnalyzer. --- dbms/src/Interpreters/ExpressionAnalyzer.cpp | 39 ++++++++++++-------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/dbms/src/Interpreters/ExpressionAnalyzer.cpp b/dbms/src/Interpreters/ExpressionAnalyzer.cpp index 9a51155d9ea..6eb4e510ac4 100644 --- a/dbms/src/Interpreters/ExpressionAnalyzer.cpp +++ b/dbms/src/Interpreters/ExpressionAnalyzer.cpp @@ -1983,26 +1983,34 @@ bool ExpressionAnalyzer::isThereArrayJoin(const ASTPtr & ast) void ExpressionAnalyzer::getActionsImpl(const ASTPtr & ast, bool no_subqueries, bool only_consts, ScopeStack & actions_stack, ProjectionManipulatorPtr projection_manipulator) { + String ast_column_name; + auto getColumnName = [&ast, &ast_column_name]() + { + if (ast_column_name.empty()) + ast_column_name = ast->getColumnName(); + + return ast_column_name; + }; + /// If the result of the calculation already exists in the block. if ((typeid_cast(ast.get()) || typeid_cast(ast.get())) - && projection_manipulator->tryToGetFromUpperProjection(ast->getColumnName())) + && projection_manipulator->tryToGetFromUpperProjection(getColumnName())) return; - if (ASTIdentifier * node = typeid_cast(ast.get())) + if (typeid_cast(ast.get())) { - std::string name = node->getColumnName(); - if (!only_consts && !projection_manipulator->tryToGetFromUpperProjection(ast->getColumnName())) + if (!only_consts && !projection_manipulator->tryToGetFromUpperProjection(getColumnName())) { /// The requested column is not in the block. /// If such a column exists in the table, then the user probably forgot to surround it with an aggregate function or add it to GROUP BY. bool found = false; for (const auto & column_name_type : source_columns) - if (column_name_type.name == name) + if (column_name_type.name == getColumnName()) found = true; if (found) - throw Exception("Column " + name + " is not under aggregate function and not in GROUP BY.", + throw Exception("Column " + getColumnName() + " is not under aggregate function and not in GROUP BY.", ErrorCodes::NOT_AN_AGGREGATE); } } @@ -2021,7 +2029,7 @@ void ExpressionAnalyzer::getActionsImpl(const ASTPtr & ast, bool no_subqueries, getActionsImpl(arg, no_subqueries, only_consts, actions_stack, projection_manipulator); if (!only_consts) { - String result_name = projection_manipulator->getColumnName(node->getColumnName()); + String result_name = projection_manipulator->getColumnName(getColumnName()); actions_stack.addAction(ExpressionAction::copyColumn(projection_manipulator->getColumnName(arg->getColumnName()), result_name)); NameSet joined_columns; joined_columns.insert(result_name); @@ -2049,7 +2057,7 @@ void ExpressionAnalyzer::getActionsImpl(const ASTPtr & ast, bool no_subqueries, /// We are in the part of the tree that we are not going to compute. You just need to define types. /// Do not subquery and create sets. We insert an arbitrary column of the correct type. ColumnWithTypeAndName fake_column; - fake_column.name = projection_manipulator->getColumnName(node->getColumnName()); + fake_column.name = projection_manipulator->getColumnName(getColumnName()); fake_column.type = std::make_shared(); actions_stack.addAction(ExpressionAction::addColumn(fake_column, projection_manipulator->getProjectionSourceColumn(), false)); getActionsImpl(node->arguments->children.at(0), no_subqueries, only_consts, actions_stack, @@ -2065,7 +2073,7 @@ void ExpressionAnalyzer::getActionsImpl(const ASTPtr & ast, bool no_subqueries, { actions_stack.addAction(ExpressionAction::addColumn(ColumnWithTypeAndName( ColumnConst::create(ColumnUInt8::create(1, 1), 1), std::make_shared(), - projection_manipulator->getColumnName(node->getColumnName())), projection_manipulator->getProjectionSourceColumn(), false)); + projection_manipulator->getColumnName(getColumnName())), projection_manipulator->getProjectionSourceColumn(), false)); return; } @@ -2073,7 +2081,7 @@ void ExpressionAnalyzer::getActionsImpl(const ASTPtr & ast, bool no_subqueries, return; const FunctionBuilderPtr & function_builder = FunctionFactory::instance().get(node->name, context); - auto projection_action = getProjectionAction(node->name, actions_stack, projection_manipulator, node->getColumnName(), context); + auto projection_action = getProjectionAction(node->name, actions_stack, projection_manipulator, getColumnName(), context); Names argument_names; DataTypes argument_types; @@ -2085,6 +2093,7 @@ void ExpressionAnalyzer::getActionsImpl(const ASTPtr & ast, bool no_subqueries, for (size_t arg = 0; arg < node->arguments->children.size(); ++arg) { auto & child = node->arguments->children[arg]; + auto child_column_name = child->getColumnName(); ASTFunction * lambda = typeid_cast(child.get()); if (lambda && lambda->name == "lambda") @@ -2115,7 +2124,7 @@ void ExpressionAnalyzer::getActionsImpl(const ASTPtr & ast, bool no_subqueries, if (!set->empty()) column.name = getUniqueName(actions_stack.getSampleBlock(), "__set"); else - column.name = child->getColumnName(); + column.name = child_column_name; column.name = projection_manipulator->getColumnName(column.name); @@ -2135,8 +2144,8 @@ void ExpressionAnalyzer::getActionsImpl(const ASTPtr & ast, bool no_subqueries, projection_action->preArgumentAction(); getActionsImpl(child, no_subqueries, only_consts, actions_stack, projection_manipulator); - std::string name = projection_manipulator->getColumnName(child->getColumnName()); - projection_action->postArgumentAction(child->getColumnName()); + std::string name = projection_manipulator->getColumnName(child_column_name); + projection_action->postArgumentAction(child_column_name); if (actions_stack.getSampleBlock().has(name)) { argument_types.push_back(actions_stack.getSampleBlock().getByName(name).type); @@ -2239,7 +2248,7 @@ void ExpressionAnalyzer::getActionsImpl(const ASTPtr & ast, bool no_subqueries, actions_stack.addAction( ExpressionAction::applyFunction(function_builder, argument_names, - projection_manipulator->getColumnName(node->getColumnName()), + projection_manipulator->getColumnName(getColumnName()), projection_manipulator->getProjectionSourceColumn())); } } @@ -2251,7 +2260,7 @@ void ExpressionAnalyzer::getActionsImpl(const ASTPtr & ast, bool no_subqueries, ColumnWithTypeAndName column; column.column = type->createColumnConst(1, convertFieldToType(node->value, *type)); column.type = type; - column.name = node->getColumnName(); + column.name = getColumnName(); actions_stack.addAction(ExpressionAction::addColumn(column, "", false)); projection_manipulator->tryToGetFromUpperProjection(column.name); From 782caef119a730edb8a55d1b4305e4ef8c9c30e1 Mon Sep 17 00:00:00 2001 From: Nikolai Kochetov Date: Wed, 27 Jun 2018 19:34:11 +0300 Subject: [PATCH 40/47] Added IAST::appendColumnName(WriteBuffer &); reimplemented IAST::getColumnName() using it. --- dbms/src/Parsers/ASTAsterisk.cpp | 21 ++++++++++++++++++ dbms/src/Parsers/ASTAsterisk.h | 14 +++--------- dbms/src/Parsers/ASTFunction.cpp | 26 +++++++++++------------ dbms/src/Parsers/ASTFunction.h | 2 +- dbms/src/Parsers/ASTIdentifier.cpp | 5 +++++ dbms/src/Parsers/ASTIdentifier.h | 2 +- dbms/src/Parsers/ASTLiteral.cpp | 16 +++++++++----- dbms/src/Parsers/ASTLiteral.h | 2 +- dbms/src/Parsers/ASTQualifiedAsterisk.cpp | 6 ++++-- dbms/src/Parsers/ASTQualifiedAsterisk.h | 2 +- dbms/src/Parsers/ASTSubquery.cpp | 22 ++++++++++++++++--- dbms/src/Parsers/ASTSubquery.h | 16 ++------------ dbms/src/Parsers/ASTWithAlias.cpp | 8 +++++++ dbms/src/Parsers/ASTWithAlias.h | 6 +++--- dbms/src/Parsers/IAST.cpp | 12 +++++++++++ dbms/src/Parsers/IAST.h | 6 +++++- 16 files changed, 109 insertions(+), 57 deletions(-) create mode 100644 dbms/src/Parsers/ASTAsterisk.cpp diff --git a/dbms/src/Parsers/ASTAsterisk.cpp b/dbms/src/Parsers/ASTAsterisk.cpp new file mode 100644 index 00000000000..19aefa1fc29 --- /dev/null +++ b/dbms/src/Parsers/ASTAsterisk.cpp @@ -0,0 +1,21 @@ +#include +#include + +namespace DB +{ + +ASTPtr ASTAsterisk::clone() const +{ + auto clone = std::make_shared(*this); + clone->cloneChildren(); + return std::move(clone); +} + +void ASTAsterisk::appendColumnName(WriteBuffer & ostr) const { ostr.write('*'); } + +void ASTAsterisk::formatImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const +{ + settings.ostr << "*"; +} + +} diff --git a/dbms/src/Parsers/ASTAsterisk.h b/dbms/src/Parsers/ASTAsterisk.h index 2308a0179ec..02a0f99895d 100644 --- a/dbms/src/Parsers/ASTAsterisk.h +++ b/dbms/src/Parsers/ASTAsterisk.h @@ -10,19 +10,11 @@ class ASTAsterisk : public IAST { public: String getID() const override { return "Asterisk"; } - ASTPtr clone() const override - { - auto clone = std::make_shared(*this); - clone->cloneChildren(); - return std::move(clone); - } - String getColumnName() const override { return "*"; } + ASTPtr clone() const override; + void appendColumnName(WriteBuffer & ostr) const override; protected: - void formatImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const override - { - settings.ostr << "*"; - } + void formatImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const override; }; } diff --git a/dbms/src/Parsers/ASTFunction.cpp b/dbms/src/Parsers/ASTFunction.cpp index c972a9e64c4..d84d77b649b 100644 --- a/dbms/src/Parsers/ASTFunction.cpp +++ b/dbms/src/Parsers/ASTFunction.cpp @@ -9,32 +9,30 @@ namespace DB { -String ASTFunction::getColumnNameImpl() const +void ASTFunction::appendColumnNameImpl(WriteBuffer & ostr) const { - WriteBufferFromOwnString wb; - writeString(name, wb); + writeString(name, ostr); if (parameters) { - writeChar('(', wb); - for (ASTs::const_iterator it = parameters->children.begin(); it != parameters->children.end(); ++it) + writeChar('(', ostr); + for (auto it = parameters->children.begin(); it != parameters->children.end(); ++it) { if (it != parameters->children.begin()) - writeCString(", ", wb); - writeString((*it)->getColumnName(), wb); + writeCString(", ", ostr); + (*it)->appendColumnName(ostr); } - writeChar(')', wb); + writeChar(')', ostr); } - writeChar('(', wb); - for (ASTs::const_iterator it = arguments->children.begin(); it != arguments->children.end(); ++it) + writeChar('(', ostr); + for (auto it = arguments->children.begin(); it != arguments->children.end(); ++it) { if (it != arguments->children.begin()) - writeCString(", ", wb); - writeString((*it)->getColumnName(), wb); + writeCString(", ", ostr); + (*it)->appendColumnName(ostr); } - writeChar(')', wb); - return wb.str(); + writeChar(')', ostr); } /** Get the text that identifies this element. */ diff --git a/dbms/src/Parsers/ASTFunction.h b/dbms/src/Parsers/ASTFunction.h index 9e78de369a1..e580b8c38b1 100644 --- a/dbms/src/Parsers/ASTFunction.h +++ b/dbms/src/Parsers/ASTFunction.h @@ -25,7 +25,7 @@ public: protected: void formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override; - String getColumnNameImpl() const override; + void appendColumnNameImpl(WriteBuffer & ostr) const override; }; diff --git a/dbms/src/Parsers/ASTIdentifier.cpp b/dbms/src/Parsers/ASTIdentifier.cpp index 1fed3a29842..7a8f8b639fe 100644 --- a/dbms/src/Parsers/ASTIdentifier.cpp +++ b/dbms/src/Parsers/ASTIdentifier.cpp @@ -37,4 +37,9 @@ void ASTIdentifier::formatImplWithoutAlias(const FormatSettings & settings, Form } } +void ASTIdentifier::appendColumnNameImpl(WriteBuffer & ostr) const +{ + writeString(name, ostr); +} + } diff --git a/dbms/src/Parsers/ASTIdentifier.h b/dbms/src/Parsers/ASTIdentifier.h index 4374255b874..1ef06711505 100644 --- a/dbms/src/Parsers/ASTIdentifier.h +++ b/dbms/src/Parsers/ASTIdentifier.h @@ -40,7 +40,7 @@ public: protected: void formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override; - String getColumnNameImpl() const override { return name; } + void appendColumnNameImpl(WriteBuffer & ostr) const override; }; } diff --git a/dbms/src/Parsers/ASTLiteral.cpp b/dbms/src/Parsers/ASTLiteral.cpp index ef0f01a4aeb..18a16d0f630 100644 --- a/dbms/src/Parsers/ASTLiteral.cpp +++ b/dbms/src/Parsers/ASTLiteral.cpp @@ -7,8 +7,7 @@ namespace DB { - -String ASTLiteral::getColumnNameImpl() const +void ASTLiteral::appendColumnNameImpl(WriteBuffer & ostr) const { /// Special case for very large arrays. Instead of listing all elements, will use hash of them. /// (Otherwise column name will be too long, that will lead to significant slowdown of expression analysis.) @@ -19,10 +18,17 @@ String ASTLiteral::getColumnNameImpl() const applyVisitor(FieldVisitorHash(hash), value); UInt64 low, high; hash.get128(low, high); - return "__array_" + toString(low) + "_" + toString(high); + + writeCString("__array_", ostr); + writeText(low, ostr); + ostr.write('_'); + writeText(high, ostr); + } + else + { + String column_name = applyVisitor(FieldVisitorToString(), value); + writeString(column_name, ostr); } - - return applyVisitor(FieldVisitorToString(), value); } } diff --git a/dbms/src/Parsers/ASTLiteral.h b/dbms/src/Parsers/ASTLiteral.h index 36707a7e950..d2b86cbb28c 100644 --- a/dbms/src/Parsers/ASTLiteral.h +++ b/dbms/src/Parsers/ASTLiteral.h @@ -28,7 +28,7 @@ protected: settings.ostr << applyVisitor(FieldVisitorToString(), value); } - String getColumnNameImpl() const override; + void appendColumnNameImpl(WriteBuffer & ostr) const override; }; } diff --git a/dbms/src/Parsers/ASTQualifiedAsterisk.cpp b/dbms/src/Parsers/ASTQualifiedAsterisk.cpp index b5c83b6554f..cbde6d4f15d 100644 --- a/dbms/src/Parsers/ASTQualifiedAsterisk.cpp +++ b/dbms/src/Parsers/ASTQualifiedAsterisk.cpp @@ -1,12 +1,14 @@ #include +#include namespace DB { -String ASTQualifiedAsterisk::getColumnName() const +void ASTQualifiedAsterisk::appendColumnName(WriteBuffer & ostr) const { const auto & qualifier = children.at(0); - return qualifier->getColumnName() + ".*"; + qualifier->appendColumnName(ostr); + writeCString(".*", ostr); } void ASTQualifiedAsterisk::formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const diff --git a/dbms/src/Parsers/ASTQualifiedAsterisk.h b/dbms/src/Parsers/ASTQualifiedAsterisk.h index 83a5b4f20bd..eb800b3aedc 100644 --- a/dbms/src/Parsers/ASTQualifiedAsterisk.h +++ b/dbms/src/Parsers/ASTQualifiedAsterisk.h @@ -19,7 +19,7 @@ public: clone->cloneChildren(); return std::move(clone); } - String getColumnName() const override; + void appendColumnName(WriteBuffer & ostr) const override; protected: void formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override; diff --git a/dbms/src/Parsers/ASTSubquery.cpp b/dbms/src/Parsers/ASTSubquery.cpp index 7b90b8a931b..b0d45cd26f1 100644 --- a/dbms/src/Parsers/ASTSubquery.cpp +++ b/dbms/src/Parsers/ASTSubquery.cpp @@ -4,14 +4,30 @@ namespace DB { -String ASTSubquery::getColumnNameImpl() const +void ASTSubquery::appendColumnNameImpl(WriteBuffer & ostr) const { /// This is a hack. We use alias, if available, because otherwise tree could change during analysis. if (!alias.empty()) - return alias; + writeString(alias, ostr); Hash hash = getTreeHash(); - return "__subquery_" + toString(hash.first) + "_" + toString(hash.second); + writeCString("__subquery_", ostr); + writeText(hash.first, ostr); + ostr.write('_'); + writeText(hash.second, ostr); +} + +void ASTSubquery::formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const +{ + std::string indent_str = settings.one_line ? "" : std::string(4u * frame.indent, ' '); + std::string nl_or_nothing = settings.one_line ? "" : "\n"; + + settings.ostr << nl_or_nothing << indent_str << "(" << nl_or_nothing; + FormatStateStacked frame_nested = frame; + frame_nested.need_parens = false; + ++frame_nested.indent; + children[0]->formatImpl(settings, state, frame_nested); + settings.ostr << nl_or_nothing << indent_str << ")"; } } diff --git a/dbms/src/Parsers/ASTSubquery.h b/dbms/src/Parsers/ASTSubquery.h index 1b9ba97ac88..513f0673c6b 100644 --- a/dbms/src/Parsers/ASTSubquery.h +++ b/dbms/src/Parsers/ASTSubquery.h @@ -29,20 +29,8 @@ public: } protected: - void formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override - { - std::string indent_str = settings.one_line ? "" : std::string(4 * frame.indent, ' '); - std::string nl_or_nothing = settings.one_line ? "" : "\n"; - - settings.ostr << nl_or_nothing << indent_str << "(" << nl_or_nothing; - FormatStateStacked frame_nested = frame; - frame_nested.need_parens = false; - ++frame_nested.indent; - children[0]->formatImpl(settings, state, frame_nested); - settings.ostr << nl_or_nothing << indent_str << ")"; - } - - String getColumnNameImpl() const override; + void formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override; + void appendColumnNameImpl(WriteBuffer & ostr) const override; }; } diff --git a/dbms/src/Parsers/ASTWithAlias.cpp b/dbms/src/Parsers/ASTWithAlias.cpp index fae4cf6b664..1f46160ec43 100644 --- a/dbms/src/Parsers/ASTWithAlias.cpp +++ b/dbms/src/Parsers/ASTWithAlias.cpp @@ -33,4 +33,12 @@ void ASTWithAlias::formatImpl(const FormatSettings & settings, FormatState & sta } } +void ASTWithAlias::appendColumnName(WriteBuffer & ostr) const +{ + if (prefer_alias_to_column_name && !alias.empty()) + writeString(alias, ostr); + else + appendColumnNameImpl(ostr); +} + } diff --git a/dbms/src/Parsers/ASTWithAlias.h b/dbms/src/Parsers/ASTWithAlias.h index 2ab863b3132..a868b29c757 100644 --- a/dbms/src/Parsers/ASTWithAlias.h +++ b/dbms/src/Parsers/ASTWithAlias.h @@ -20,8 +20,8 @@ public: using IAST::IAST; - String getColumnName() const override final { return prefer_alias_to_column_name && !alias.empty() ? alias : getColumnNameImpl(); } - String getAliasOrColumnName() const override { return alias.empty() ? getColumnNameImpl() : alias; } + void appendColumnName(WriteBuffer & ostr) const final; + String getAliasOrColumnName() const override { return alias.empty() ? getColumnName() : alias; } String tryGetAlias() const override { return alias; } void setAlias(const String & to) override { alias = to; } @@ -31,7 +31,7 @@ public: virtual void formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const = 0; protected: - virtual String getColumnNameImpl() const = 0; + virtual void appendColumnNameImpl(WriteBuffer & ostr) const = 0; }; /// helper for setting aliases and chaining result to other functions diff --git a/dbms/src/Parsers/IAST.cpp b/dbms/src/Parsers/IAST.cpp index 7b48d749627..8eddfdd74c4 100644 --- a/dbms/src/Parsers/IAST.cpp +++ b/dbms/src/Parsers/IAST.cpp @@ -101,4 +101,16 @@ void IAST::cloneChildren() child = child->clone(); } + +String IAST::getColumnName() const +{ + String column_name; + { + WriteBufferFromString write_buffer(column_name); + appendColumnName(write_buffer); + } + + return column_name; +} + } diff --git a/dbms/src/Parsers/IAST.h b/dbms/src/Parsers/IAST.h index e1d36112392..22491a053d3 100644 --- a/dbms/src/Parsers/IAST.h +++ b/dbms/src/Parsers/IAST.h @@ -46,7 +46,11 @@ public: virtual ~IAST() = default; /** Get the canonical name of the column if the element is a column */ - virtual String getColumnName() const { throw Exception("Trying to get name of not a column: " + getID(), ErrorCodes::NOT_A_COLUMN); } + String getColumnName() const; + virtual void appendColumnName(WriteBuffer &) const + { + throw Exception("Trying to get name of not a column: " + getID(), ErrorCodes::NOT_A_COLUMN); + } /** Get the alias, if any, or the canonical name of the column, if it is not. */ virtual String getAliasOrColumnName() const { return getColumnName(); } From b7ac6ac8c13db61cd49257e2a68c80d5aae056c7 Mon Sep 17 00:00:00 2001 From: alexey-milovidov Date: Thu, 28 Jun 2018 20:22:14 +0300 Subject: [PATCH 41/47] Update IAST.cpp --- dbms/src/Parsers/IAST.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/dbms/src/Parsers/IAST.cpp b/dbms/src/Parsers/IAST.cpp index 8eddfdd74c4..aaed05bc9da 100644 --- a/dbms/src/Parsers/IAST.cpp +++ b/dbms/src/Parsers/IAST.cpp @@ -104,13 +104,9 @@ void IAST::cloneChildren() String IAST::getColumnName() const { - String column_name; - { - WriteBufferFromString write_buffer(column_name); - appendColumnName(write_buffer); - } - - return column_name; + WriteBufferFromOwnString write_buffer; + appendColumnName(write_buffer); + return write_buffer.str(); } } From 74a8996367aa953687441df1669cf30064bb66ec Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Fri, 29 Jun 2018 15:07:07 +0300 Subject: [PATCH 42/47] Updated information about Gentoo (tnx. kmeaw) [#CLICKHOUSE-2] --- docs/en/getting_started/index.md | 2 +- docs/ru/getting_started/index.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/en/getting_started/index.md b/docs/en/getting_started/index.md index 584cea354cb..34ac16fca2e 100644 --- a/docs/en/getting_started/index.md +++ b/docs/en/getting_started/index.md @@ -70,7 +70,7 @@ Docker image: RPM packages for CentOS or RHEL: -Gentoo overlay: +Gentoo: `emerge clickhouse` ## Launch diff --git a/docs/ru/getting_started/index.md b/docs/ru/getting_started/index.md index d73e21de9b8..66bf5649987 100644 --- a/docs/ru/getting_started/index.md +++ b/docs/ru/getting_started/index.md @@ -16,7 +16,7 @@ grep -q sse4_2 /proc/cpuinfo && echo "SSE 4.2 supported" || echo "SSE 4.2 not su В целях тестирования и разработки, система может быть установлена на один сервер или на рабочий компьютер. -### Установка из пакетов для Debian/Ubuntu +### Установка из пакетов для Debian/Ubuntu Пропишите в `/etc/apt/sources.list` (или в отдельный файл `/etc/apt/sources.list.d/clickhouse.list`) репозитории: @@ -70,7 +70,7 @@ Docker образ: RPM пакеты для CentOS, RHEL: -Gentoo overlay: +Gentoo: `emerge clickhouse` ## Запуск From 3cbced0d2a574b486ecba64708ef715862f4e037 Mon Sep 17 00:00:00 2001 From: Alexey Zatelepin Date: Fri, 29 Jun 2018 16:46:28 +0300 Subject: [PATCH 43/47] add integration test for mutations of Replicated tables [#CLICKHOUSE-3747] --- .../test_replicated_mutations/__init__.py | 0 .../test_replicated_mutations/test.py | 175 ++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 dbms/tests/integration/test_replicated_mutations/__init__.py create mode 100644 dbms/tests/integration/test_replicated_mutations/test.py diff --git a/dbms/tests/integration/test_replicated_mutations/__init__.py b/dbms/tests/integration/test_replicated_mutations/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dbms/tests/integration/test_replicated_mutations/test.py b/dbms/tests/integration/test_replicated_mutations/test.py new file mode 100644 index 00000000000..e44bc51e6be --- /dev/null +++ b/dbms/tests/integration/test_replicated_mutations/test.py @@ -0,0 +1,175 @@ +import time +import threading +import random +from collections import Counter + +import pytest + +from helpers.cluster import ClickHouseCluster + + +cluster = ClickHouseCluster(__file__) + +node1 = cluster.add_instance('node1', with_zookeeper=True) +node2 = cluster.add_instance('node2', with_zookeeper=True) +nodes = [node1, node2] + +@pytest.fixture(scope="module") +def started_cluster(): + try: + cluster.start() + + for node in nodes: + node.query("DROP TABLE IF EXISTS test_mutations") + + for node in nodes: + node.query("CREATE TABLE test_mutations(d Date, x UInt32, i UInt32) ENGINE ReplicatedMergeTree('/clickhouse/tables/test/test_mutations', '{instance}') ORDER BY x PARTITION BY toYYYYMM(d)") + + yield cluster + + finally: + cluster.shutdown() + + +class Runner: + def __init__(self): + self.mtx = threading.Lock() + self.total_inserted_xs = 0 + self.total_inserted_rows = 0 + + self.total_mutations = 0 + self.total_deleted_xs = 0 + self.total_deleted_rows = 0 + + self.current_xs = Counter() + + self.currently_inserting_xs = Counter() + self.currently_deleting_xs = set() + + self.stop_ev = threading.Event() + + def do_insert(self, thread_num): + self.stop_ev.wait(random.random()) + + # Each thread inserts a small random number of rows with random year, month 01 and day determined + # by the thread number. The idea is to avoid spurious duplicates and to insert into a + # nontrivial number of partitions. + month = '01' + day = str(thread_num + 1).zfill(2) + i = 1 + while not self.stop_ev.is_set(): + xs = [random.randint(1, 10) for _ in range(random.randint(1, 10))] + with self.mtx: + xs = [x for x in xs if x not in self.currently_deleting_xs] + if len(xs) == 0: + continue + for x in xs: + self.currently_inserting_xs[x] += 1 + + year = 2000 + random.randint(0, 10) + date_str = '{year}-{month}-{day}'.format(year=year, month=month, day=day) + payload = '' + for x in xs: + payload += '{date_str} {x} {i}\n'.format(date_str=date_str, x=x, i=i) + i += 1 + + try: + print 'thread {}: insert for {}: {}'.format(thread_num, date_str, ','.join(str(x) for x in xs)) + random.choice(nodes).query("INSERT INTO test_mutations FORMAT TSV", payload) + + with self.mtx: + for x in xs: + self.current_xs[x] += 1 + self.total_inserted_xs += sum(xs) + self.total_inserted_rows += len(xs) + + except Exception, e: + print 'Exception while inserting,', e + finally: + with self.mtx: + for x in xs: + self.currently_inserting_xs[x] -= 1 + + self.stop_ev.wait(0.2 + random.random() / 5) + + def do_delete(self, thread_num): + self.stop_ev.wait(1.0 + random.random()) + + while not self.stop_ev.is_set(): + chosen = False + with self.mtx: + if self.current_xs: + x = random.choice(list(self.current_xs.elements())) + + if self.currently_inserting_xs[x] == 0 and x not in self.currently_deleting_xs: + chosen = True + self.currently_deleting_xs.add(x) + to_delete_count = self.current_xs[x] + + if not chosen: + self.stop_ev.wait(0.1 * random.random()) + continue + + try: + print 'thread {}: delete {} * {}'.format(thread_num, to_delete_count, x) + random.choice(nodes).query("ALTER TABLE test_mutations DELETE WHERE x = {}".format(x)) + + with self.mtx: + self.total_mutations += 1 + self.current_xs[x] -= to_delete_count + self.total_deleted_xs += to_delete_count * x + self.total_deleted_rows += to_delete_count + + except Exception, e: + print 'Exception while deleting,', e + finally: + with self.mtx: + self.currently_deleting_xs.remove(x) + + self.stop_ev.wait(1.0 + random.random() * 2) + + +def test_mutations(started_cluster): + DURATION_SECONDS = 50 + + runner = Runner() + + threads = [] + for thread_num in range(5): + threads.append(threading.Thread(target=runner.do_insert, args=(thread_num, ))) + + for thread_num in (11, 12, 13): + threads.append(threading.Thread(target=runner.do_delete, args=(thread_num,))) + + for t in threads: + t.start() + + time.sleep(DURATION_SECONDS) + runner.stop_ev.set() + + for t in threads: + t.join() + + # Sanity check: at least something was inserted and something was deleted + assert runner.total_inserted_rows > 0 + assert runner.total_mutations > 0 + + all_done = False + for i in range(100): # wait for replication 10 seconds max + time.sleep(0.1) + + def get_done_mutations(node): + return int(node.query("SELECT sum(is_done) FROM system.mutations WHERE table = 'test_mutations'").rstrip()) + + if all([get_done_mutations(n) == runner.total_mutations for n in nodes]): + all_done = True + break + + print node1.query("SELECT mutation_id, command, parts_to_do, is_done FROM system.mutations WHERE table = 'test_mutations' FORMAT TSVWithNames") + assert all_done + + expected_sum = runner.total_inserted_xs - runner.total_deleted_xs + actual_sums = [] + for i, node in enumerate(nodes): + actual_sums.append(int(node.query("SELECT sum(x) FROM test_mutations").rstrip())) + assert actual_sums[i] == expected_sum From f5ecd410ae6fb205f4bdd0aaf06a6c5d1a68d93b Mon Sep 17 00:00:00 2001 From: Nikolai Kochetov Date: Fri, 29 Jun 2018 17:05:02 +0300 Subject: [PATCH 44/47] Renamed test. --- ...reference => 00650_array_enumerate_uniq_with_tuples.reference} | 0 ...with_tuples.sql => 00650_array_enumerate_uniq_with_tuples.sql} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename dbms/tests/queries/0_stateless/{00742_array_enumerate_uniq_with_tuples.reference => 00650_array_enumerate_uniq_with_tuples.reference} (100%) rename dbms/tests/queries/0_stateless/{00742_array_enumerate_uniq_with_tuples.sql => 00650_array_enumerate_uniq_with_tuples.sql} (100%) diff --git a/dbms/tests/queries/0_stateless/00742_array_enumerate_uniq_with_tuples.reference b/dbms/tests/queries/0_stateless/00650_array_enumerate_uniq_with_tuples.reference similarity index 100% rename from dbms/tests/queries/0_stateless/00742_array_enumerate_uniq_with_tuples.reference rename to dbms/tests/queries/0_stateless/00650_array_enumerate_uniq_with_tuples.reference diff --git a/dbms/tests/queries/0_stateless/00742_array_enumerate_uniq_with_tuples.sql b/dbms/tests/queries/0_stateless/00650_array_enumerate_uniq_with_tuples.sql similarity index 100% rename from dbms/tests/queries/0_stateless/00742_array_enumerate_uniq_with_tuples.sql rename to dbms/tests/queries/0_stateless/00650_array_enumerate_uniq_with_tuples.sql From 33205bba92e24985cb9fa88597f80458ec3244cd Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Fri, 29 Jun 2018 21:06:07 +0300 Subject: [PATCH 45/47] Disabled "LOAD DATA LOCAL INFILE" in mysql client because it has security issues [#CLOUDSECURITY-58] --- libs/libmysqlxx/src/Connection.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libs/libmysqlxx/src/Connection.cpp b/libs/libmysqlxx/src/Connection.cpp index fa848889316..00eeed49616 100644 --- a/libs/libmysqlxx/src/Connection.cpp +++ b/libs/libmysqlxx/src/Connection.cpp @@ -85,17 +85,18 @@ void Connection::connect(const char* db, throw ConnectionFailed(errorMessage(driver.get()), mysql_errno(driver.get())); /// Set timeouts. - if (mysql_options(driver.get(), MYSQL_OPT_CONNECT_TIMEOUT, reinterpret_cast(&timeout))) + if (mysql_options(driver.get(), MYSQL_OPT_CONNECT_TIMEOUT, &timeout)) throw ConnectionFailed(errorMessage(driver.get()), mysql_errno(driver.get())); - if (mysql_options(driver.get(), MYSQL_OPT_READ_TIMEOUT, reinterpret_cast(&rw_timeout))) + if (mysql_options(driver.get(), MYSQL_OPT_READ_TIMEOUT, &rw_timeout)) throw ConnectionFailed(errorMessage(driver.get()), mysql_errno(driver.get())); - if (mysql_options(driver.get(), MYSQL_OPT_WRITE_TIMEOUT, reinterpret_cast(&rw_timeout))) + if (mysql_options(driver.get(), MYSQL_OPT_WRITE_TIMEOUT, &rw_timeout)) throw ConnectionFailed(errorMessage(driver.get()), mysql_errno(driver.get())); - /// Enables ability to use query LOAD DATA LOCAL INFILE with servers were compiled without --enable-local-infile option. - if (mysql_options(driver.get(), MYSQL_OPT_LOCAL_INFILE, nullptr)) + /// Disable LOAD DATA LOCAL INFILE because it is insecure. + unsigned enable_local_infile = 0; + if (mysql_options(driver.get(), MYSQL_OPT_LOCAL_INFILE, &enable_local_infile)) throw ConnectionFailed(errorMessage(driver.get()), mysql_errno(driver.get())); /// Specifies particular ssl key and certificate if it needs From 394b0208697bd07c929681cd2110ae908bb40cae Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Sat, 30 Jun 2018 02:27:56 +0300 Subject: [PATCH 46/47] Fixed potential issue in Obfuscator on illegal UTF-8 source #2518 --- dbms/programs/obfuscator/Obfuscator.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dbms/programs/obfuscator/Obfuscator.cpp b/dbms/programs/obfuscator/Obfuscator.cpp index a634a41f468..09bcd04d6f8 100644 --- a/dbms/programs/obfuscator/Obfuscator.cpp +++ b/dbms/programs/obfuscator/Obfuscator.cpp @@ -503,8 +503,11 @@ private: CodePoint readCodePoint(const char *& pos, const char * end) { size_t length = UTF8::seqLength(*pos); + if (pos + length > end) length = end - pos; + if (length > sizeof(CodePoint)) + length = sizeof(CodePoint); CodePoint res = 0; memcpy(&res, pos, length); From 9845814701a646164504798fb8bbd9dd60bd324c Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Sat, 30 Jun 2018 22:03:26 +0300 Subject: [PATCH 47/47] Obfuscator: added heuristic #2518 --- dbms/programs/obfuscator/Obfuscator.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/dbms/programs/obfuscator/Obfuscator.cpp b/dbms/programs/obfuscator/Obfuscator.cpp index 09bcd04d6f8..854771b3b26 100644 --- a/dbms/programs/obfuscator/Obfuscator.cpp +++ b/dbms/programs/obfuscator/Obfuscator.cpp @@ -87,6 +87,7 @@ namespace DB namespace ErrorCodes { extern const int LOGICAL_ERROR; + extern const int NOT_IMPLEMENTED; extern const int CANNOT_SEEK_THROUGH_FILE; } @@ -682,7 +683,7 @@ public: } if (table.end() == it) - throw Exception("Logical error in markov model"); + throw Exception("Logical error in markov model", ErrorCodes::LOGICAL_ERROR); size_t offset_from_begin_of_string = pos - data; size_t determinator_sliding_window_size = params.determinator_sliding_window_size; @@ -703,7 +704,8 @@ public: /// If string is greater than desired_size, increase probability of end. double end_probability_multiplier = 0; Int64 num_bytes_after_desired_size = (pos - data) - desired_size; - if (num_bytes_after_desired_size) + + if (num_bytes_after_desired_size > 0) end_probability_multiplier = std::pow(1.25, num_bytes_after_desired_size); CodePoint code = it->second.sample(determinator, end_probability_multiplier); @@ -711,6 +713,14 @@ public: if (code == END) break; + if (num_bytes_after_desired_size > 0) + { + /// Heuristic: break at ASCII non-alnum code point. + /// This allows to be close to desired_size but not break natural looking words. + if (code < 128 && !isAlphaNumericASCII(code)) + break; + } + if (!writeCodePoint(code, pos, end)) break; @@ -884,7 +894,7 @@ public: if (auto type = typeid_cast(&data_type)) return std::make_unique(get(*type->getNestedType(), seed, markov_model_params)); - throw Exception("Unsupported data type"); + throw Exception("Unsupported data type", ErrorCodes::NOT_IMPLEMENTED); } };