mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-24 16:42:05 +00:00
Merge branch 'master' into fix-infinite-loop-in-test
This commit is contained in:
commit
c57210736b
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -148,9 +148,6 @@
|
||||
path = contrib/avro
|
||||
url = https://github.com/ClickHouse-Extras/avro.git
|
||||
ignore = untracked
|
||||
[submodule "website/images/feathericons"]
|
||||
path = website/images/feathericons
|
||||
url = https://github.com/feathericons/feather
|
||||
[submodule "contrib/msgpack-c"]
|
||||
path = contrib/msgpack-c
|
||||
url = https://github.com/msgpack/msgpack-c
|
||||
|
@ -786,4 +786,4 @@
|
||||
#### Security Fix
|
||||
* Fixed the possibility of reading directories structure in tables with `File` table engine. This fixes [#8536](https://github.com/ClickHouse/ClickHouse/issues/8536). [#8537](https://github.com/ClickHouse/ClickHouse/pull/8537) ([alexey-milovidov](https://github.com/alexey-milovidov))
|
||||
|
||||
## [Changelog for 2019](https://github.com/ClickHouse/ClickHouse/blob/master/docs/en/whats_new/changelog/2019.md)
|
||||
## [Changelog for 2019](https://github.com/ClickHouse/ClickHouse/blob/master/docs/en/whats-new/changelog/2019.md)
|
||||
|
@ -211,7 +211,8 @@ if (COMPILER_CLANG)
|
||||
endif()
|
||||
|
||||
# Display absolute paths in error messages. Otherwise KDevelop fails to navigate to correct file and opens a new file instead.
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -fdiagnostics-absolute-paths")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-absolute-paths")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdiagnostics-absolute-paths")
|
||||
|
||||
option(ENABLE_THINLTO "Enable Thin LTO. Only applicable for clang. It's also suppressed when building with tests or sanitizers." ON)
|
||||
|
||||
|
@ -37,7 +37,12 @@ using YearWeek = std::pair<UInt16, UInt8>;
|
||||
class DateLUTImpl
|
||||
{
|
||||
public:
|
||||
DateLUTImpl(const std::string & time_zone);
|
||||
explicit DateLUTImpl(const std::string & time_zone);
|
||||
|
||||
DateLUTImpl(const DateLUTImpl &) = delete;
|
||||
DateLUTImpl & operator=(const DateLUTImpl &) = delete;
|
||||
DateLUTImpl(const DateLUTImpl &&) = delete;
|
||||
DateLUTImpl & operator=(const DateLUTImpl &&) = delete;
|
||||
|
||||
public:
|
||||
/// The order of fields matters for alignment and sizeof.
|
||||
|
@ -1,18 +1,6 @@
|
||||
#include <common/demangle.h>
|
||||
|
||||
#if defined(__has_feature)
|
||||
#if __has_feature(memory_sanitizer)
|
||||
#define MEMORY_SANITIZER 1
|
||||
#else
|
||||
#define MEMORY_SANITIZER 0
|
||||
#endif
|
||||
#elif defined(__MEMORY_SANITIZER__)
|
||||
#define MEMORY_SANITIZER 1
|
||||
#else
|
||||
#define MEMORY_SANITIZER 0
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) || MEMORY_SANITIZER
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
DemangleResult tryDemangle(const char *)
|
||||
{
|
||||
|
@ -36,8 +36,10 @@ if (SANITIZE)
|
||||
endif ()
|
||||
|
||||
elseif (SANITIZE STREQUAL "thread")
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SAN_FLAGS} -fsanitize=thread")
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SAN_FLAGS} -fsanitize=thread")
|
||||
set (TSAN_FLAGS "-fsanitize=thread -fsanitize-blacklist=${CMAKE_SOURCE_DIR}/tests/tsan_suppressions.txt")
|
||||
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SAN_FLAGS} ${TSAN_FLAGS}")
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SAN_FLAGS} ${TSAN_FLAGS}")
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=thread")
|
||||
endif()
|
||||
|
@ -1,9 +1,9 @@
|
||||
cmake_minimum_required(VERSION 3.5.1)
|
||||
|
||||
|
||||
set(GRPC_SOURCE_DIR ${ClickHouse_SOURCE_DIR}/contrib/grpc)
|
||||
set(GRPC_INCLUDE_DIR ${GRPC_SOURCE_DIR}/include/)
|
||||
set(GRPC_BINARY_DIR ${ClickHouse_BINARY_DIR}/contrib/grpc)
|
||||
|
||||
if(UNIX)
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
set(_gRPC_PLATFORM_LINUX ON)
|
||||
@ -56,29 +56,19 @@ endif()
|
||||
|
||||
# protobuf.cmake
|
||||
set(PROTOBUF_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../protobuf)
|
||||
# if(NOT protobuf_BUILD_TESTS)
|
||||
# set(protobuf_BUILD_TESTS OFF CACHE BOOL "Build protobuf tests")
|
||||
# endif()
|
||||
|
||||
set(protobuf_BUILD_TESTS OFF CACHE BOOL "Build protobuf tests")
|
||||
if(NOT protobuf_WITH_ZLIB)
|
||||
set(protobuf_WITH_ZLIB OFF CACHE BOOL "Build protobuf with zlib.")
|
||||
endif()
|
||||
set(protobuf_MSVC_STATIC_RUNTIME OFF CACHE BOOL "Link static runtime libraries")
|
||||
if(NOT USE_INTERNAL_PROTOBUF_LIBRARY)
|
||||
add_subdirectory(${PROTOBUF_ROOT_DIR}/cmake ${GRPC_BINARY_DIR}/third_party/protobuf)
|
||||
endif()
|
||||
if(TARGET ${_gRPC_PROTOBUF_LIBRARY_NAME})
|
||||
set(_gRPC_PROTOBUF_LIBRARIES ${_gRPC_PROTOBUF_LIBRARY_NAME})
|
||||
endif()
|
||||
if(TARGET libprotoc)
|
||||
set(_gRPC_PROTOBUF_PROTOC_LIBRARIES libprotoc)
|
||||
endif()
|
||||
if(TARGET protoc)
|
||||
set(_gRPC_PROTOBUF_PROTOC protoc)
|
||||
set(_gRPC_PROTOBUF_PROTOC_EXECUTABLE $<TARGET_FILE:protoc>)
|
||||
endif()
|
||||
# For well-known .proto files distributed with protobuf
|
||||
set(_gRPC_PROTOBUF_WELLKNOWN_INCLUDE_DIR "${PROTOBUF_ROOT_DIR}/src")
|
||||
|
||||
set(_gRPC_PROTOBUF_LIBRARIES libprotobuf)
|
||||
set(_gRPC_PROTOBUF_PROTOC_LIBRARIES libprotoc)
|
||||
set(_gRPC_PROTOBUF_PROTOC protoc)
|
||||
set(_gRPC_PROTOBUF_PROTOC_EXECUTABLE $<TARGET_FILE:protoc>)
|
||||
set(_gRPC_PROTOBUF_INCLUDE_DIR "${PROTOBUF_ROOT_DIR}/src")
|
||||
|
||||
if(gRPC_INSTALL)
|
||||
message(WARNING "gRPC_INSTALL will be forced to FALSE because gRPC_PROTOBUF_PROVIDER is \"module\"")
|
||||
set(gRPC_INSTALL FALSE)
|
||||
@ -98,12 +88,13 @@ set(_gRPC_UPB_GRPC_GENERATED_DIR "${GRPC_SOURCE_DIR}/src/core/ext/upb-generated"
|
||||
set(_gRPC_UPB_LIBRARIES upb)
|
||||
|
||||
# zlib.cmake
|
||||
set(ZLIB_ROOT_DIR ${GRPC_SOURCE_DIR}/third_party/zlib-ng)
|
||||
set(ZLIB_ROOT_DIR ${GRPC_SOURCE_DIR}/../zlib-ng)
|
||||
include_directories("${ZLIB_ROOT_DIR}")
|
||||
# add_subdirectory(${ZLIB_ROOT_DIR} ${ZLIB_ROOT_DIR})
|
||||
set(_gRPC_ZLIB_LIBRARIES zlibstatic)
|
||||
set(_gRPC_ZLIB_INCLUDE_DIR "${ZLIB_ROOT_DIR}")
|
||||
|
||||
## add_subdirectory(${ZLIB_ROOT_DIR} ${ZLIB_ROOT_DIR})
|
||||
if(TARGET zlibstatic)
|
||||
set(_gRPC_ZLIB_LIBRARIES zlibstatic)
|
||||
set(_gRPC_ZLIB_INCLUDE_DIR "${ZLIB_ROOT_DIR}" "${GRPC_SOURCE_DIR}/third_party/zlib")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
@ -134,6 +125,7 @@ target_include_directories(address_sorting
|
||||
)
|
||||
target_link_libraries(address_sorting
|
||||
${_gRPC_BASELIB_LIBRARIES}
|
||||
${_gRPC_PROTOBUF_LIBRARIES}
|
||||
${_gRPC_ALLTARGETS_LIBRARIES}
|
||||
)
|
||||
|
||||
@ -194,6 +186,7 @@ target_include_directories(gpr
|
||||
)
|
||||
target_link_libraries(gpr
|
||||
${_gRPC_ALLTARGETS_LIBRARIES}
|
||||
${_gRPC_PROTOBUF_LIBRARIES}
|
||||
)
|
||||
|
||||
add_library(grpc
|
||||
@ -597,6 +590,7 @@ target_link_libraries(grpc
|
||||
${_gRPC_CARES_LIBRARIES}
|
||||
${_gRPC_ADDRESS_SORTING_LIBRARIES}
|
||||
${_gRPC_ALLTARGETS_LIBRARIES}
|
||||
${_gRPC_PROTOBUF_LIBRARIES}
|
||||
gpr
|
||||
)
|
||||
if (_gRPC_PLATFORM_MAC)
|
||||
@ -943,6 +937,7 @@ target_link_libraries(grpc_cronet
|
||||
${_gRPC_CARES_LIBRARIES}
|
||||
${_gRPC_ADDRESS_SORTING_LIBRARIES}
|
||||
${_gRPC_ALLTARGETS_LIBRARIES}
|
||||
${_gRPC_PROTOBUF_LIBRARIES}
|
||||
gpr
|
||||
)
|
||||
if (_gRPC_PLATFORM_MAC)
|
||||
@ -1273,6 +1268,7 @@ target_link_libraries(grpc_unsecure
|
||||
${_gRPC_CARES_LIBRARIES}
|
||||
${_gRPC_ADDRESS_SORTING_LIBRARIES}
|
||||
${_gRPC_ALLTARGETS_LIBRARIES}
|
||||
${_gRPC_PROTOBUF_LIBRARIES}
|
||||
gpr
|
||||
)
|
||||
if (_gRPC_PLATFORM_MAC)
|
||||
|
2
contrib/libcpuid
vendored
2
contrib/libcpuid
vendored
@ -1 +1 @@
|
||||
Subproject commit f670a1fa508427b6e94f1c801cb12545a97b3cc1
|
||||
Subproject commit 8db3b8d2d32d22437f063ce692a1b9bb15e42d18
|
2
contrib/poco
vendored
2
contrib/poco
vendored
@ -1 +1 @@
|
||||
Subproject commit 9b347d4ab71e4436d8215aace978024e93462731
|
||||
Subproject commit be2ab90ba5dccd46919a116e3fe4fa77bb85063b
|
@ -29,7 +29,7 @@ pull requests (0 for master) manually.
|
||||
|
||||
```
|
||||
docker run --network=host --volume=$(pwd)/workspace:/workspace --volume=$(pwd)/output:/output
|
||||
[-e REF_PR={} -e REF_SHA={} -e ]
|
||||
[-e REF_PR={} -e REF_SHA={}]
|
||||
-e PR_TO_TEST={} -e SHA_TO_TEST={}
|
||||
yandex/clickhouse-performance-comparison
|
||||
```
|
||||
@ -40,6 +40,7 @@ There are some environment variables that influence what the test does:
|
||||
* `-e CHCP_RUNS` -- the number of runs;
|
||||
* `-e CHPC_TEST_GREP` -- the names of the tests (xml files) to run, interpreted
|
||||
as a grep pattern.
|
||||
* `-e CHPC_LOCAL_SCRIPT` -- use the comparison scripts from the docker container and not from the tested commit.
|
||||
|
||||
#### Re-genarate report with your tweaks
|
||||
From the workspace directory (extracted test output archive):
|
||||
|
@ -6,11 +6,14 @@ install_and_run_server() {
|
||||
mkdir /unpacked
|
||||
tar -xzf /package_folder/shared_build.tgz -C /unpacked --strip 1
|
||||
LD_LIBRARY_PATH=/unpacked /unpacked/clickhouse-server --config /unpacked/config/config.xml >/var/log/clickhouse-server/stderr.log 2>&1 &
|
||||
sleep 5
|
||||
}
|
||||
|
||||
run_client() {
|
||||
LD_LIBRARY_PATH=/unpacked /unpacked/clickhouse-client --query "select 'OK'" 2>/var/log/clickhouse-server/clientstderr.log || echo "FAIL"
|
||||
for i in {1..100}; do
|
||||
sleep 1
|
||||
LD_LIBRARY_PATH=/unpacked /unpacked/clickhouse-client --query "select 'OK'" 2>/var/log/clickhouse-server/clientstderr.log && break
|
||||
[[ $i == 100 ]] && echo 'FAIL'
|
||||
done
|
||||
}
|
||||
|
||||
install_and_run_server
|
||||
|
@ -10,7 +10,7 @@ toc_title: Support
|
||||
|
||||
## Altinity {#altinity}
|
||||
|
||||
[Service description](https://www.altinity.com/24x7-support)
|
||||
Altinity has offered enterprise ClickHouse support and services since 2017. Altinity customers range from Fortune 100 enterprises to startups. Visit [www.altinity.com](https://www.altinity.com/) for more information.
|
||||
|
||||
## Mafiree {#mafiree}
|
||||
|
||||
|
@ -516,10 +516,10 @@ And the result will be:
|
||||
|
||||
## timeSeriesGroupRateSum(uid, ts, val) {#agg-function-timeseriesgroupratesum}
|
||||
|
||||
Similarly timeSeriesGroupRateSum, timeSeriesGroupRateSum will Calculate the rate of time-series and then sum rates together.
|
||||
Similarly to `timeSeriesGroupSum`, `timeSeriesGroupRateSum` calculates the rate of time-series and then sum rates together.
|
||||
Also, timestamp should be in ascend order before use this function.
|
||||
|
||||
Use this function, the result above case will be:
|
||||
Applying this function to the data from the `timeSeriesGroupSum` example, you get the following result:
|
||||
|
||||
``` text
|
||||
[(2,0),(3,0.1),(7,0.3),(8,0.3),(12,0.3),(17,0.3),(18,0.3),(24,0.3),(25,0.1)]
|
||||
|
@ -23,6 +23,41 @@ Uses a linear congruential generator.
|
||||
|
||||
## randConstant {#randconstant}
|
||||
|
||||
Returns a pseudo-random UInt32 number, The value is one for different blocks.
|
||||
Produces a constant column with a random value.
|
||||
|
||||
**Syntax**
|
||||
|
||||
``` sql
|
||||
randConstant([x])
|
||||
```
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `x` — [Expression](../syntax.md#syntax-expressions) resulting in any of the [supported data types](../data-types/index.md#data_types). The resulting value is discarded, but the expression itself if used for bypassing [common subexpression elimination](index.md#common-subexpression-elimination) if the function is called multiple times in one query. Optional parameter.
|
||||
|
||||
**Returned value**
|
||||
|
||||
- Pseudo-random number.
|
||||
|
||||
Type: [UInt32](../data-types/int-uint.md).
|
||||
|
||||
**Example**
|
||||
|
||||
Query:
|
||||
|
||||
``` sql
|
||||
SELECT rand(), rand(1), rand(number), randConstant(), randConstant(1), randConstant(number)
|
||||
FROM numbers(3)
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
``` text
|
||||
┌─────rand()─┬────rand(1)─┬─rand(number)─┬─randConstant()─┬─randConstant(1)─┬─randConstant(number)─┐
|
||||
│ 3047369878 │ 4132449925 │ 4044508545 │ 2740811946 │ 4229401477 │ 1924032898 │
|
||||
│ 2938880146 │ 1267722397 │ 4154983056 │ 2740811946 │ 4229401477 │ 1924032898 │
|
||||
│ 956619638 │ 4238287282 │ 1104342490 │ 2740811946 │ 4229401477 │ 1924032898 │
|
||||
└────────────┴────────────┴──────────────┴────────────────┴─────────────────┴──────────────────────┘
|
||||
```
|
||||
|
||||
[Original article](https://clickhouse.tech/docs/en/query_language/functions/random_functions/) <!--hide-->
|
||||
|
@ -3,9 +3,9 @@ toc_priority: 77
|
||||
toc_title: '2019'
|
||||
---
|
||||
|
||||
## ClickHouse Release V19.17 {#clickhouse-release-v19-17}
|
||||
## ClickHouse Release 19.17 {#clickhouse-release-v19-17}
|
||||
|
||||
### ClickHouse Release V19.17.6.36, 2019-12-27 {#clickhouse-release-v19-17-6-36-2019-12-27}
|
||||
### ClickHouse Release 19.17.6.36, 2019-12-27 {#clickhouse-release-v19-17-6-36-2019-12-27}
|
||||
|
||||
#### Bug Fix {#bug-fix}
|
||||
|
||||
@ -40,7 +40,7 @@ toc_title: '2019'
|
||||
- Now an exception will be thrown in case of using WITH TIES alongside LIMIT BY. And now it’s possible to use TOP with LIMIT BY. [\#7637](https://github.com/ClickHouse/ClickHouse/pull/7637) ([Nikita Mikhaylov](https://github.com/nikitamikhaylov))
|
||||
- Fix dictionary reload if it has `invalidate_query`, which stopped updates and some exception on previous update tries. [\#8029](https://github.com/ClickHouse/ClickHouse/pull/8029) ([alesapin](https://github.com/alesapin))
|
||||
|
||||
### ClickHouse Release V19.17.4.11, 2019-11-22 {#clickhouse-release-v19-17-4-11-2019-11-22}
|
||||
### ClickHouse Release 19.17.4.11, 2019-11-22 {#clickhouse-release-v19-17-4-11-2019-11-22}
|
||||
|
||||
#### Backward Incompatible Change {#backward-incompatible-change}
|
||||
|
||||
@ -126,13 +126,13 @@ toc_title: '2019'
|
||||
|
||||
- Added ANTLR4 grammar for ClickHouse SQL dialect [\#7595](https://github.com/ClickHouse/ClickHouse/issues/7595) [\#7596](https://github.com/ClickHouse/ClickHouse/pull/7596) ([alexey-milovidov](https://github.com/alexey-milovidov))
|
||||
|
||||
## ClickHouse Release V19.16 {#clickhouse-release-v19-16}
|
||||
## ClickHouse Release 19.16 {#clickhouse-release-v19-16}
|
||||
|
||||
#### ClickHouse Release V19.16.14.65, 2020-03-25 {#clickhouse-release-v19-16-14-65-2020-03-25}
|
||||
#### ClickHouse Release 19.16.14.65, 2020-03-25 {#clickhouse-release-v19-16-14-65-2020-03-25}
|
||||
|
||||
- Fixed up a bug in batched calculations of ternary logical OPs on multiple arguments (more than 10). [\#8718](https://github.com/ClickHouse/ClickHouse/pull/8718) ([Alexander Kazakov](https://github.com/Akazz)) This bugfix was backported to version 19.16 by a special request from Altinity.
|
||||
|
||||
#### ClickHouse Release V19.16.14.65, 2020-03-05 {#clickhouse-release-v19-16-14-65-2020-03-05}
|
||||
#### ClickHouse Release 19.16.14.65, 2020-03-05 {#clickhouse-release-v19-16-14-65-2020-03-05}
|
||||
|
||||
- Fix distributed subqueries incompatibility with older CH versions. Fixes [\#7851](https://github.com/ClickHouse/ClickHouse/issues/7851)
|
||||
[(tabplubix)](https://github.com/tavplubix)
|
||||
@ -152,7 +152,7 @@ toc_title: '2019'
|
||||
- Add `deduplicate_blocks_in_dependent_materialized_views` option to control the behaviour of idempotent inserts into tables with materialized views. This new feature was added to the bugfix release by a special request from Altinity.
|
||||
[\#9070](https://github.com/ClickHouse/ClickHouse/pull/9070) [(urykhy)](https://github.com/urykhy)
|
||||
|
||||
### ClickHouse Release V19.16.2.2, 2019-10-30 {#clickhouse-release-v19-16-2-2-2019-10-30}
|
||||
### ClickHouse Release 19.16.2.2, 2019-10-30 {#clickhouse-release-v19-16-2-2-2019-10-30}
|
||||
|
||||
#### Backward Incompatible Change {#backward-incompatible-change-1}
|
||||
|
||||
|
@ -6,21 +6,13 @@
|
||||
|
||||
Основные возможности:
|
||||
|
||||
- Хранит данные, отсортированные по первичному ключу.
|
||||
- **Хранит данные, отсортированные по первичному ключу.** Это позволяет создавать разреженный индекс небольшого объёма, который позволяет быстрее находить данные.
|
||||
|
||||
Это позволяет создавать разреженный индекс небольшого объёма, который позволяет быстрее находить данные.
|
||||
- **Позволяет оперировать партициями, если задан [ключ партиционирования](custom-partitioning-key.md).** ClickHouse поддерживает отдельные операции с партициями, которые работают эффективнее, чем общие операции с этим же результатом над этими же данными. Также, ClickHouse автоматически отсекает данные по партициям там, где ключ партиционирования указан в запросе. Это также увеличивает эффективность выполнения запросов.
|
||||
|
||||
- Позволяет оперировать партициями, если задан [ключ партиционирования](custom-partitioning-key.md).
|
||||
- **Поддерживает репликацию данных.** Для этого используется семейство таблиц `ReplicatedMergeTree`. Подробнее читайте в разделе [Репликация данных](replication.md).
|
||||
|
||||
ClickHouse поддерживает отдельные операции с партициями, которые работают эффективнее, чем общие операции с этим же результатом над этими же данными. Также, ClickHouse автоматически отсекает данные по партициям там, где ключ партиционирования указан в запросе. Это также увеличивает эффективность выполнения запросов.
|
||||
|
||||
- Поддерживает репликацию данных.
|
||||
|
||||
Для этого используется семейство таблиц `ReplicatedMergeTree`. Подробнее читайте в разделе [Репликация данных](replication.md).
|
||||
|
||||
- Поддерживает сэмплирование данных.
|
||||
|
||||
При необходимости можно задать способ сэмплирования данных в таблице.
|
||||
- **Поддерживает сэмплирование данных.** При необходимости можно задать способ сэмплирования данных в таблице.
|
||||
|
||||
!!! info "Info"
|
||||
Движок [Merge](../special/merge.md#merge) не относится к семейству `*MergeTree`.
|
||||
@ -53,44 +45,30 @@ CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
|
||||
|
||||
- `ENGINE` — имя и параметры движка. `ENGINE = MergeTree()`. `MergeTree` не имеет параметров.
|
||||
|
||||
- `PARTITION BY` — [ключ партиционирования](custom-partitioning-key.md).
|
||||
- `PARTITION BY` — [ключ партиционирования](custom-partitioning-key.md). Для партиционирования по месяцам используйте выражение `toYYYYMM(date_column)`, где `date_column` — столбец с датой типа [Date](../../../engines/table-engines/mergetree-family/mergetree.md). В этом случае имена партиций имеют формат `"YYYYMM"`.
|
||||
|
||||
Для партиционирования по месяцам используйте выражение `toYYYYMM(date_column)`, где `date_column` — столбец с датой типа [Date](../../../engines/table_engines/mergetree_family/mergetree.md). В этом случае имена партиций имеют формат `"YYYYMM"`.
|
||||
- `ORDER BY` — ключ сортировки. Кортеж столбцов или произвольных выражений. Пример: `ORDER BY (CounterID, EventDate)`.
|
||||
|
||||
- `ORDER BY` — ключ сортировки.
|
||||
- `PRIMARY KEY` — первичный ключ, если он [отличается от ключа сортировки](#pervichnyi-kliuch-otlichnyi-ot-kliucha-sortirovki). По умолчанию первичный ключ совпадает с ключом сортировки (который задаётся секцией `ORDER BY`.) Поэтому в большинстве случаев секцию `PRIMARY KEY` отдельно указывать не нужно.
|
||||
|
||||
Кортеж столбцов или произвольных выражений. Пример: `ORDER BY (CounterID, EventDate)`.
|
||||
- `SAMPLE BY` — выражение для сэмплирования. Если используется выражение для сэмплирования, то первичный ключ должен содержать его. Пример: `SAMPLE BY intHash32(UserID) ORDER BY (CounterID, EventDate, intHash32(UserID))`.
|
||||
|
||||
- `PRIMARY KEY` — первичный ключ, если он [отличается от ключа сортировки](#pervichnyi-kliuch-otlichnyi-ot-kliucha-sortirovki).
|
||||
|
||||
По умолчанию первичный ключ совпадает с ключом сортировки (который задаётся секцией `ORDER BY`.) Поэтому в большинстве случаев секцию `PRIMARY KEY` отдельно указывать не нужно.
|
||||
|
||||
- `SAMPLE BY` — выражение для сэмплирования.
|
||||
|
||||
Если используется выражение для сэмплирования, то первичный ключ должен содержать его. Пример:
|
||||
|
||||
`SAMPLE BY intHash32(UserID) ORDER BY (CounterID, EventDate, intHash32(UserID))`.
|
||||
|
||||
- `TTL` — список правил, определяющих длительности хранения строк, а также задающих правила перемещения частей на определённые тома или диски.
|
||||
|
||||
Выражение должно возвращать столбец `Date` или `DateTime`. Пример: `TTL date + INTERVAL 1 DAY`.
|
||||
|
||||
Тип правила `DELETE|TO DISK 'xxx'|TO VOLUME 'xxx'` указывает действие, которое будет выполнено с частью, удаление строк (прореживание), перемещение (при выполнении условия для всех строк части) на определённый диск (`TO DISK 'xxx'`) или том (`TO VOLUME 'xxx'`). Поведение по умолчанию соответствует удалению строк (`DELETE`). В списке правил может быть указано только одно выражение с поведением `DELETE`.
|
||||
|
||||
Дополнительные сведения смотрите в разделе [TTL для столбцов и таблиц](#table_engine-mergetree-ttl)
|
||||
- `TTL` — список правил, определяющих длительности хранения строк, а также задающих правила перемещения частей на определённые тома или диски. Выражение должно возвращать столбец `Date` или `DateTime`. Пример: `TTL date + INTERVAL 1 DAY`.
|
||||
- Тип правила `DELETE|TO DISK 'xxx'|TO VOLUME 'xxx'` указывает действие, которое будет выполнено с частью, удаление строк (прореживание), перемещение (при выполнении условия для всех строк части) на определённый диск (`TO DISK 'xxx'`) или том (`TO VOLUME 'xxx'`).
|
||||
- Поведение по умолчанию соответствует удалению строк (`DELETE`). В списке правил может быть указано только одно выражение с поведением `DELETE`.
|
||||
- Дополнительные сведения смотрите в разделе [TTL для столбцов и таблиц](#table_engine-mergetree-ttl)
|
||||
|
||||
- `SETTINGS` — дополнительные параметры, регулирующие поведение `MergeTree`:
|
||||
|
||||
- `index_granularity` — максимальное количество строк данных между засечками индекса. По умолчанию — 8192. Смотрите [Хранение данных](#mergetree-data-storage).
|
||||
- `index_granularity_bytes` — максимальный размер гранул данных в байтах. По умолчанию — 10Mb. Чтобы ограничить размер гранул только количеством строк, установите значение 0 (не рекомендовано). Смотрите [Хранение данных](#mergetree-data-storage).
|
||||
- `enable_mixed_granularity_parts` — включает или выключает переход к ограничению размера гранул с помощью настройки `index_granularity_bytes`. До версии 19.11, размер гранул ограничивался только настройкой `index_granularity`. Настройка `index_granularity_bytes` улучшает производительность ClickHouse при выборке данных из таблиц с большими (десятки и сотни мегабайтов) строками. Если у вас есть таблицы с большими строками, можно включить эту настройку, чтобы повысить эффективность запросов `SELECT`.
|
||||
- `use_minimalistic_part_header_in_zookeeper` — Способ хранения заголовков кусков данных в ZooKeeper. Если `use_minimalistic_part_header_in_zookeeper = 1`, то ZooKeeper хранит меньше данных. Подробнее читайте в [описании настройки](../../../operations/server_configuration_parameters/settings.md#server-settings-use_minimalistic_part_header_in_zookeeper) в разделе "Конфигурационные параметры сервера".
|
||||
- `min_merge_bytes_to_use_direct_io` — минимальный объём данных при слиянии, необходимый для прямого (небуферизованного) чтения/записи (direct I/O) на диск. При слиянии частей данных ClickHouse вычисляет общий объём хранения всех данных, подлежащих слиянию. Если общий объём хранения всех данных для чтения превышает `min_bytes_to_use_direct_io` байт, тогда ClickHouse использует флаг `O_DIRECT` при чтении данных с диска. Если `min_merge_bytes_to_use_direct_io = 0`, тогда прямой ввод-вывод отключен. Значение по умолчанию: `10 * 1024 * 1024 * 1024` байтов.
|
||||
<a name="mergetree_setting-merge_with_ttl_timeout"></a>
|
||||
- `merge_with_ttl_timeout` — минимальное время в секундах перед повторным слиянием с TTL. По умолчанию — 86400 (1 день).
|
||||
- `write_final_mark` — включает или отключает запись последней засечки индекса в конце куска данных, указывающей за последний байт. По умолчанию — 1. Не отключайте её.
|
||||
- `merge_max_block_size` — Максимальное количество строк в блоке для операций слияния. Значение по умолчанию: 8192.
|
||||
- `storage_policy` — политика хранения данных. Смотрите [Хранение данных таблицы на нескольких блочных устройствах](#table_engine-mergetree-multiple-volumes).
|
||||
- `index_granularity` — максимальное количество строк данных между засечками индекса. По умолчанию — 8192. Смотрите [Хранение данных](#mergetree-data-storage).
|
||||
- `index_granularity_bytes` — максимальный размер гранул данных в байтах. По умолчанию — 10Mb. Чтобы ограничить размер гранул только количеством строк, установите значение 0 (не рекомендовано). Смотрите [Хранение данных](#mergetree-data-storage).
|
||||
- `enable_mixed_granularity_parts` — включает или выключает переход к ограничению размера гранул с помощью настройки `index_granularity_bytes`. Настройка `index_granularity_bytes` улучшает производительность ClickHouse при выборке данных из таблиц с большими (десятки и сотни мегабайтов) строками. Если у вас есть таблицы с большими строками, можно включить эту настройку, чтобы повысить эффективность запросов `SELECT`.
|
||||
- `use_minimalistic_part_header_in_zookeeper` — Способ хранения заголовков кусков данных в ZooKeeper. Если `use_minimalistic_part_header_in_zookeeper = 1`, то ZooKeeper хранит меньше данных. Подробнее читайте в [описании настройки](../../../operations/server-configuration-parameters/settings.md#server-settings-use_minimalistic_part_header_in_zookeeper) в разделе "Конфигурационные параметры сервера".
|
||||
- `min_merge_bytes_to_use_direct_io` — минимальный объём данных при слиянии, необходимый для прямого (небуферизованного) чтения/записи (direct I/O) на диск. При слиянии частей данных ClickHouse вычисляет общий объём хранения всех данных, подлежащих слиянию. Если общий объём хранения всех данных для чтения превышает `min_bytes_to_use_direct_io` байт, тогда ClickHouse использует флаг `O_DIRECT` при чтении данных с диска. Если `min_merge_bytes_to_use_direct_io = 0`, тогда прямой ввод-вывод отключен. Значение по умолчанию: `10 * 1024 * 1024 * 1024` байтов.
|
||||
- <a name="mergetree_setting-merge_with_ttl_timeout"></a>`merge_with_ttl_timeout` — минимальное время в секундах перед повторным слиянием с TTL. По умолчанию — 86400 (1 день).
|
||||
- `write_final_mark` — включает или отключает запись последней засечки индекса в конце куска данных, указывающей за последний байт. По умолчанию — 1. Не отключайте её.
|
||||
- `merge_max_block_size` — Максимальное количество строк в блоке для операций слияния. Значение по умолчанию: 8192.
|
||||
- `storage_policy` — политика хранения данных. Смотрите [Хранение данных таблицы на нескольких блочных устройствах](#table_engine-mergetree-multiple-volumes).
|
||||
|
||||
**Пример задания секций**
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Настройки MergeTree таблиц {#merge-tree-settings}
|
||||
|
||||
Значения настроек merge-tree (для всех MergeTree таблиц) можно посмотреть в таблице `system.merge_tree_settings`, их можно переопределить в `config.xml` в секции `merge_tree`, или задать в секции `SETTINGS` у каждой таблицы.
|
||||
Значения настроек для всех MergeTree таблиц можно посмотреть в таблице `system.merge_tree_settings`, их можно переопределить в `config.xml` в секции `merge_tree`, или задать в секции `SETTINGS` у каждой таблицы.
|
||||
|
||||
Пример переопределения в `config.xml`:
|
||||
|
||||
@ -97,7 +97,7 @@ Eсли суммарное число активных кусков во все
|
||||
|
||||
Значение по умолчанию: 100.
|
||||
|
||||
Команда `Insert` создает один или несколько блоков (кусков). При вставке в Replicated таблицы ClickHouse для [дедупликации вставок](../../engines/table-engines/mergetree-family/replication/) записывает в Zookeeper хеш-суммы созданных кусков. Но хранятся хеш-суммы не всех кусков, а только последние `replicated_deduplication_window`. Наиболее старые хеш-суммы удаляются из Zookeeper.
|
||||
Команда `Insert` создает один или несколько блоков (кусков). При вставке в Replicated таблицы ClickHouse для [дедупликации вставок](../../engines/table-engines/mergetree-family/replication.md) записывает в Zookeeper хеш-суммы созданных кусков. Но хранятся хеш-суммы не всех кусков, а только последние `replicated_deduplication_window`. Наиболее старые хеш-суммы удаляются из Zookeeper.
|
||||
Большое число `replicated_deduplication_window` замедляет `Insert`-ы. Хеш-сумма рассчитывается от композиции имен и типов полей, а также данных вставленного куска (потока байт).
|
||||
|
||||
## replicated\_deduplication\_window\_seconds {#replicated-deduplication-window-seconds}
|
||||
@ -110,7 +110,7 @@ Eсли суммарное число активных кусков во все
|
||||
|
||||
Значение по умолчанию: 604800 (1 неделя).
|
||||
|
||||
Аналогично [replicated_deduplication_window](#replicated_deduplication_window), задает, сколько времени хранить хеш-суммы блоков для дедупликции `Insert`-в. Хеш-суммы старше `replicated_deduplication_window_seconds` удаляются из Zookeeper, даже если их меньше чем `replicated_deduplication_window`.
|
||||
Аналогично [replicated_deduplication_window](#replicated-deduplication-window), задает, сколько времени хранить хеш-суммы блоков для дедупликции `Insert`-в. Хеш-суммы старше `replicated_deduplication_window_seconds` удаляются из Zookeeper, даже если их меньше чем `replicated_deduplication_window`.
|
||||
|
||||
## old\_parts\_lifetime {#old-parts-lifetime}
|
||||
|
||||
@ -181,4 +181,4 @@ Eсли суммарное число активных кусков во все
|
||||
|
||||
При старте ClickHouse читает все куски всех таблиц (читает файлы с метаданными кусков), чтобы построить в ОЗУ список всех кусков. В некоторых системах с большим количеством кусков этот процесс может занимать длительное время, и это время можно сократить, увеличив `max_part_loading_threads` (если при этом процессе есть недозагруженность CPU и диска).
|
||||
|
||||
[Оригинальная статья](https://clickhouse.tech/docs/ru/operations/settings/merge_tree_settings/) <!--hide-->
|
||||
{## [Оригинальная статья](https://clickhouse.tech/docs/ru/operations/settings/merge-tree-settings/) ##}
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
В ClickHouse, в отличие от стандартного SQL, типизация является строгой. То есть, не производится неявных преобразований между типами. Все функции работают для определённого набора типов. Это значит, что иногда вам придётся использовать функции преобразования типов.
|
||||
|
||||
## Склейка одинаковых выражений {#skleika-odinakovykh-vyrazhenii}
|
||||
## Склейка одинаковых выражений {#common-subexpression-elimination}
|
||||
|
||||
Все выражения в запросе, имеющие одинаковые AST (одинаковую запись или одинаковый результат синтаксического разбора), считаются имеющими одинаковые значения. Такие выражения склеиваются и исполняются один раз. Одинаковые подзапросы тоже склеиваются.
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Функции генерации псевдослучайных чисел {#funktsii-generatsii-psevdosluchainykh-chisel}
|
||||
# Функции генерации псевдослучайных чисел {#functions-for-generating-pseudo-random-numbers}
|
||||
|
||||
Используются не криптографические генераторы псевдослучайных чисел.
|
||||
|
||||
@ -16,4 +16,43 @@
|
||||
Возвращает псевдослучайное число типа UInt64, равномерно распределённое среди всех чисел типа UInt64.
|
||||
Используется linear congruential generator.
|
||||
|
||||
## randConstant {#randconstant}
|
||||
|
||||
Создает константный столбец с псевдослучайным значением.
|
||||
|
||||
**Синтаксис**
|
||||
|
||||
``` sql
|
||||
randConstant([x])
|
||||
```
|
||||
|
||||
**Параметры**
|
||||
|
||||
- `x` — [Выражение](../syntax.md#syntax-expressions), возвращающее значение одного из [поддерживаемых типов данных](../data-types/index.md#data_types). Значение используется, чтобы избежать [склейки одинаковых выражений](index.md#common-subexpression-elimination), если функция вызывается несколько раз в одном запросе. Необязательный параметр.
|
||||
|
||||
**Возвращаемое значение**
|
||||
|
||||
- Псевдослучайное число.
|
||||
|
||||
Тип: [UInt32](../data-types/int-uint.md).
|
||||
|
||||
**Пример**
|
||||
|
||||
Запрос:
|
||||
|
||||
``` sql
|
||||
SELECT rand(), rand(1), rand(number), randConstant(), randConstant(1), randConstant(number)
|
||||
FROM numbers(3)
|
||||
```
|
||||
|
||||
Результат:
|
||||
|
||||
``` text
|
||||
┌─────rand()─┬────rand(1)─┬─rand(number)─┬─randConstant()─┬─randConstant(1)─┬─randConstant(number)─┐
|
||||
│ 3047369878 │ 4132449925 │ 4044508545 │ 2740811946 │ 4229401477 │ 1924032898 │
|
||||
│ 2938880146 │ 1267722397 │ 4154983056 │ 2740811946 │ 4229401477 │ 1924032898 │
|
||||
│ 956619638 │ 4238287282 │ 1104342490 │ 2740811946 │ 4229401477 │ 1924032898 │
|
||||
└────────────┴────────────┴──────────────┴────────────────┴─────────────────┴──────────────────────┘
|
||||
```
|
||||
|
||||
[Оригинальная статья](https://clickhouse.tech/docs/ru/query_language/functions/random_functions/) <!--hide-->
|
||||
|
@ -128,7 +128,7 @@ CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
|
||||
|
||||
### Выражение для TTL {#vyrazhenie-dlia-ttl}
|
||||
|
||||
Определяет время хранения значений. Может быть указано только для таблиц семейства MergeTree. Подробнее смотрите в [TTL для столбцов и таблиц](../../sql-reference/statements/create.md#table_engine-mergetree-ttl).
|
||||
Определяет время хранения значений. Может быть указано только для таблиц семейства MergeTree. Подробнее смотрите в [TTL для столбцов и таблиц](../../engines/table-engines/mergetree-family/mergetree.md#table_engine-mergetree-ttl).
|
||||
|
||||
### Кодеки сжатия столбцов {#codecs}
|
||||
|
||||
|
@ -241,6 +241,7 @@ if __name__ == '__main__':
|
||||
arg_parser.add_argument('--skip-amp', action='store_true')
|
||||
arg_parser.add_argument('--skip-pdf', action='store_true')
|
||||
arg_parser.add_argument('--skip-website', action='store_true')
|
||||
arg_parser.add_argument('--skip-git-log', action='store_true')
|
||||
arg_parser.add_argument('--test-only', action='store_true')
|
||||
arg_parser.add_argument('--minify', action='store_true')
|
||||
arg_parser.add_argument('--htmlproofer', action='store_true')
|
||||
@ -273,6 +274,9 @@ if __name__ == '__main__':
|
||||
args.skip_pdf = True
|
||||
args.skip_amp = True
|
||||
|
||||
if args.skip_git_log or args.skip_amp:
|
||||
mdx_clickhouse.PatchedMacrosPlugin.skip_git_log = True
|
||||
|
||||
from build import build
|
||||
build(args)
|
||||
|
||||
|
@ -86,6 +86,7 @@ def get_translations(dirname, lang):
|
||||
|
||||
class PatchedMacrosPlugin(macros.plugin.MacrosPlugin):
|
||||
disabled = False
|
||||
skip_git_log = False
|
||||
|
||||
def on_config(self, config):
|
||||
super(PatchedMacrosPlugin, self).on_config(config)
|
||||
@ -120,6 +121,8 @@ class PatchedMacrosPlugin(macros.plugin.MacrosPlugin):
|
||||
markdown = super(PatchedMacrosPlugin, self).on_page_markdown(markdown, page, config, files)
|
||||
if config.data['extra'].get('version_prefix') or config.data['extra'].get('single_page'):
|
||||
return markdown
|
||||
if self.skip_git_log:
|
||||
return markdown
|
||||
src_path = page.file.abs_src_path
|
||||
try:
|
||||
git_log = subprocess.check_output(f'git log --follow --date=iso8601 "{src_path}"', shell=True)
|
||||
|
@ -201,6 +201,7 @@ public:
|
||||
|
||||
Field operator[](size_t n) const override
|
||||
{
|
||||
assert(n < data.size()); /// This assert is more strict than the corresponding assert inside PODArray.
|
||||
return data[n];
|
||||
}
|
||||
|
||||
|
@ -403,8 +403,20 @@ Block Block::sortColumns() const
|
||||
{
|
||||
Block sorted_block;
|
||||
|
||||
for (const auto & name : index_by_name)
|
||||
sorted_block.insert(data[name.second]);
|
||||
/// std::unordered_map (index_by_name) cannot be used to guarantee the sort order
|
||||
std::vector<decltype(index_by_name.begin())> sorted_index_by_name(index_by_name.size());
|
||||
{
|
||||
size_t i = 0;
|
||||
for (auto it = index_by_name.begin(); it != index_by_name.end(); ++it)
|
||||
sorted_index_by_name[i++] = it;
|
||||
}
|
||||
std::sort(sorted_index_by_name.begin(), sorted_index_by_name.end(), [](const auto & lhs, const auto & rhs)
|
||||
{
|
||||
return lhs->first < rhs->first;
|
||||
});
|
||||
|
||||
for (const auto & it : sorted_index_by_name)
|
||||
sorted_block.insert(data[it->second]);
|
||||
|
||||
return sorted_block;
|
||||
}
|
||||
|
@ -50,9 +50,10 @@ struct DecimalComponents
|
||||
* If `scale` is to big (scale > maxPrecision<DecimalType::NativeType>), result is undefined.
|
||||
*/
|
||||
template <typename DecimalType>
|
||||
DecimalType decimalFromComponentsWithMultiplier(const typename DecimalType::NativeType & whole,
|
||||
const typename DecimalType::NativeType & fractional,
|
||||
typename DecimalType::NativeType scale_multiplier)
|
||||
inline DecimalType decimalFromComponentsWithMultiplier(
|
||||
const typename DecimalType::NativeType & whole,
|
||||
const typename DecimalType::NativeType & fractional,
|
||||
typename DecimalType::NativeType scale_multiplier)
|
||||
{
|
||||
using T = typename DecimalType::NativeType;
|
||||
const auto fractional_sign = whole < 0 ? -1 : 1;
|
||||
@ -70,8 +71,10 @@ DecimalType decimalFromComponentsWithMultiplier(const typename DecimalType::Nati
|
||||
* @see `decimalFromComponentsWithMultiplier` for details.
|
||||
*/
|
||||
template <typename DecimalType>
|
||||
DecimalType decimalFromComponents(
|
||||
const typename DecimalType::NativeType & whole, const typename DecimalType::NativeType & fractional, UInt32 scale)
|
||||
inline DecimalType decimalFromComponents(
|
||||
const typename DecimalType::NativeType & whole,
|
||||
const typename DecimalType::NativeType & fractional,
|
||||
UInt32 scale)
|
||||
{
|
||||
using T = typename DecimalType::NativeType;
|
||||
|
||||
@ -82,8 +85,9 @@ DecimalType decimalFromComponents(
|
||||
* @see `decimalFromComponentsWithMultiplier` for details.
|
||||
*/
|
||||
template <typename DecimalType>
|
||||
DecimalType decimalFromComponents(
|
||||
const DecimalComponents<typename DecimalType::NativeType> & components, UInt32 scale)
|
||||
inline DecimalType decimalFromComponents(
|
||||
const DecimalComponents<typename DecimalType::NativeType> & components,
|
||||
UInt32 scale)
|
||||
{
|
||||
return decimalFromComponents<DecimalType>(components.whole, components.fractional, scale);
|
||||
}
|
||||
@ -92,8 +96,9 @@ DecimalType decimalFromComponents(
|
||||
* This is an optimization to reduce number of calls to scaleMultiplier on known scale.
|
||||
*/
|
||||
template <typename DecimalType>
|
||||
DecimalComponents<typename DecimalType::NativeType> splitWithScaleMultiplier(
|
||||
const DecimalType & decimal, typename DecimalType::NativeType scale_multiplier)
|
||||
inline DecimalComponents<typename DecimalType::NativeType> splitWithScaleMultiplier(
|
||||
const DecimalType & decimal,
|
||||
typename DecimalType::NativeType scale_multiplier)
|
||||
{
|
||||
using T = typename DecimalType::NativeType;
|
||||
const auto whole = decimal.value / scale_multiplier;
|
||||
@ -106,7 +111,7 @@ DecimalComponents<typename DecimalType::NativeType> splitWithScaleMultiplier(
|
||||
|
||||
/// Split decimal into components: whole and fractional part, @see `DecimalComponents` for details.
|
||||
template <typename DecimalType>
|
||||
DecimalComponents<typename DecimalType::NativeType> split(const DecimalType & decimal, UInt32 scale)
|
||||
inline DecimalComponents<typename DecimalType::NativeType> split(const DecimalType & decimal, UInt32 scale)
|
||||
{
|
||||
if (scale == 0)
|
||||
{
|
||||
@ -121,7 +126,7 @@ DecimalComponents<typename DecimalType::NativeType> split(const DecimalType & de
|
||||
* If scale is to big, result is undefined.
|
||||
*/
|
||||
template <typename DecimalType>
|
||||
typename DecimalType::NativeType getWholePart(const DecimalType & decimal, size_t scale)
|
||||
inline typename DecimalType::NativeType getWholePart(const DecimalType & decimal, size_t scale)
|
||||
{
|
||||
if (scale == 0)
|
||||
return decimal.value;
|
||||
@ -129,24 +134,34 @@ typename DecimalType::NativeType getWholePart(const DecimalType & decimal, size_
|
||||
return decimal.value / scaleMultiplier<typename DecimalType::NativeType>(scale);
|
||||
}
|
||||
|
||||
|
||||
template <typename DecimalType, bool keep_sign = false>
|
||||
inline typename DecimalType::NativeType getFractionalPartWithScaleMultiplier(
|
||||
const DecimalType & decimal,
|
||||
typename DecimalType::NativeType scale_multiplier)
|
||||
{
|
||||
using T = typename DecimalType::NativeType;
|
||||
|
||||
T result = decimal.value;
|
||||
if constexpr (!keep_sign)
|
||||
if (result < T(0))
|
||||
result = -result;
|
||||
|
||||
return result % scale_multiplier;
|
||||
}
|
||||
|
||||
/** Get fractional part from decimal
|
||||
*
|
||||
* Result is always positive.
|
||||
* If scale is to big, result is undefined.
|
||||
*/
|
||||
template <typename DecimalType>
|
||||
typename DecimalType::NativeType getFractionalPart(const DecimalType & decimal, size_t scale)
|
||||
inline typename DecimalType::NativeType getFractionalPart(const DecimalType & decimal, size_t scale)
|
||||
{
|
||||
using T = typename DecimalType::NativeType;
|
||||
|
||||
if (scale == 0)
|
||||
return 0;
|
||||
|
||||
T result = decimal.value;
|
||||
if (result < T(0))
|
||||
result *= T(-1);
|
||||
|
||||
return result % scaleMultiplier<T>(scale);
|
||||
return getFractionalPartWithScaleMultiplier(decimal, scaleMultiplier<typename DecimalType::NativeType>(scale));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -116,6 +116,7 @@ struct Settings : public SettingsCollection<Settings>
|
||||
M(SettingBool, distributed_group_by_no_merge, false, "Do not merge aggregation states from different servers for distributed query processing - in case it is for certain that there are different keys on different shards.", 0) \
|
||||
M(SettingBool, parallel_distributed_insert_select, false, "If true, distributed insert select query in the same cluster will be processed on local tables on every shard", 0) \
|
||||
M(SettingBool, optimize_skip_unused_shards, false, "Assumes that data is distributed by sharding_key. Optimization to skip unused shards if SELECT query filters by sharding_key.", 0) \
|
||||
M(SettingBool, optimize_distributed_group_by_sharding_key, false, "Optimize GROUP BY sharding_key queries (by avodiing costly aggregation on the initiator server).", 0) \
|
||||
M(SettingUInt64, force_optimize_skip_unused_shards, 0, "Throw an exception if unused shards cannot be skipped (1 - throw only if the table has the sharding key, 2 - always throw.", 0) \
|
||||
M(SettingBool, force_optimize_skip_unused_shards_no_nested, false, "Do not apply force_optimize_skip_unused_shards for nested Distributed tables.", 0) \
|
||||
\
|
||||
|
@ -45,7 +45,7 @@ private:
|
||||
|
||||
size_t rows_removed = 0;
|
||||
Logger * log;
|
||||
DateLUTImpl date_lut;
|
||||
const DateLUTImpl & date_lut;
|
||||
|
||||
/// TODO rewrite defaults logic to evaluteMissingDefaults
|
||||
std::unordered_map<String, String> defaults_result_column;
|
||||
|
@ -45,40 +45,66 @@ public:
|
||||
bool equals(const IDataType & rhs) const override;
|
||||
};
|
||||
|
||||
|
||||
/** Basic wrapper for Tansform-types for DateTime64.
|
||||
/** Tansform-type wrapper for DateTime64, applies given Transform to DateTime64 value or only to a whole part of it.
|
||||
*
|
||||
* Allows reusing existing Transform (that takes DateTime-values as UInt32) with DateTime64-values,
|
||||
* by discarding fractional part and producing SAME return type as original Transform.
|
||||
* Depending on what overloads of Transform::execute() are available, when called with DateTime64 value,
|
||||
* invokes Transform::execute() with:
|
||||
* * whole part of DateTime64 value, discarding fractional part.
|
||||
* * DateTime64 value and scale factor.
|
||||
*
|
||||
* Such Transfotm-types are commonly used in Date/DateTime manipulation functions,
|
||||
* and implement static execute fucntion with following signature:
|
||||
* R execute(UInt32, T, const DateLUTImpl &)
|
||||
* Suitable Transfotm-types are commonly used in Date/DateTime manipulation functions,
|
||||
* and should implement static (or const) fucntion with following signatures:
|
||||
* R execute(UInt32 whole_value, ... , const TimeZoneImpl &)
|
||||
* OR
|
||||
* R execute(DateTime64 value, Int64 scale_factor, ... , const TimeZoneImpl &)
|
||||
*
|
||||
* Wehere R and T could be arbitrary types.
|
||||
*/
|
||||
template <typename Transform>
|
||||
class DateTime64BasicTransformWrapper : public Transform
|
||||
class TransformDateTime64 : public Transform
|
||||
{
|
||||
private:
|
||||
// Detect if Transform::execute is const or static method
|
||||
// with signature defined by template args (ignoring result type).
|
||||
template<typename = void, typename... Args>
|
||||
struct TransformHasExecuteOverload : std::false_type {};
|
||||
|
||||
template<typename... Args>
|
||||
struct TransformHasExecuteOverload<std::void_t<decltype(std::declval<Transform>().execute(std::declval<Args>()...))>, Args...>
|
||||
: std::true_type {};
|
||||
|
||||
template<typename... Args>
|
||||
static constexpr bool TransformHasExecuteOverload_v = TransformHasExecuteOverload<void, Args...>::value;
|
||||
|
||||
public:
|
||||
static constexpr auto name = Transform::name;
|
||||
|
||||
using Transform::execute;
|
||||
|
||||
explicit DateTime64BasicTransformWrapper(UInt32 scale_)
|
||||
// non-explicit constructor to allow creating from scale value (or with no scale at all), indispensable in some contexts.
|
||||
TransformDateTime64(UInt32 scale_ = 0)
|
||||
: scale_multiplier(DecimalUtils::scaleMultiplier<DateTime64::NativeType>(scale_))
|
||||
{}
|
||||
|
||||
template <typename T>
|
||||
auto execute(DateTime64 t, T v, const DateLUTImpl & time_zone) const
|
||||
template <typename ... Args>
|
||||
inline auto execute(const DateTime64 & t, Args && ... args) const
|
||||
{
|
||||
const auto components = DecimalUtils::splitWithScaleMultiplier(t, scale_multiplier);
|
||||
return static_cast<const Transform *>(this)->execute(
|
||||
static_cast<UInt32>(components.whole), v, time_zone);
|
||||
const auto transform = static_cast<const Transform *>(this);
|
||||
|
||||
if constexpr (TransformHasExecuteOverload_v<DateTime64, decltype(scale_multiplier), Args...>)
|
||||
{
|
||||
return transform->execute(t, scale_multiplier, std::forward<Args>(args)...);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto components = DecimalUtils::splitWithScaleMultiplier(t, scale_multiplier);
|
||||
return transform->execute(static_cast<UInt32>(components.whole), std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
UInt32 scale_multiplier = 1;
|
||||
DateTime64::NativeType scale_multiplier = 1;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -777,7 +777,7 @@ void CacheDictionary::updateThreadFunction()
|
||||
|
||||
UpdateUnitPtr current_unit_ptr;
|
||||
|
||||
while (!update_request.empty() && update_queue.tryPop(current_unit_ptr))
|
||||
while (update_request.size() < current_queue_size + 1 && update_queue.tryPop(current_unit_ptr))
|
||||
update_request.emplace_back(std::move(current_unit_ptr));
|
||||
|
||||
BunchUpdateUnit bunch_update_unit(update_request);
|
||||
@ -817,7 +817,7 @@ void CacheDictionary::waitForCurrentUpdateFinish(UpdateUnitPtr & update_unit_ptr
|
||||
bool result = is_update_finished.wait_for(
|
||||
update_lock,
|
||||
std::chrono::milliseconds(timeout_for_wait),
|
||||
[&] {return update_unit_ptr->is_done || update_unit_ptr->current_exception; });
|
||||
[&] { return update_unit_ptr->is_done || update_unit_ptr->current_exception; });
|
||||
|
||||
if (!result)
|
||||
{
|
||||
@ -936,7 +936,6 @@ void CacheDictionary::update(BunchUpdateUnit & bunch_update_unit) const
|
||||
else
|
||||
cell.setExpiresAt(std::chrono::time_point<std::chrono::system_clock>::max());
|
||||
|
||||
|
||||
bunch_update_unit.informCallersAboutPresentId(id, cell_idx);
|
||||
/// mark corresponding id as found
|
||||
remaining_ids[id] = 1;
|
||||
@ -962,7 +961,8 @@ void CacheDictionary::update(BunchUpdateUnit & bunch_update_unit) const
|
||||
}
|
||||
}
|
||||
|
||||
size_t not_found_num = 0, found_num = 0;
|
||||
size_t not_found_num = 0;
|
||||
size_t found_num = 0;
|
||||
|
||||
/// Check which ids have not been found and require setting null_value
|
||||
for (const auto & id_found_pair : remaining_ids)
|
||||
|
@ -38,12 +38,16 @@ template <typename AttributeType, typename OutputType, typename DefaultGetter>
|
||||
void CacheDictionary::getItemsNumberImpl(
|
||||
Attribute & attribute, const PaddedPODArray<Key> & ids, ResultArrayType<OutputType> & out, DefaultGetter && get_default) const
|
||||
{
|
||||
/// First fill everything with default values
|
||||
const auto rows = ext::size(ids);
|
||||
for (const auto row : ext::range(0, rows))
|
||||
out[row] = get_default(row);
|
||||
|
||||
/// Mapping: <id> -> { all indices `i` of `ids` such that `ids[i]` = <id> }
|
||||
std::unordered_map<Key, std::vector<size_t>> cache_expired_ids;
|
||||
std::unordered_map<Key, std::vector<size_t>> cache_not_found_ids;
|
||||
|
||||
auto & attribute_array = std::get<ContainerPtrType<AttributeType>>(attribute.arrays);
|
||||
const auto rows = ext::size(ids);
|
||||
|
||||
size_t cache_hit = 0;
|
||||
|
||||
@ -67,7 +71,8 @@ void CacheDictionary::getItemsNumberImpl(
|
||||
{
|
||||
const auto & cell_idx = find_result.cell_idx;
|
||||
const auto & cell = cells[cell_idx];
|
||||
out[row] = cell.isDefault() ? get_default(row) : static_cast<OutputType>(attribute_array[cell_idx]);
|
||||
if (!cell.isDefault())
|
||||
out[row] = static_cast<OutputType>(attribute_array[cell_idx]);
|
||||
};
|
||||
|
||||
if (!find_result.valid)
|
||||
@ -154,14 +159,7 @@ void CacheDictionary::getItemsNumberImpl(
|
||||
out[row] = static_cast<OutputType>(attribute_value);
|
||||
};
|
||||
|
||||
auto on_id_not_found = [&] (const auto id, const auto)
|
||||
{
|
||||
for (const size_t row : cache_not_found_ids[id])
|
||||
out[row] = get_default(row);
|
||||
|
||||
for (const size_t row : cache_expired_ids[id])
|
||||
out[row] = get_default(row);
|
||||
};
|
||||
auto on_id_not_found = [&] (auto, auto) {};
|
||||
|
||||
/// Request new values
|
||||
auto update_unit_ptr = std::make_shared<UpdateUnit>(required_ids, on_cell_updated, on_id_not_found);
|
||||
|
@ -175,6 +175,41 @@ struct ToStartOfMinuteImpl
|
||||
using FactorTransform = ZeroTransform;
|
||||
};
|
||||
|
||||
// Rounding towards negative infinity.
|
||||
// 1.01 => 1.00
|
||||
// -1.01 => -2
|
||||
struct ToStartOfSecondImpl
|
||||
{
|
||||
static constexpr auto name = "toStartOfSecond";
|
||||
|
||||
static inline DateTime64 execute(const DateTime64 & datetime64, Int64 scale_multiplier, const DateLUTImpl &)
|
||||
{
|
||||
auto fractional_with_sign = DecimalUtils::getFractionalPartWithScaleMultiplier<DateTime64, true>(datetime64, scale_multiplier);
|
||||
|
||||
// given that scale is 3, scale_multiplier is 1000
|
||||
// for DateTime64 value of 123.456:
|
||||
// 123456 - 456 = 123000
|
||||
// for DateTime64 value of -123.456:
|
||||
// -123456 - (1000 + (-456)) = -124000
|
||||
|
||||
if (fractional_with_sign < 0)
|
||||
fractional_with_sign += scale_multiplier;
|
||||
|
||||
return datetime64 - fractional_with_sign;
|
||||
}
|
||||
|
||||
static inline UInt32 execute(UInt32, const DateLUTImpl &)
|
||||
{
|
||||
throw Exception("Illegal type DateTime of argument for function " + std::string(name), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
}
|
||||
static inline UInt32 execute(UInt16, const DateLUTImpl &)
|
||||
{
|
||||
return dateIsNotSupported(name);
|
||||
}
|
||||
|
||||
using FactorTransform = ZeroTransform;
|
||||
};
|
||||
|
||||
struct ToStartOfFiveMinuteImpl
|
||||
{
|
||||
static constexpr auto name = "toStartOfFiveMinute";
|
||||
|
@ -110,7 +110,7 @@ public:
|
||||
{
|
||||
CustomWeekTransformImpl<DataTypeDateTime64, ToDataType>::execute(
|
||||
block, arguments, result, input_rows_count,
|
||||
DateTime64BasicTransformWrapper<Transform>{assert_cast<const DataTypeDateTime64 *>(from_type)->getScale()});
|
||||
TransformDateTime64<Transform>{assert_cast<const DataTypeDateTime64 *>(from_type)->getScale()});
|
||||
}
|
||||
else
|
||||
throw Exception(
|
||||
|
@ -16,26 +16,6 @@ namespace ErrorCodes
|
||||
extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
|
||||
}
|
||||
|
||||
template<class Transform>
|
||||
struct WithDateTime64Converter : public Transform
|
||||
{
|
||||
UInt8 scale;
|
||||
Transform transform;
|
||||
|
||||
explicit WithDateTime64Converter(UInt8 scale_, Transform transform_ = {})
|
||||
: scale(scale_),
|
||||
transform(std::move(transform_))
|
||||
{}
|
||||
|
||||
inline auto execute(DataTypeDateTime64::FieldType t, const DateLUTImpl & time_zone) const
|
||||
{
|
||||
auto x = DateTime64(t);
|
||||
auto res = transform.execute(static_cast<UInt32>(DecimalUtils::getWholePart(x, scale)), time_zone);
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// See DateTimeTransforms.h
|
||||
template <typename ToDataType, typename Transform>
|
||||
class FunctionDateOrDateTimeToSomething : public IFunction
|
||||
@ -90,7 +70,13 @@ public:
|
||||
if constexpr (std::is_same_v<ToDataType, DataTypeDateTime>)
|
||||
return std::make_shared<ToDataType>(extractTimeZoneNameFromFunctionArguments(arguments, 1, 0));
|
||||
if constexpr (std::is_same_v<ToDataType, DataTypeDateTime64>)
|
||||
return std::make_shared<ToDataType>(extractTimeZoneNameFromFunctionArguments(arguments, 1, 0));
|
||||
{
|
||||
Int64 scale = DataTypeDateTime64::default_scale;
|
||||
if (const auto * dt64 = checkAndGetDataType<DataTypeDateTime64>(arguments[0].type.get()))
|
||||
scale = dt64->getScale();
|
||||
|
||||
return std::make_shared<ToDataType>(scale, extractTimeZoneNameFromFunctionArguments(arguments, 1, 0));
|
||||
}
|
||||
else
|
||||
return std::make_shared<ToDataType>();
|
||||
}
|
||||
@ -110,16 +96,14 @@ public:
|
||||
else if (which.isDateTime64())
|
||||
{
|
||||
const auto scale = static_cast<const DataTypeDateTime64 *>(from_type)->getScale();
|
||||
WithDateTime64Converter<Transform> transformer(scale);
|
||||
|
||||
DateTimeTransformImpl<DataTypeDateTime64, ToDataType, WithDateTime64Converter<Transform>>::execute(block, arguments, result, input_rows_count, transformer);
|
||||
const TransformDateTime64<Transform> transformer(scale);
|
||||
DateTimeTransformImpl<DataTypeDateTime64, ToDataType, decltype(transformer)>::execute(block, arguments, result, input_rows_count, transformer);
|
||||
}
|
||||
else
|
||||
throw Exception("Illegal type " + block.getByPosition(arguments[0]).type->getName() + " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
}
|
||||
|
||||
|
||||
bool hasInformationAboutMonotonicity() const override
|
||||
{
|
||||
return true;
|
||||
|
@ -56,6 +56,15 @@ FunctionOverloadResolverImplPtr FunctionFactory::getImpl(
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<std::string> FunctionFactory::getAllNames() const
|
||||
{
|
||||
std::vector<std::string> res;
|
||||
res.reserve(functions.size());
|
||||
for (const auto & func : functions)
|
||||
res.emplace_back(func.first);
|
||||
return res;
|
||||
}
|
||||
|
||||
FunctionOverloadResolverPtr FunctionFactory::get(
|
||||
const std::string & name,
|
||||
const Context & context) const
|
||||
|
@ -39,6 +39,9 @@ public:
|
||||
registerFunction(name, &Function::create, case_sensitiveness);
|
||||
}
|
||||
|
||||
/// This function is used by YQL - internal Yandex product that depends on ClickHouse by source code.
|
||||
std::vector<std::string> getAllNames() const;
|
||||
|
||||
/// Throws an exception if not found.
|
||||
FunctionOverloadResolverPtr get(const std::string & name, const Context & context) const;
|
||||
|
||||
|
@ -11,6 +11,7 @@ void registerFunctionToDayOfWeek(FunctionFactory &);
|
||||
void registerFunctionToDayOfYear(FunctionFactory &);
|
||||
void registerFunctionToHour(FunctionFactory &);
|
||||
void registerFunctionToMinute(FunctionFactory &);
|
||||
void registerFunctionToStartOfSecond(FunctionFactory &);
|
||||
void registerFunctionToSecond(FunctionFactory &);
|
||||
void registerFunctionToStartOfDay(FunctionFactory &);
|
||||
void registerFunctionToMonday(FunctionFactory &);
|
||||
@ -84,6 +85,7 @@ void registerFunctionsDateTime(FunctionFactory & factory)
|
||||
registerFunctionToStartOfMonth(factory);
|
||||
registerFunctionToStartOfQuarter(factory);
|
||||
registerFunctionToStartOfYear(factory);
|
||||
registerFunctionToStartOfSecond(factory);
|
||||
registerFunctionToStartOfMinute(factory);
|
||||
registerFunctionToStartOfFiveMinute(factory);
|
||||
registerFunctionToStartOfTenMinutes(factory);
|
||||
|
@ -31,6 +31,8 @@ namespace
|
||||
template <>
|
||||
struct Transform<IntervalKind::Year>
|
||||
{
|
||||
static constexpr auto name = function_name;
|
||||
|
||||
static UInt16 execute(UInt16 d, UInt64 years, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toStartOfYearInterval(DayNum(d), years);
|
||||
@ -45,6 +47,8 @@ namespace
|
||||
template <>
|
||||
struct Transform<IntervalKind::Quarter>
|
||||
{
|
||||
static constexpr auto name = function_name;
|
||||
|
||||
static UInt16 execute(UInt16 d, UInt64 quarters, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toStartOfQuarterInterval(DayNum(d), quarters);
|
||||
@ -59,6 +63,8 @@ namespace
|
||||
template <>
|
||||
struct Transform<IntervalKind::Month>
|
||||
{
|
||||
static constexpr auto name = function_name;
|
||||
|
||||
static UInt16 execute(UInt16 d, UInt64 months, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toStartOfMonthInterval(DayNum(d), months);
|
||||
@ -73,6 +79,8 @@ namespace
|
||||
template <>
|
||||
struct Transform<IntervalKind::Week>
|
||||
{
|
||||
static constexpr auto name = function_name;
|
||||
|
||||
static UInt16 execute(UInt16 d, UInt64 weeks, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toStartOfWeekInterval(DayNum(d), weeks);
|
||||
@ -87,6 +95,8 @@ namespace
|
||||
template <>
|
||||
struct Transform<IntervalKind::Day>
|
||||
{
|
||||
static constexpr auto name = function_name;
|
||||
|
||||
static UInt32 execute(UInt16 d, UInt64 days, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toStartOfDayInterval(DayNum(d), days);
|
||||
@ -101,6 +111,8 @@ namespace
|
||||
template <>
|
||||
struct Transform<IntervalKind::Hour>
|
||||
{
|
||||
static constexpr auto name = function_name;
|
||||
|
||||
static UInt32 execute(UInt16, UInt64, const DateLUTImpl &) { return dateIsNotSupported(function_name); }
|
||||
|
||||
static UInt32 execute(UInt32 t, UInt64 hours, const DateLUTImpl & time_zone) { return time_zone.toStartOfHourInterval(t, hours); }
|
||||
@ -109,6 +121,8 @@ namespace
|
||||
template <>
|
||||
struct Transform<IntervalKind::Minute>
|
||||
{
|
||||
static constexpr auto name = function_name;
|
||||
|
||||
static UInt32 execute(UInt16, UInt64, const DateLUTImpl &) { return dateIsNotSupported(function_name); }
|
||||
|
||||
static UInt32 execute(UInt32 t, UInt64 minutes, const DateLUTImpl & time_zone)
|
||||
@ -120,6 +134,8 @@ namespace
|
||||
template <>
|
||||
struct Transform<IntervalKind::Second>
|
||||
{
|
||||
static constexpr auto name = function_name;
|
||||
|
||||
static UInt32 execute(UInt16, UInt64, const DateLUTImpl &) { return dateIsNotSupported(function_name); }
|
||||
|
||||
static UInt32 execute(UInt32 t, UInt64 seconds, const DateLUTImpl & time_zone)
|
||||
@ -311,7 +327,7 @@ private:
|
||||
|
||||
if constexpr (std::is_same_v<FromDataType, DataTypeDateTime64>)
|
||||
{
|
||||
const auto transform = DateTime64BasicTransformWrapper<Transform<unit>>{from_datatype.getScale()};
|
||||
const auto transform = TransformDateTime64<Transform<unit>>{from_datatype.getScale()};
|
||||
for (size_t i = 0; i != size; ++i)
|
||||
result_data[i] = transform.execute(time_data[i], num_units, time_zone);
|
||||
}
|
||||
|
18
src/Functions/toStartOfSecond.cpp
Normal file
18
src/Functions/toStartOfSecond.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
#include <Functions/IFunctionImpl.h>
|
||||
#include <Functions/FunctionFactory.h>
|
||||
#include <Functions/DateTimeTransforms.h>
|
||||
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||
#include <DataTypes/DataTypesNumber.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using FunctionToStartOfSecond = FunctionDateOrDateTimeToSomething<DataTypeDateTime64, ToStartOfSecondImpl>;
|
||||
|
||||
void registerFunctionToStartOfSecond(FunctionFactory & factory)
|
||||
{
|
||||
factory.registerFunction<FunctionToStartOfSecond>();
|
||||
}
|
||||
|
||||
}
|
@ -380,6 +380,7 @@ SRCS(
|
||||
toStartOfMinute.cpp
|
||||
toStartOfMonth.cpp
|
||||
toStartOfQuarter.cpp
|
||||
toStartOfSecond.cpp
|
||||
toStartOfTenMinutes.cpp
|
||||
toStartOfYear.cpp
|
||||
toTime.cpp
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include <Interpreters/InterpreterSetQuery.h>
|
||||
#include <Interpreters/evaluateConstantExpression.h>
|
||||
#include <Interpreters/convertFieldToType.h>
|
||||
#include <Interpreters/addTypeConversionToAST.h>
|
||||
#include <Interpreters/ExpressionAnalyzer.h>
|
||||
#include <Interpreters/getTableExpressions.h>
|
||||
#include <Interpreters/JoinToSubqueryTransformVisitor.h>
|
||||
@ -1210,7 +1211,12 @@ void InterpreterSelectQuery::executeFetchColumns(
|
||||
const auto column_default = storage_columns.getDefault(column);
|
||||
bool is_alias = column_default && column_default->kind == ColumnDefaultKind::Alias;
|
||||
if (is_alias)
|
||||
column_expr = setAlias(column_default->expression->clone(), column);
|
||||
{
|
||||
auto column_decl = storage_columns.get(column);
|
||||
/// TODO: can make CAST only if the type is different (but requires SyntaxAnalyzer).
|
||||
auto cast_column_default = addTypeConversionToAST(column_default->expression->clone(), column_decl.type->getName());
|
||||
column_expr = setAlias(cast_column_default->clone(), column);
|
||||
}
|
||||
else
|
||||
column_expr = std::make_shared<ASTIdentifier>(column);
|
||||
|
||||
|
@ -32,9 +32,9 @@ namespace DB
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int ARGUMENT_OUT_OF_BOUND;
|
||||
extern const int LOGICAL_ERROR;
|
||||
extern const int TYPE_MISMATCH;
|
||||
extern const int TOO_LARGE_STRING_SIZE;
|
||||
extern const int CANNOT_CONVERT_TYPE;
|
||||
}
|
||||
|
||||
|
||||
@ -201,7 +201,7 @@ Field convertFieldToTypeImpl(const Field & src, const IDataType & type, const ID
|
||||
if (const auto * ptype = typeid_cast<const DataTypeDecimal<Decimal128> *>(&type)) return convertDecimalType(src, *ptype);
|
||||
|
||||
if (!which_type.isDateOrDateTime() && !which_type.isUUID() && !which_type.isEnum())
|
||||
throw Exception{"Logical error: unknown numeric type " + type.getName(), ErrorCodes::LOGICAL_ERROR};
|
||||
throw Exception{"Cannot convert field to type " + type.getName(), ErrorCodes::CANNOT_CONVERT_TYPE};
|
||||
|
||||
if (which_type.isEnum() && (src.getType() == Field::Types::UInt64 || src.getType() == Field::Types::Int64))
|
||||
{
|
||||
|
@ -710,8 +710,7 @@ static void castValueToType(const DataTypePtr & desired_type, Field & src_value,
|
||||
|
||||
try
|
||||
{
|
||||
/// NOTE: We don't need accurate info about src_type at this moment
|
||||
src_value = convertFieldToType(src_value, *desired_type);
|
||||
src_value = convertFieldToType(src_value, *desired_type, src_type.get());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
@ -375,6 +375,9 @@ bool StorageDistributed::canForceGroupByNoMerge(const Context &context, QueryPro
|
||||
|
||||
if (settings.distributed_group_by_no_merge)
|
||||
return true;
|
||||
if (!settings.optimize_distributed_group_by_sharding_key)
|
||||
return false;
|
||||
|
||||
/// Distributed-over-Distributed (see getQueryProcessingStageImpl())
|
||||
if (to_stage == QueryProcessingStage::WithMergeableState)
|
||||
return false;
|
||||
@ -385,8 +388,17 @@ bool StorageDistributed::canForceGroupByNoMerge(const Context &context, QueryPro
|
||||
|
||||
const auto & select = query_ptr->as<ASTSelectQuery &>();
|
||||
|
||||
if (select.group_by_with_totals || select.group_by_with_rollup || select.group_by_with_cube)
|
||||
return false;
|
||||
|
||||
// TODO: The following can be optimized too (but with some caveats, will be addressed later):
|
||||
// - ORDER BY
|
||||
// - LIMIT BY
|
||||
// - LIMIT
|
||||
if (select.orderBy())
|
||||
return false;
|
||||
if (select.limitBy() || select.limitLength())
|
||||
return false;
|
||||
|
||||
if (select.distinct)
|
||||
{
|
||||
@ -402,11 +414,6 @@ bool StorageDistributed::canForceGroupByNoMerge(const Context &context, QueryPro
|
||||
reason = "DISTINCT " + backQuote(serializeAST(*select.select(), true));
|
||||
}
|
||||
|
||||
// This can use distributed_group_by_no_merge but in this case limit stage
|
||||
// should be done later (which is not the case right now).
|
||||
if (select.limitBy() || select.limitLength())
|
||||
return false;
|
||||
|
||||
const ASTPtr group_by = select.groupBy();
|
||||
if (!group_by)
|
||||
{
|
||||
|
@ -194,8 +194,8 @@ String transformQueryForExternalDatabase(
|
||||
|
||||
std::stringstream out;
|
||||
IAST::FormatSettings settings(out, true);
|
||||
settings.always_quote_identifiers = true;
|
||||
settings.identifier_quoting_style = identifier_quoting_style;
|
||||
settings.always_quote_identifiers = identifier_quoting_style != IdentifierQuotingStyle::None;
|
||||
|
||||
select->format(settings);
|
||||
|
||||
|
@ -3,5 +3,5 @@ SELECT * FROM test_table_for_01070_exception_code_in_query_log_table; -- { serve
|
||||
CREATE TABLE test_table_for_01070_exception_code_in_query_log_table (value UInt64) ENGINE=Memory();
|
||||
SELECT * FROM test_table_for_01070_exception_code_in_query_log_table;
|
||||
SYSTEM FLUSH LOGS;
|
||||
SELECT exception_code FROM system.query_log WHERE query='SELECT * FROM test_table_for_01070_exception_code_in_query_log_table' ORDER BY exception_code;
|
||||
SELECT exception_code FROM system.query_log WHERE query = 'SELECT * FROM test_table_for_01070_exception_code_in_query_log_table' AND event_date >= yesterday() AND event_time > now() - INTERVAL 5 MINUTE ORDER BY exception_code;
|
||||
DROP TABLE IF EXISTS test_table_for_01070_exception_code_in_query_log_table;
|
||||
|
@ -5,10 +5,10 @@ CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
|
||||
$CLICKHOUSE_CLIENT --query "DROP TABLE IF EXISTS table_for_bad_alters";
|
||||
|
||||
$CLICKHOUSE_CLIENT -n --query "CREATE TABLE table_for_bad_alters (
|
||||
key UInt64,
|
||||
value1 UInt8,
|
||||
value2 String
|
||||
$CLICKHOUSE_CLIENT -n --query "CREATE TABLE table_for_bad_alters (
|
||||
key UInt64,
|
||||
value1 UInt8,
|
||||
value2 String
|
||||
) ENGINE = ReplicatedMergeTree('/clickhouse/tables/table_for_bad_alters', '1')
|
||||
ORDER BY key;"
|
||||
|
||||
|
@ -6,5 +6,3 @@ optimize_skip_unused_shards
|
||||
optimize_skip_unused_shards lack of WHERE
|
||||
0
|
||||
1
|
||||
0
|
||||
1
|
||||
|
@ -12,7 +12,6 @@ SELECT DISTINCT id FROM dist_01213 WHERE id = 1 SETTINGS distributed_group_by_no
|
||||
SELECT 'optimize_skip_unused_shards';
|
||||
SELECT DISTINCT id FROM dist_01213 WHERE id = 1 SETTINGS optimize_skip_unused_shards=1;
|
||||
-- check that querying all shards is ok
|
||||
-- (there will be duplicates, since the INSERT was done via local table)
|
||||
SELECT 'optimize_skip_unused_shards lack of WHERE';
|
||||
SELECT DISTINCT id FROM dist_01213 SETTINGS optimize_skip_unused_shards=1;
|
||||
|
||||
|
@ -0,0 +1,17 @@
|
||||
Distributed(number)-over-Distributed(number)
|
||||
1 0
|
||||
1 1
|
||||
1 0
|
||||
1 1
|
||||
1 0
|
||||
1 1
|
||||
1 0
|
||||
1 1
|
||||
Distributed(rand)-over-Distributed(number)
|
||||
4 0
|
||||
4 1
|
||||
Distributed(rand)-over-Distributed(rand)
|
||||
2 0
|
||||
2 1
|
||||
2 0
|
||||
2 1
|
@ -0,0 +1,36 @@
|
||||
-- TODO: correct testing with real unique shards
|
||||
|
||||
set optimize_distributed_group_by_sharding_key=1;
|
||||
|
||||
drop table if exists dist_01247;
|
||||
drop table if exists dist_layer_01247;
|
||||
drop table if exists data_01247;
|
||||
|
||||
create table data_01247 as system.numbers engine=Memory();
|
||||
-- since data is not inserted via distributed it will have duplicates
|
||||
-- (and this is how we ensure that this optimization will work)
|
||||
insert into data_01247 select * from system.numbers limit 2;
|
||||
|
||||
set max_distributed_connections=1;
|
||||
set optimize_skip_unused_shards=1;
|
||||
|
||||
select 'Distributed(number)-over-Distributed(number)';
|
||||
create table dist_layer_01247 as data_01247 engine=Distributed(test_cluster_two_shards, currentDatabase(), data_01247, number);
|
||||
create table dist_01247 as data_01247 engine=Distributed(test_cluster_two_shards, currentDatabase(), dist_layer_01247, number);
|
||||
select count(), * from dist_01247 group by number;
|
||||
drop table if exists dist_01247;
|
||||
drop table if exists dist_layer_01247;
|
||||
|
||||
select 'Distributed(rand)-over-Distributed(number)';
|
||||
create table dist_layer_01247 as data_01247 engine=Distributed(test_cluster_two_shards, currentDatabase(), data_01247, number);
|
||||
create table dist_01247 as data_01247 engine=Distributed(test_cluster_two_shards, currentDatabase(), dist_layer_01247, rand());
|
||||
select count(), * from dist_01247 group by number;
|
||||
drop table if exists dist_01247;
|
||||
drop table if exists dist_layer_01247;
|
||||
|
||||
select 'Distributed(rand)-over-Distributed(rand)';
|
||||
create table dist_layer_01247 as data_01247 engine=Distributed(test_cluster_two_shards, currentDatabase(), data_01247, rand());
|
||||
create table dist_01247 as data_01247 engine=Distributed(test_cluster_two_shards, currentDatabase(), dist_layer_01247, number);
|
||||
select count(), * from dist_01247 group by number;
|
||||
drop table dist_01247;
|
||||
drop table dist_layer_01247;
|
@ -67,3 +67,24 @@ GROUP BY (Distributed-over-Distributed) distributed_group_by_no_merge
|
||||
1 1
|
||||
1 0
|
||||
1 1
|
||||
extremes
|
||||
1 0
|
||||
1 1
|
||||
1 0
|
||||
1 1
|
||||
|
||||
1 0
|
||||
1 1
|
||||
WITH TOTALS
|
||||
2 0
|
||||
2 1
|
||||
|
||||
4 0
|
||||
WITH ROLLUP
|
||||
2 0
|
||||
2 1
|
||||
4 0
|
||||
WITH CUBE
|
||||
2 0
|
||||
2 1
|
||||
4 0
|
||||
|
@ -1,3 +1,7 @@
|
||||
-- TODO: correct testing with real unique shards
|
||||
|
||||
set optimize_distributed_group_by_sharding_key=1;
|
||||
|
||||
drop table if exists dist_01247;
|
||||
drop table if exists data_01247;
|
||||
|
||||
@ -60,3 +64,12 @@ select 'GROUP BY (Distributed-over-Distributed)';
|
||||
select count(), * from cluster(test_cluster_two_shards, currentDatabase(), dist_01247) group by number;
|
||||
select 'GROUP BY (Distributed-over-Distributed) distributed_group_by_no_merge';
|
||||
select count(), * from cluster(test_cluster_two_shards, currentDatabase(), dist_01247) group by number settings distributed_group_by_no_merge=1;
|
||||
|
||||
select 'extremes';
|
||||
select count(), * from dist_01247 group by number settings extremes=1;
|
||||
select 'WITH TOTALS';
|
||||
select count(), * from dist_01247 group by number with totals;
|
||||
select 'WITH ROLLUP';
|
||||
select count(), * from dist_01247 group by number with rollup;
|
||||
select 'WITH CUBE';
|
||||
select count(), * from dist_01247 group by number with cube;
|
||||
|
@ -0,0 +1,4 @@
|
||||
UInt8
|
||||
0
|
||||
UInt8
|
||||
0
|
22
tests/queries/0_stateless/01269_alias_type_differs.sql
Normal file
22
tests/queries/0_stateless/01269_alias_type_differs.sql
Normal file
@ -0,0 +1,22 @@
|
||||
DROP TABLE IF EXISTS data_01269;
|
||||
CREATE TABLE data_01269
|
||||
(
|
||||
key Int32,
|
||||
value Nullable(Int32),
|
||||
alias UInt8 ALIAS value>0
|
||||
)
|
||||
ENGINE = MergeTree()
|
||||
ORDER BY key;
|
||||
INSERT INTO data_01269 VALUES (1, 0);
|
||||
|
||||
-- after PR#10441
|
||||
SELECT toTypeName(alias) FROM data_01269;
|
||||
SELECT any(alias) FROM data_01269;
|
||||
|
||||
-- even without PR#10441
|
||||
ALTER TABLE data_01269 DROP COLUMN alias;
|
||||
ALTER TABLE data_01269 ADD COLUMN alias UInt8 ALIAS value>0;
|
||||
SELECT toTypeName(alias) FROM data_01269;
|
||||
SELECT any(alias) FROM data_01269;
|
||||
|
||||
DROP TABLE data_01269;
|
@ -0,0 +1,6 @@
|
||||
2019-09-16 16:20:11.000 DateTime64(3, \'UTC\')
|
||||
2019-09-16 19:20:11 DateTime64(0, \'UTC\')
|
||||
2019-09-16 19:20:11.000 DateTime64(3, \'UTC\')
|
||||
2019-09-16 19:20:11.000000000 DateTime64(9, \'UTC\')
|
||||
non-const column
|
||||
2019-09-16 19:20:11.000 DateTime64(3, \'UTC\')
|
13
tests/queries/0_stateless/01269_toStartOfSecond.sql
Normal file
13
tests/queries/0_stateless/01269_toStartOfSecond.sql
Normal file
@ -0,0 +1,13 @@
|
||||
-- Error cases
|
||||
SELECT toStartOfSecond('123'); -- {serverError 43}
|
||||
SELECT toStartOfSecond(now()); -- {serverError 43}
|
||||
SELECT toStartOfSecond(); -- {serverError 42}
|
||||
SELECT toStartOfSecond(now64(), 123); -- {serverError 43}
|
||||
|
||||
WITH toDateTime64('2019-09-16 19:20:11', 3) AS dt64 SELECT toStartOfSecond(dt64, 'UTC') AS res, toTypeName(res);
|
||||
WITH toDateTime64('2019-09-16 19:20:11', 0, 'UTC') AS dt64 SELECT toStartOfSecond(dt64) AS res, toTypeName(res);
|
||||
WITH toDateTime64('2019-09-16 19:20:11.123', 3, 'UTC') AS dt64 SELECT toStartOfSecond(dt64) AS res, toTypeName(res);
|
||||
WITH toDateTime64('2019-09-16 19:20:11.123', 9, 'UTC') AS dt64 SELECT toStartOfSecond(dt64) AS res, toTypeName(res);
|
||||
|
||||
SELECT 'non-const column';
|
||||
WITH toDateTime64('2019-09-16 19:20:11.123', 3, 'UTC') AS dt64 SELECT toStartOfSecond(materialize(dt64)) AS res, toTypeName(res);
|
59
tests/queries/0_stateless/01277_buffer_column_order.sql
Normal file
59
tests/queries/0_stateless/01277_buffer_column_order.sql
Normal file
@ -0,0 +1,59 @@
|
||||
-- Check for Block::sortColumns(), can be done using Buffer.
|
||||
|
||||
drop table if exists out_01277;
|
||||
drop table if exists in_01277;
|
||||
drop table if exists buffer_01277;
|
||||
drop table if exists mv_01277_1;
|
||||
drop table if exists mv_01277_2;
|
||||
|
||||
create table out_01277
|
||||
(
|
||||
k1 Int,
|
||||
k2 Int,
|
||||
a1 Int,
|
||||
a2 Int,
|
||||
b1 Int,
|
||||
b2 Int,
|
||||
c Int
|
||||
) Engine=Null();
|
||||
create table buffer_01277 as out_01277 Engine=Buffer(currentDatabase(), out_01277, 1,
|
||||
86400, 86400,
|
||||
1e5, 1e6,
|
||||
10e6, 100e6);
|
||||
create table in_01277 as out_01277 Engine=Null();
|
||||
|
||||
-- differs in order of fields in SELECT clause
|
||||
create materialized view mv_01277_1 to buffer_01277 as select k1, k2, a1, a2, b1, b2, c from in_01277;
|
||||
create materialized view mv_01277_2 to buffer_01277 as select a1, a2, k1, k2, b1, b2, c from in_01277;
|
||||
|
||||
-- column order is ignored, just for humans
|
||||
insert into mv_01277_1 select
|
||||
number k1,
|
||||
number k2,
|
||||
number a1,
|
||||
number a2,
|
||||
number b1,
|
||||
number b2,
|
||||
number c
|
||||
from numbers(1);
|
||||
|
||||
-- with wrong order in Block::sortColumns() triggers:
|
||||
--
|
||||
-- Code: 171. DB::Exception: Received from localhost:9000. DB::Exception: Block structure mismatch in Buffer stream: different names of columns:
|
||||
-- c Int32 Int32(size = 1), b2 Int32 Int32(size = 1), a2 Int32 Int32(size = 1), a1 Int32 Int32(size = 1), k2 Int32 Int32(size = 1), b1 Int32 Int32(size = 1), k1 Int32 Int32(size = 1)
|
||||
-- c Int32 Int32(size = 1), b2 Int32 Int32(size = 1), k2 Int32 Int32(size = 1), a1 Int32 Int32(size = 1), b1 Int32 Int32(size = 1), k1 Int32 Int32(size = 1), a2 Int32 Int32(size = 1).
|
||||
insert into mv_01277_2 select
|
||||
number a1,
|
||||
number a2,
|
||||
number k1,
|
||||
number k2,
|
||||
number b1,
|
||||
number b2,
|
||||
number c
|
||||
from numbers(1);
|
||||
|
||||
drop table mv_01277_1;
|
||||
drop table mv_01277_2;
|
||||
drop table buffer_01277;
|
||||
drop table out_01277;
|
||||
drop table in_01277;
|
@ -0,0 +1 @@
|
||||
SELECT -2487, globalNullIn(toIntervalMinute(-88074), 'qEkek..'), [-27.537293]; -- { serverError 70 }
|
@ -0,0 +1,10 @@
|
||||
['2020-01-01 10:00:00']
|
||||
['2020-01-02 00:00:00']
|
||||
['2020-01-01 00:00:00','2020-01-01 10:00:00']
|
||||
['2020-01-01 00:00:00','2020-01-01 10:00:00','2020-01-02 00:00:00']
|
||||
['2020-01-01 00:00:00','2020-01-01 10:00:00','2020-01-02 00:00:00']
|
||||
['2020-01-01 00:00:00','2020-01-01 10:00:00','2020-01-02 00:00:00']
|
||||
['2020-01-01 00:00:00','2020-01-01 10:00:00','2020-01-02 00:00:00']
|
||||
[]
|
||||
[]
|
||||
[]
|
@ -0,0 +1,22 @@
|
||||
DROP TABLE IF EXISTS test.date_datetime_key_condition;
|
||||
|
||||
CREATE TABLE test.date_datetime_key_condition (dt DateTime) ENGINE = MergeTree() ORDER BY dt;
|
||||
INSERT INTO test.date_datetime_key_condition VALUES ('2020-01-01 00:00:00'), ('2020-01-01 10:00:00'), ('2020-01-02 00:00:00');
|
||||
|
||||
-- partial
|
||||
SELECT groupArray(dt) from test.date_datetime_key_condition WHERE dt > toDate('2020-01-01') AND dt < toDate('2020-01-02');
|
||||
SELECT groupArray(dt) from test.date_datetime_key_condition WHERE dt >= toDate('2020-01-02');
|
||||
SELECT groupArray(dt) from test.date_datetime_key_condition WHERE dt < toDate('2020-01-02');
|
||||
|
||||
-- inside
|
||||
SELECT groupArray(dt) from test.date_datetime_key_condition WHERE dt > toDate('2019-01-02');
|
||||
SELECT groupArray(dt) from test.date_datetime_key_condition WHERE dt < toDate('2021-01-02');
|
||||
SELECT groupArray(dt) from test.date_datetime_key_condition WHERE dt >= toDate('2019-01-02') AND dt < toDate('2021-01-02');
|
||||
SELECT groupArray(dt) from test.date_datetime_key_condition WHERE dt > toDate('2019-01-02') OR dt <= toDate('2021-01-02');
|
||||
|
||||
-- outside
|
||||
SELECT groupArray(dt) from test.date_datetime_key_condition WHERE dt < toDate('2019-01-02');
|
||||
SELECT groupArray(dt) from test.date_datetime_key_condition WHERE dt > toDate('2021-01-02');
|
||||
SELECT groupArray(dt) from test.date_datetime_key_condition WHERE dt < toDate('2019-01-02') OR dt > toDate('2021-01-02');
|
||||
|
||||
DROP TABLE test.date_datetime_key_condition;
|
@ -1,5 +1 @@
|
||||
# libc++
|
||||
race:locale
|
||||
|
||||
# Too many mutexes: https://github.com/google/sanitizers/issues/950
|
||||
deadlock:DB::MergeTreeReadPool::fillPerPartInfo
|
||||
# Fortunately, we have no suppressions!
|
||||
|
BIN
website/images/clickhouse-209x60.png
Normal file
BIN
website/images/clickhouse-209x60.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 975 B |
@ -1 +0,0 @@
|
||||
Subproject commit dca4f121b86577616e90d46ffcd9771942311f71
|
Binary file not shown.
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 4.4 KiB |
@ -6,7 +6,7 @@
|
||||
"mainEntityOfPage": "{{ url or 'https://clickhouse.tech/' }}",
|
||||
{% if page.meta.published_date %}"datePublished": "{{ page.meta.published_date.isoformat() }}",{% endif %}
|
||||
{% if page.meta.modified_date %}"dateModified": "{{ page.meta.modified_date.isoformat() }}",{% endif %}
|
||||
"image": "https://clickhouse.tech/images/logo.png",
|
||||
"image": "https://clickhouse.tech/images/logo-209x60.png",
|
||||
"author": {
|
||||
"@type": "Project",
|
||||
"name": "ClickHouse"
|
||||
@ -16,9 +16,9 @@
|
||||
"name": "Yandex LLC",
|
||||
"logo": {
|
||||
"@type": "ImageObject",
|
||||
"url": "https://clickhouse.tech/images/logo.png",
|
||||
"width": 240,
|
||||
"height": 120
|
||||
"url": "https://clickhouse.tech/images/yandex.png",
|
||||
"width": 163,
|
||||
"height": 60
|
||||
}
|
||||
}
|
||||
}</script>
|
||||
|
Loading…
Reference in New Issue
Block a user