mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-26 17:41:59 +00:00
Merge branch 'master' into anna-shakhova-DOCSUP-3201-add_raw_blob_format
This commit is contained in:
commit
c67786e2e6
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -142,9 +142,6 @@
|
|||||||
[submodule "contrib/replxx"]
|
[submodule "contrib/replxx"]
|
||||||
path = contrib/replxx
|
path = contrib/replxx
|
||||||
url = https://github.com/ClickHouse-Extras/replxx.git
|
url = https://github.com/ClickHouse-Extras/replxx.git
|
||||||
[submodule "contrib/ryu"]
|
|
||||||
path = contrib/ryu
|
|
||||||
url = https://github.com/ClickHouse-Extras/ryu.git
|
|
||||||
[submodule "contrib/avro"]
|
[submodule "contrib/avro"]
|
||||||
path = contrib/avro
|
path = contrib/avro
|
||||||
url = https://github.com/ClickHouse-Extras/avro.git
|
url = https://github.com/ClickHouse-Extras/avro.git
|
||||||
@ -209,3 +206,6 @@
|
|||||||
path = contrib/abseil-cpp
|
path = contrib/abseil-cpp
|
||||||
url = https://github.com/ClickHouse-Extras/abseil-cpp.git
|
url = https://github.com/ClickHouse-Extras/abseil-cpp.git
|
||||||
branch = lts_2020_02_25
|
branch = lts_2020_02_25
|
||||||
|
[submodule "contrib/dragonbox"]
|
||||||
|
path = contrib/dragonbox
|
||||||
|
url = https://github.com/ClickHouse-Extras/dragonbox.git
|
||||||
|
3
contrib/CMakeLists.txt
vendored
3
contrib/CMakeLists.txt
vendored
@ -35,7 +35,6 @@ add_subdirectory (libmetrohash)
|
|||||||
add_subdirectory (lz4-cmake)
|
add_subdirectory (lz4-cmake)
|
||||||
add_subdirectory (murmurhash)
|
add_subdirectory (murmurhash)
|
||||||
add_subdirectory (replxx-cmake)
|
add_subdirectory (replxx-cmake)
|
||||||
add_subdirectory (ryu-cmake)
|
|
||||||
add_subdirectory (unixodbc-cmake)
|
add_subdirectory (unixodbc-cmake)
|
||||||
add_subdirectory (xz)
|
add_subdirectory (xz)
|
||||||
|
|
||||||
@ -322,3 +321,5 @@ endif()
|
|||||||
if (USE_INTERNAL_ROCKSDB_LIBRARY)
|
if (USE_INTERNAL_ROCKSDB_LIBRARY)
|
||||||
add_subdirectory(rocksdb-cmake)
|
add_subdirectory(rocksdb-cmake)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
add_subdirectory(dragonbox)
|
||||||
|
1
contrib/dragonbox
vendored
Submodule
1
contrib/dragonbox
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit b2751c65c0592c0239aec3becd53d0ea2fde9329
|
2
contrib/poco
vendored
2
contrib/poco
vendored
@ -1 +1 @@
|
|||||||
Subproject commit f3d791f6568b99366d089b4479f76a515beb66d5
|
Subproject commit b5523bb9b4bc4239640cbfec4d734be8b8585639
|
1
contrib/ryu
vendored
1
contrib/ryu
vendored
@ -1 +0,0 @@
|
|||||||
Subproject commit 5b4a853534b47438b4d97935370f6b2397137c2b
|
|
@ -1,10 +0,0 @@
|
|||||||
SET(LIBRARY_DIR ${ClickHouse_SOURCE_DIR}/contrib/ryu)
|
|
||||||
|
|
||||||
add_library(ryu
|
|
||||||
${LIBRARY_DIR}/ryu/d2fixed.c
|
|
||||||
${LIBRARY_DIR}/ryu/d2s.c
|
|
||||||
${LIBRARY_DIR}/ryu/f2s.c
|
|
||||||
${LIBRARY_DIR}/ryu/generic_128.c
|
|
||||||
)
|
|
||||||
|
|
||||||
target_include_directories(ryu SYSTEM BEFORE PUBLIC "${LIBRARY_DIR}")
|
|
@ -137,7 +137,6 @@ function clone_submodules
|
|||||||
contrib/libxml2
|
contrib/libxml2
|
||||||
contrib/poco
|
contrib/poco
|
||||||
contrib/libunwind
|
contrib/libunwind
|
||||||
contrib/ryu
|
|
||||||
contrib/fmtlib
|
contrib/fmtlib
|
||||||
contrib/base64
|
contrib/base64
|
||||||
contrib/cctz
|
contrib/cctz
|
||||||
@ -155,6 +154,7 @@ function clone_submodules
|
|||||||
contrib/croaring
|
contrib/croaring
|
||||||
contrib/miniselect
|
contrib/miniselect
|
||||||
contrib/xz
|
contrib/xz
|
||||||
|
contrib/dragonbox
|
||||||
)
|
)
|
||||||
|
|
||||||
git submodule sync
|
git submodule sync
|
||||||
|
@ -1,12 +1,36 @@
|
|||||||
---
|
---
|
||||||
toc_priority: 14
|
toc_priority: 14
|
||||||
toc_title: "\u266A\u64CD\u573A\u266A"
|
toc_title: 体验平台
|
||||||
---
|
---
|
||||||
|
|
||||||
# ClickHouse体验平台 {#clickhouse-playground}
|
# ClickHouse体验平台 {#clickhouse-playground}
|
||||||
|
|
||||||
[ClickHouse体验平台](https://play.clickhouse.tech?file=welcome) 允许人们通过即时运行查询来尝试ClickHouse,而无需设置他们的服务器或集群。
|
[ClickHouse体验平台](https://play.clickhouse.tech?file=welcome) 允许人们通过即时运行查询来尝试ClickHouse,而无需设置他们的服务器或集群。
|
||||||
体验平台中提供了几个示例数据集以及显示ClickHouse特性的示例查询。
|
|
||||||
|
体验平台中提供几个示例数据集以及显示ClickHouse特性的示例查询。还有一些ClickHouse LTS版本可供尝试。
|
||||||
|
|
||||||
|
ClickHouse体验平台提供了小型集群[Managed Service for ClickHouse](https://cloud.yandex.com/services/managed-clickhouse)实例配置(4 vCPU, 32 GB RAM)它们托管在[Yandex.Cloud](https://cloud.yandex.com/). 更多信息查询[cloud providers](../commercial/cloud.md).
|
||||||
|
|
||||||
|
您可以使用任何HTTP客户端对ClickHouse体验平台进行查询,例如[curl](https://curl.haxx.se)或者[wget](https://www.gnu.org/software/wget/),或使用[JDBC](../interfaces/jdbc.md)或者[ODBC](../interfaces/odbc.md)驱动连接。关于支持ClickHouse的软件产品的更多信息详见[here](../interfaces/index.md).
|
||||||
|
|
||||||
|
## Credentials {#credentials}
|
||||||
|
|
||||||
|
| 参数 | 值 |
|
||||||
|
|:--------------------|:----------------------------------------|
|
||||||
|
| HTTPS端点 | `https://play-api.clickhouse.tech:8443` |
|
||||||
|
| TCP端点 | `play-api.clickhouse.tech:9440` |
|
||||||
|
| 用户 | `playground` |
|
||||||
|
| 密码 | `clickhouse` |
|
||||||
|
|
||||||
|
还有一些带有特定ClickHouse版本的附加信息来试验它们之间的差异(端口和用户/密码与上面相同):
|
||||||
|
|
||||||
|
- 20.3 LTS: `play-api-v20-3.clickhouse.tech`
|
||||||
|
- 19.14 LTS: `play-api-v19-14.clickhouse.tech`
|
||||||
|
|
||||||
|
!!! note "注意"
|
||||||
|
所有这些端点都需要安全的TLS连接。
|
||||||
|
|
||||||
|
## 查询限制 {#limitations}
|
||||||
|
|
||||||
查询以只读用户身份执行。 这意味着一些局限性:
|
查询以只读用户身份执行。 这意味着一些局限性:
|
||||||
|
|
||||||
@ -14,33 +38,34 @@ toc_title: "\u266A\u64CD\u573A\u266A"
|
|||||||
- 不允许插入查询
|
- 不允许插入查询
|
||||||
|
|
||||||
还强制执行以下设置:
|
还强制执行以下设置:
|
||||||
- [`max_result_bytes=10485760`](../operations/settings/query_complexity/#max-result-bytes)
|
- [max_result_bytes=10485760](../operations/settings/query-complexity/#max-result-bytes)
|
||||||
- [`max_result_rows=2000`](../operations/settings/query_complexity/#setting-max_result_rows)
|
- [max_result_rows=2000](../operations/settings/query-complexity/#setting-max_result_rows)
|
||||||
- [`result_overflow_mode=break`](../operations/settings/query_complexity/#result-overflow-mode)
|
- [result_overflow_mode=break](../operations/settings/query-complexity/#result-overflow-mode)
|
||||||
- [`max_execution_time=60000`](../operations/settings/query_complexity/#max-execution-time)
|
- [max_execution_time=60000](../operations/settings/query-complexity/#max-execution-time)
|
||||||
|
|
||||||
ClickHouse体验还有如下:
|
ClickHouse体验还有如下:
|
||||||
[ClickHouse管理服务](https://cloud.yandex.com/services/managed-clickhouse)
|
[ClickHouse管理服务](https://cloud.yandex.com/services/managed-clickhouse)
|
||||||
实例托管 [Yandex云](https://cloud.yandex.com/)。
|
实例托管 [Yandex云](https://cloud.yandex.com/)。
|
||||||
更多信息 [云提供商](../commercial/cloud.md)。
|
更多信息 [云提供商](../commercial/cloud.md)。
|
||||||
|
|
||||||
ClickHouse体验平台界面实际上是通过ClickHouse [HTTP API](../interfaces/http.md)接口实现的.
|
## 示例 {#examples}
|
||||||
体验平台后端只是一个ClickHouse集群,没有任何额外的服务器端应用程序。
|
|
||||||
体验平台也同样提供了ClickHouse HTTPS服务端口。
|
|
||||||
|
|
||||||
您可以使用任何HTTP客户端向体验平台进行查询,例如 [curl](https://curl.haxx.se) 或 [wget](https://www.gnu.org/software/wget/),或使用以下方式建立连接 [JDBC](../interfaces/jdbc.md) 或 [ODBC](../interfaces/odbc.md) 驱动。
|
使用`curl`连接Https服务:
|
||||||
有关支持ClickHouse的软件产品的更多信息,请访问 [这里](../interfaces/index.md)。
|
|
||||||
|
|
||||||
| 参数 | 值 |
|
|
||||||
|:---------|:--------------------------------------|
|
|
||||||
| 服务端口 | https://play-api.clickhouse.tech:8443 |
|
|
||||||
| 用户 | `playground` |
|
|
||||||
| 密码 | `clickhouse` |
|
|
||||||
|
|
||||||
请注意,此服务端口需要安全连接。
|
|
||||||
|
|
||||||
示例:
|
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
curl "https://play-api.clickhouse.tech:8443/?query=SELECT+'Play+ClickHouse!';&user=playground&password=clickhouse&database=datasets"
|
curl "https://play-api.clickhouse.tech:8443/?query=SELECT+'Play+ClickHouse\!';&user=playground&password=clickhouse&database=datasets"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
TCP连接示例[CLI](../interfaces/cli.md):
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
clickhouse client --secure -h play-api.clickhouse.tech --port 9440 -u playground --password clickhouse -q "SELECT 'Play ClickHouse\!'"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Implementation Details {#implementation-details}
|
||||||
|
|
||||||
|
ClickHouse体验平台界面实际上是通过ClickHouse [HTTP API](../interfaces/http.md)接口实现的。
|
||||||
|
ClickHouse体验平台是一个ClickHouse集群,没有任何附加的服务器端应用程序。如上所述,ClickHouse的HTTPS和TCP/TLS端点也可以作为体验平台的一部分公开使用, 代理通过[Cloudflare Spectrum](https://www.cloudflare.com/products/cloudflare-spectrum/)增加一层额外的保护和改善连接。
|
||||||
|
|
||||||
|
!!! warning "注意"
|
||||||
|
**强烈不推荐**在任何其他情况下将ClickHouse服务器暴露给公共互联网。确保它只在私有网络上侦听,并由正确配置的防火墙监控。
|
||||||
|
@ -1,71 +1,105 @@
|
|||||||
# 命令行客户端 {#ming-ling-xing-ke-hu-duan}
|
---
|
||||||
|
toc_priority: 17
|
||||||
|
toc_title: 命令行客户端
|
||||||
|
---
|
||||||
|
|
||||||
通过命令行来访问 ClickHouse,您可以使用 `clickhouse-client`
|
# 命令行客户端 {#command-line-client}
|
||||||
|
|
||||||
|
ClickHouse提供了一个原生命令行客户端`clickhouse-client`客户端支持命令行支持的更多信息详见[Configuring](#interfaces_cli_configuration)。
|
||||||
|
|
||||||
|
[安装部署](../getting-started/index.md)后,系统默认会安装`clickhouse-client`(同时它属于`clickhouse-client`安装包中)。
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
$ clickhouse-client
|
$ clickhouse-client
|
||||||
ClickHouse client version 0.0.26176.
|
ClickHouse client version 19.17.1.1579 (official build).
|
||||||
Connecting to localhost:9000.
|
Connecting to localhost:9000 as user default.
|
||||||
Connected to ClickHouse server version 0.0.26176.:)
|
Connected to ClickHouse server version 19.17.1 revision 54428.
|
||||||
|
|
||||||
|
:)
|
||||||
```
|
```
|
||||||
|
|
||||||
该客户端支持命令行参数以及配置文件。查看更多,请看 «[配置](#interfaces_cli_configuration)»
|
不同的客户端和服务器版本彼此兼容,但是一些特性可能在旧客户机中不可用。我们建议使用与服务器应用相同版本的客户端。当你尝试使用旧版本的客户端时,服务器上的`clickhouse-client`会显示如下信息:
|
||||||
|
|
||||||
## 使用方式 {#shi-yong-fang-shi}
|
ClickHouse client version is older than ClickHouse server. It may lack support for new features.
|
||||||
|
|
||||||
这个客户端可以选择使用交互式与非交互式(批量)两种模式。
|
## 使用方式 {#cli_usage}
|
||||||
使用批量模式,要指定 `query` 参数,或者发送数据到 `stdin`(它会检查 `stdin` 是否是 Terminal),或者两种同时使用。
|
|
||||||
它与 HTTP 接口很相似,当使用 `query` 参数发送数据到 `stdin` 时,客户端请求就是一行一行的 `stdin` 输入作为 `query` 的参数。这种方式在大规模的插入请求中非常方便。
|
|
||||||
|
|
||||||
使用这个客户端插入数据的示例:
|
客户端可以在交互和非交互(批处理)模式下使用。要使用批处理模式,请指定`query`参数,或将数据发送到`stdin`(它会验证`stdin`是否是终端),或两者同时进行。与HTTP接口类似,当使用`query`参数并向`stdin`发送数据时,客户端请求就是一行一行的`stdin`输入作为`query`的参数。这种方式在大规模的插入请求中非常方便。
|
||||||
|
|
||||||
|
使用客户端插入数据的示例:
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
echo -ne "1, 'some text', '2016-08-14 00:00:00'\n2, 'some more text', '2016-08-14 00:00:01'" | clickhouse-client --database=test --query="INSERT INTO test FORMAT CSV";
|
$ echo -ne "1, 'some text', '2016-08-14 00:00:00'\n2, 'some more text', '2016-08-14 00:00:01'" | clickhouse-client --database=test --query="INSERT INTO test FORMAT CSV";
|
||||||
|
|
||||||
cat <<_EOF | clickhouse-client --database=test --query="INSERT INTO test FORMAT CSV";
|
$ cat <<_EOF | clickhouse-client --database=test --query="INSERT INTO test FORMAT CSV";
|
||||||
3, 'some text', '2016-08-14 00:00:00'
|
3, 'some text', '2016-08-14 00:00:00'
|
||||||
4, 'some more text', '2016-08-14 00:00:01'
|
4, 'some more text', '2016-08-14 00:00:01'
|
||||||
_EOF
|
_EOF
|
||||||
|
|
||||||
cat file.csv | clickhouse-client --database=test --query="INSERT INTO test FORMAT CSV";
|
$ cat file.csv | clickhouse-client --database=test --query="INSERT INTO test FORMAT CSV";
|
||||||
```
|
```
|
||||||
|
|
||||||
在批量模式中,默认的数据格式是 `TabSeparated` 分隔的。您可以根据查询来灵活设置 FORMAT 格式。
|
在批量模式中,默认的数据格式是`TabSeparated`分隔的。您可以根据查询来灵活设置FORMAT格式。
|
||||||
|
|
||||||
默认情况下,在批量模式中只能执行单个查询。为了从一个 Script 中执行多个查询,可以使用 `--multiquery` 参数。除了 INSERT 请求外,这种方式在任何地方都有用。查询的结果会连续且不含分隔符地输出。
|
默认情况下,在批量模式中只能执行单个查询。为了从一个Script中执行多个查询,可以使用`--multiquery`参数。除了INSERT请求外,这种方式在任何地方都有用。查询的结果会连续且不含分隔符地输出。
|
||||||
同样的,为了执行大规模的查询,您可以为每个查询执行一次 `clickhouse-client`。但注意到每次启动 `clickhouse-client` 程序都需要消耗几十毫秒时间。
|
同样的,为了执行大规模的查询,您可以为每个查询执行一次`clickhouse-client`。但注意到每次启动`clickhouse-client`程序都需要消耗几十毫秒时间。
|
||||||
|
|
||||||
在交互模式下,每条查询过后,你可以直接输入下一条查询命令。
|
在交互模式下,每条查询过后,你可以直接输入下一条查询命令。
|
||||||
|
|
||||||
如果 `multiline` 没有指定(默认没指定):为了执行查询,按下 Enter 即可。查询语句不是必须使用分号结尾。如果需要写一个多行的查询语句,可以在换行之前输入一个反斜杠`\`,然后在您按下 Enter 键后,您就可以输入当前语句的下一行查询了。
|
如果`multiline`没有指定(默认没指定):为了执行查询,按下Enter即可。查询语句不是必须使用分号结尾。如果需要写一个多行的查询语句,可以在换行之前输入一个反斜杠`\`,然后在您按下Enter键后,您就可以输入当前语句的下一行查询了。
|
||||||
|
|
||||||
如果 `multiline` 指定了:为了执行查询,需要以分号结尾并且按下 Enter 键。如果行末没有分号,将认为当前语句并没有输入完而要求继续输入下一行。
|
如果指定了`multiline`:为了执行查询,需要以分号结尾并且按下Enter键。如果行末没有分号,将认为当前语句并没有输入完而要求继续输入下一行。
|
||||||
|
|
||||||
若只运行单个查询,分号后面的所有内容都会被忽略。
|
若只运行单个查询,分号后面的所有内容都会被忽略。
|
||||||
|
|
||||||
您可以指定 `\G` 来替代分号或者在分号后面,这表示 `Vertical` 的格式。在这种格式下,每一个值都会打印在不同的行中,这种方式对于宽表来说很方便。这个不常见的特性是为了兼容 MySQL 命令而加的。
|
您可以指定`\G`来替代分号或者在分号后面,这表示使用`Vertical`的格式。在这种格式下,每一个值都会打印在不同的行中,这种方式对于宽表来说很方便。这个不常见的特性是为了兼容MySQL命令而加的。
|
||||||
|
|
||||||
命令行客户端是基于 `replxx`。换句话说,它可以使用我们熟悉的快捷键方式来操作以及保留历史命令。
|
命令行客户端是基于`replxx`(类似于`readline`)。换句话说,它可以使用我们熟悉的快捷键方式来操作以及保留历史命令。
|
||||||
历史命令会写入在 `~/.clickhouse-client-history` 中。
|
历史命令会写入在`~/.clickhouse-client-history`中。
|
||||||
|
|
||||||
默认情况下,输出的格式是 `PrettyCompact`。您可以通过 FORMAT 设置根据不同查询来修改格式,或者通过在查询末尾指定 `\G` 字符,或通过在命令行中使用 `--format` 或 `--vertical` 参数,或使用客户端的配置文件。
|
默认情况下,输出的格式是`PrettyCompact`。您可以通过FORMAT设置根据不同查询来修改格式,或者通过在查询末尾指定`\G`字符,或通过在命令行中使用`--format`或`--vertical`参数,或使用客户端的配置文件。
|
||||||
|
|
||||||
若要退出客户端,使用 Ctrl+D (或 Ctrl+C),或者输入以下其中一个命令:`exit`, `quit`, `logout`, `учше`, `йгше`, `дщпщге`, `exit;`, `quit;`, `logout;`, `учшеж`, `йгшеж`, `дщпщгеж`, `q`, `й`, `q`, `Q`, `:q`, `й`, `Й`, `Жй`
|
若要退出客户端,使用Ctrl+D(或Ctrl+C),或者输入以下其中一个命令:`exit`, `quit`, `logout`, `учше`, `йгше`, `дщпщге`, `exit;`, `quit;`, `logout;`, `q`, `Q`, `:q`
|
||||||
|
|
||||||
当执行一个查询的时候,客户端会显示:
|
当执行一个查询的时候,客户端会显示:
|
||||||
|
|
||||||
1. 进度, 进度会每秒更新十次 (默认情况下)。 对于很快的查询,进度可能没有时间显示。
|
1. 进度, 进度会每秒更新十次(默认情况下)。对于很快的查询,进度可能没有时间显示。
|
||||||
2. 为了调试会显示解析且格式化后的查询语句。
|
2. 为了调试会显示解析且格式化后的查询语句。
|
||||||
3. 指定格式的输出结果。
|
3. 指定格式的输出结果。
|
||||||
4. 输出结果的行数的行数,经过的时间,以及查询处理的速度。
|
4. 输出结果的行数的行数,经过的时间,以及查询处理的速度。
|
||||||
|
|
||||||
您可以通过 Ctrl+C 来取消一个长时间的查询。然而,您依然需要等待服务端来中止请求。在某个阶段去取消查询是不可能的。如果您不等待并再次按下 Ctrl + C,客户端将会退出。
|
您可以通过Ctrl+C来取消一个长时间的查询。然而,您依然需要等待服务端来中止请求。在某个阶段去取消查询是不可能的。如果您不等待并再次按下Ctrl + C,客户端将会退出。
|
||||||
|
|
||||||
命令行客户端允许通过外部数据 (外部临时表) 来查询。更多相关信息,请参考 «[外部数据查询处理](../engines/table-engines/special/external-data.md)».
|
命令行客户端允许通过外部数据(外部临时表)来查询。更多相关信息,请参考 «[外部数据查询处理](../engines/table-engines/special/external-data.md)».
|
||||||
|
|
||||||
|
### 查询参数 {#cli-queries-with-parameters}
|
||||||
|
|
||||||
|
您可以创建带有参数的查询,并将值从客户端传递给服务器。这允许避免在客户端使用特定的动态值格式化查询。例如:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
$ clickhouse-client --param_parName="[1, 2]" -q "SELECT * FROM table WHERE a = {parName:Array(UInt16)}"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 查询语法 {#cli-queries-with-parameters-syntax}
|
||||||
|
|
||||||
|
像平常一样格式化一个查询,然后把你想要从app参数传递到查询的值用大括号格式化,格式如下:
|
||||||
|
|
||||||
|
``` sql
|
||||||
|
{<name>:<data type>}
|
||||||
|
```
|
||||||
|
|
||||||
|
- `name` — 占位符标识符。在控制台客户端,使用`--param_<name> = value`来指定
|
||||||
|
- `data type` — [数据类型](../sql-reference/data-types/index.md)参数值。例如,一个数据结构`(integer, ('string', integer))`拥有`Tuple(UInt8, Tuple(String, UInt8))`数据类型(你也可以用另一个[integer](../sql-reference/data-types/int-uint.md)类型)。
|
||||||
|
|
||||||
|
#### 示例 {#example}
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
$ clickhouse-client --param_tuple_in_tuple="(10, ('dt', 10))" -q "SELECT * FROM table WHERE val = {tuple_in_tuple:Tuple(UInt8, Tuple(String, UInt8))}"
|
||||||
|
```
|
||||||
|
|
||||||
## 配置 {#interfaces_cli_configuration}
|
## 配置 {#interfaces_cli_configuration}
|
||||||
|
|
||||||
您可以通过以下方式传入参数到 `clickhouse-client` 中 (所有的参数都有默认值):
|
您可以通过以下方式传入参数到`clickhouse-client`中(所有的参数都有默认值):
|
||||||
|
|
||||||
- 通过命令行
|
- 通过命令行
|
||||||
|
|
||||||
@ -75,29 +109,32 @@ cat file.csv | clickhouse-client --database=test --query="INSERT INTO test FORMA
|
|||||||
|
|
||||||
配置文件的配置会覆盖默认值
|
配置文件的配置会覆盖默认值
|
||||||
|
|
||||||
### 命令行参数 {#ming-ling-xing-can-shu}
|
### 命令行参数 {#command-line-options}
|
||||||
|
|
||||||
- `--host, -h` -– 服务端的 host 名称, 默认是 ‘localhost’。 您可以选择使用 host 名称或者 IPv4 或 IPv6 地址。
|
- `--host, -h` -– 服务端的host名称, 默认是`localhost`。您可以选择使用host名称或者IPv4或IPv6地址。
|
||||||
- `--port` – 连接的端口,默认值: 9000。注意 HTTP 接口以及 TCP 原生接口是使用不同端口的。
|
- `--port` – 连接的端口,默认值:9000。注意HTTP接口以及TCP原生接口使用的是不同端口。
|
||||||
- `--user, -u` – 用户名。 默认值: default。
|
- `--user, -u` – 用户名。 默认值:`default`。
|
||||||
- `--password` – 密码。 默认值: 空字符串。
|
- `--password` – 密码。 默认值:空字符串。
|
||||||
- `--query, -q` – 非交互模式下的查询语句.
|
- `--query, -q` – 使用非交互模式查询。
|
||||||
- `--database, -d` – 默认当前操作的数据库. 默认值: 服务端默认的配置 (默认是 `default`)。
|
- `--database, -d` – 默认当前操作的数据库. 默认值:服务端默认的配置(默认是`default`)。
|
||||||
- `--multiline, -m` – 如果指定,允许多行语句查询(Enter 仅代表换行,不代表查询语句完结)。
|
- `--multiline, -m` – 如果指定,允许多行语句查询(Enter仅代表换行,不代表查询语句完结)。
|
||||||
- `--multiquery, -n` – 如果指定, 允许处理用逗号分隔的多个查询,只在非交互模式下生效。
|
- `--multiquery, -n` – 如果指定, 允许处理用`;`号分隔的多个查询,只在非交互模式下生效。
|
||||||
- `--format, -f` – 使用指定的默认格式输出结果。
|
- `--format, -f` – 使用指定的默认格式输出结果。
|
||||||
- `--vertical, -E` – 如果指定,默认情况下使用垂直格式输出结果。这与 ‘–format=Vertical’ 相同。在这种格式中,每个值都在单独的行上打印,这种方式对显示宽表很有帮助。
|
- `--vertical, -E` – 如果指定,默认情况下使用垂直格式输出结果。这与`–format=Vertical`相同。在这种格式中,每个值都在单独的行上打印,这种方式对显示宽表很有帮助。
|
||||||
- `--time, -t` – 如果指定,非交互模式下会打印查询执行的时间到 ‘stderr’ 中。
|
- `--time, -t` – 如果指定,非交互模式下会打印查询执行的时间到`stderr`中。
|
||||||
- `--stacktrace` – 如果指定,如果出现异常,会打印堆栈跟踪信息。
|
- `--stacktrace` – 如果指定,如果出现异常,会打印堆栈跟踪信息。
|
||||||
- `--config-file` – 配置文件的名称。
|
- `--config-file` – 配置文件的名称。
|
||||||
|
- `--secure` – 如果指定,将通过安全连接连接到服务器。
|
||||||
|
- `--history_file` — 存放命令历史的文件的路径。
|
||||||
|
- `--param_<name>` — 查询参数配置[查询参数](#cli-queries-with-parameters).
|
||||||
|
|
||||||
### 配置文件 {#pei-zhi-wen-jian}
|
### 配置文件 {#configuration_files}
|
||||||
|
|
||||||
`clickhouse-client` 使用一下第一个存在的文件:
|
`clickhouse-client`使用以下第一个配置文件:
|
||||||
|
|
||||||
- 通过 `--config-file` 参数指定的文件.
|
- 通过`--config-file`参数指定。
|
||||||
- `./clickhouse-client.xml`
|
- `./clickhouse-client.xml`
|
||||||
- `\~/.clickhouse-client/config.xml`
|
- `~/.clickhouse-client/config.xml`
|
||||||
- `/etc/clickhouse-client/config.xml`
|
- `/etc/clickhouse-client/config.xml`
|
||||||
|
|
||||||
配置文件示例:
|
配置文件示例:
|
||||||
@ -106,6 +143,7 @@ cat file.csv | clickhouse-client --database=test --query="INSERT INTO test FORMA
|
|||||||
<config>
|
<config>
|
||||||
<user>username</user>
|
<user>username</user>
|
||||||
<password>password</password>
|
<password>password</password>
|
||||||
|
<secure>False</secure>
|
||||||
</config>
|
</config>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
# C ++客户端库 {#c-ke-hu-duan-ku}
|
---
|
||||||
|
toc_priority: 24
|
||||||
|
toc_title: C++客户端库
|
||||||
|
---
|
||||||
|
|
||||||
请参阅以下网站的自述文件[ツ暗ェツ氾环催ツ団](https://github.com/ClickHouse/clickhouse-cpp)资料库。
|
# C++客户端库 {#c-client-library}
|
||||||
|
|
||||||
|
请参考仓库的描述文件[clickhouse-cpp](https://github.com/ClickHouse/clickhouse-cpp)。
|
||||||
|
|
||||||
[原始文章](https://clickhouse.tech/docs/zh/interfaces/cpp/) <!--hide-->
|
[原始文章](https://clickhouse.tech/docs/zh/interfaces/cpp/) <!--hide-->
|
||||||
|
@ -1,23 +1,31 @@
|
|||||||
# HTTP 客户端 {#http-ke-hu-duan}
|
---
|
||||||
|
toc_priority: 19
|
||||||
|
toc_title: HTTP客户端
|
||||||
|
---
|
||||||
|
|
||||||
HTTP 接口可以让你通过任何平台和编程语言来使用 ClickHouse。我们用 Java 和 Perl 以及 shell 脚本来访问它。在其他的部门中,HTTP 接口会用在 Perl,Python 以及 Go 中。HTTP 接口比 TCP 原生接口更为局限,但是却有更好的兼容性。
|
# HTTP客户端 {#http-interface}
|
||||||
|
|
||||||
默认情况下,clickhouse-server 会在端口 8123 上监控 HTTP 请求(这可以在配置中修改)。
|
HTTP接口允许您在任何编程语言的任何平台上使用ClickHouse。我们使用它在Java和Perl以及shell脚本中工作。在其他部门中,HTTP接口用于Perl、Python和Go。HTTP接口比原生接口受到更多的限制,但它具有更好的兼容性。
|
||||||
如果你发送了一个不带参数的 GET 请求,它会返回一个字符串 «Ok.»(结尾有换行)。可以将它用在健康检查脚本中。
|
|
||||||
|
默认情况下,`clickhouse-server`会在`8123`端口上监控HTTP请求(这可以在配置中修改)。
|
||||||
|
|
||||||
|
如果你发送了一个未携带任何参数的`GET /`请求,它会返回一个字符串 «Ok.»(结尾有换行)。可以将它用在健康检查脚本中。
|
||||||
|
|
||||||
|
如果你发送了一个未携带任何参数的`GET /`请求,它返回响应码200和`OK`字符串定义,可在[Http服务响应配置](../operations/server-configuration-parameters/settings.md#server_configuration_parameters-http_server_default_response)定义(在末尾添加换行)
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
$ curl 'http://localhost:8123/'
|
$ curl 'http://localhost:8123/'
|
||||||
Ok.
|
Ok.
|
||||||
```
|
```
|
||||||
|
|
||||||
通过 URL 中的 `query` 参数来发送请求,或者发送 POST 请求,或者将查询的开头部分放在 URL 的 `query` 参数中,其他部分放在 POST 中(我们会在后面解释为什么这样做是有必要的)。URL 的大小会限制在 16 KB,所以发送大型查询时要时刻记住这点。
|
通过URL中的 `query` 参数来发送请求,或者发送POST请求,或者将查询的开头部分放在URL的`query`参数中,其他部分放在POST中(我们会在后面解释为什么这样做是有必要的)。URL的大小会限制在16KB,所以发送大型查询时要时刻记住这点。
|
||||||
|
|
||||||
如果请求成功,将会收到 200 的响应状态码和响应主体中的结果。
|
如果请求成功,将会收到200的响应状态码和响应主体中的结果。
|
||||||
如果发生了某个异常,将会收到 500 的响应状态码和响应主体中的异常描述信息。
|
如果发生了某个异常,将会收到500的响应状态码和响应主体中的异常描述信息。
|
||||||
|
|
||||||
当使用 GET 方法请求时,`readonly` 会被设置。换句话说,若要作修改数据的查询,只能发送 POST 方法的请求。可以将查询通过 POST 主体发送,也可以通过 URL 参数发送。
|
当使用GET方法请求时,`readonly`会被设置。换句话说,若要作修改数据的查询,只能发送POST方法的请求。可以将查询通过POST主体发送,也可以通过URL参数发送。
|
||||||
|
|
||||||
例:
|
示例:
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
$ curl 'http://localhost:8123/?query=SELECT%201'
|
$ curl 'http://localhost:8123/?query=SELECT%201'
|
||||||
@ -26,13 +34,14 @@ $ curl 'http://localhost:8123/?query=SELECT%201'
|
|||||||
$ wget -nv -O- 'http://localhost:8123/?query=SELECT 1'
|
$ wget -nv -O- 'http://localhost:8123/?query=SELECT 1'
|
||||||
1
|
1
|
||||||
|
|
||||||
$ GET 'http://localhost:8123/?query=SELECT 1'
|
|
||||||
1
|
|
||||||
|
|
||||||
$ echo -ne 'GET /?query=SELECT%201 HTTP/1.0\r\n\r\n' | nc localhost 8123
|
$ echo -ne 'GET /?query=SELECT%201 HTTP/1.0\r\n\r\n' | nc localhost 8123
|
||||||
HTTP/1.0 200 OK
|
HTTP/1.0 200 OK
|
||||||
|
Date: Wed, 27 Nov 2019 10:30:18 GMT
|
||||||
Connection: Close
|
Connection: Close
|
||||||
Date: Fri, 16 Nov 2012 19:21:50 GMT
|
Content-Type: text/tab-separated-values; charset=UTF-8
|
||||||
|
X-ClickHouse-Server-Display-Name: clickhouse.ru-central1.internal
|
||||||
|
X-ClickHouse-Query-Id: 5abe861c-239c-467f-b955-8a201abb8b7f
|
||||||
|
X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0"}
|
||||||
|
|
||||||
1
|
1
|
||||||
```
|
```
|
||||||
@ -50,7 +59,22 @@ $ echo '1' | curl 'http://localhost:8123/?query=SELECT' --data-binary @-
|
|||||||
1
|
1
|
||||||
```
|
```
|
||||||
|
|
||||||
如果一部分请求是通过参数发送的,另外一部分通过 POST 主体发送,两部分查询之间会一行空行插入。
|
如您所见,curl有些不方便,因为空格必须进行URL转义。
|
||||||
|
尽管wget本身会对所有内容进行转义,但我们不推荐使用它,因为在使用keepalive和传输编码chunked时,它在HTTP 1.1上不能很好地工作。
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
$ echo 'SELECT 1' | curl 'http://localhost:8123/' --data-binary @-
|
||||||
|
1
|
||||||
|
|
||||||
|
$ echo 'SELECT 1' | curl 'http://localhost:8123/?query=' --data-binary @-
|
||||||
|
1
|
||||||
|
|
||||||
|
$ echo '1' | curl 'http://localhost:8123/?query=SELECT' --data-binary @-
|
||||||
|
1
|
||||||
|
```
|
||||||
|
|
||||||
|
如果部分查询是在参数中发送的,部分是在POST中发送的,则在这两个数据部分之间插入换行。
|
||||||
|
|
||||||
错误示例:
|
错误示例:
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
@ -60,8 +84,11 @@ ECT 1
|
|||||||
, expected One of: SHOW TABLES, SHOW DATABASES, SELECT, INSERT, CREATE, ATTACH, RENAME, DROP, DETACH, USE, SET, OPTIMIZE., e.what() = DB::Exception
|
, expected One of: SHOW TABLES, SHOW DATABASES, SELECT, INSERT, CREATE, ATTACH, RENAME, DROP, DETACH, USE, SET, OPTIMIZE., e.what() = DB::Exception
|
||||||
```
|
```
|
||||||
|
|
||||||
默认情况下,返回的数据是 TabSeparated 格式的,更多信息,见 «\[数据格式\]» 部分。
|
默认情况下,返回的数据是`TabSeparated`格式的,更多信息,见[Formats](../interfaces/formats/)部分。
|
||||||
可以使用 FORMAT 设置查询来请求不同格式。
|
|
||||||
|
您可以使用查询的FORMAT子句来设置其他格式。
|
||||||
|
|
||||||
|
另外,还可以使用`default_format`URL参数或`X-ClickHouse-Format`头来指定TabSeparated之外的默认格式。
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
$ echo 'SELECT 1 FORMAT Pretty' | curl 'http://localhost:8123/?' --data-binary @-
|
$ echo 'SELECT 1 FORMAT Pretty' | curl 'http://localhost:8123/?' --data-binary @-
|
||||||
@ -72,42 +99,42 @@ $ echo 'SELECT 1 FORMAT Pretty' | curl 'http://localhost:8123/?' --data-binary @
|
|||||||
└───┘
|
└───┘
|
||||||
```
|
```
|
||||||
|
|
||||||
INSERT 必须通过 POST 方法来插入数据。这种情况下,你可以将查询的开头部分放在 URL 参数中,然后用 POST 主体传入插入的数据。插入的数据可以是,举个例子,从 MySQL 导出的以 tab 分割的数据。在这种方式中,INSERT 查询取代了 LOAD DATA LOCAL INFILE from MySQL。
|
INSERT必须通过POST方法来插入数据。在这种情况下,您可以在URL参数中编写查询的开始部分,并使用POST传递要插入的数据。例如,要插入的数据可以是来自MySQL的一个以tab分隔的存储。通过这种方式,INSERT查询替换了从MySQL查询的LOAD DATA LOCAL INFILE。
|
||||||
|
|
||||||
示例: 创建一个表:
|
示例: 创建一个表:
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
echo 'CREATE TABLE t (a UInt8) ENGINE = Memory' | POST 'http://localhost:8123/'
|
$ echo 'CREATE TABLE t (a UInt8) ENGINE = Memory' | curl 'http://localhost:8123/' --data-binary @-
|
||||||
```
|
```
|
||||||
|
|
||||||
使用类似 INSERT 的查询来插入数据:
|
使用类似INSERT的查询来插入数据:
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
echo 'INSERT INTO t VALUES (1),(2),(3)' | POST 'http://localhost:8123/'
|
$ echo 'INSERT INTO t VALUES (1),(2),(3)' | curl 'http://localhost:8123/' --data-binary @-
|
||||||
```
|
```
|
||||||
|
|
||||||
数据可以从查询中单独发送:
|
数据可以从查询中单独发送:
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
echo '(4),(5),(6)' | POST 'http://localhost:8123/?query=INSERT INTO t VALUES'
|
$ echo '(4),(5),(6)' | curl 'http://localhost:8123/?query=INSERT%20INTO%20t%20VALUES' --data-binary @-
|
||||||
```
|
```
|
||||||
|
|
||||||
可以指定任何数据格式。值的格式和写入表 `t` 的值的格式相同:
|
您可以指定任何数据格式。`Values`格式与将INSERT写入`t`值时使用的格式相同:
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
echo '(7),(8),(9)' | POST 'http://localhost:8123/?query=INSERT INTO t FORMAT Values'
|
$ echo '(7),(8),(9)' | curl 'http://localhost:8123/?query=INSERT%20INTO%20t%20FORMAT%20Values' --data-binary @-
|
||||||
```
|
```
|
||||||
|
|
||||||
若要插入 tab 分割的数据,需要指定对应的格式:
|
若要插入tab分割的数据,需要指定对应的格式:
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
echo -ne '10\n11\n12\n' | POST 'http://localhost:8123/?query=INSERT INTO t FORMAT TabSeparated'
|
$ echo -ne '10\n11\n12\n' | curl 'http://localhost:8123/?query=INSERT%20INTO%20t%20FORMAT%20TabSeparated' --data-binary @-
|
||||||
```
|
```
|
||||||
|
|
||||||
从表中读取内容。由于查询处理是并行的,数据以随机顺序输出。
|
从表中读取内容。由于查询处理是并行的,数据以随机顺序输出。
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
$ GET 'http://localhost:8123/?query=SELECT a FROM t'
|
$ curl 'http://localhost:8123/?query=SELECT%20a%20FROM%20t'
|
||||||
7
|
7
|
||||||
8
|
8
|
||||||
9
|
9
|
||||||
@ -122,22 +149,37 @@ $ GET 'http://localhost:8123/?query=SELECT a FROM t'
|
|||||||
6
|
6
|
||||||
```
|
```
|
||||||
|
|
||||||
删除表。
|
删除表:
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
POST 'http://localhost:8123/?query=DROP TABLE t'
|
$ echo 'DROP TABLE t' | curl 'http://localhost:8123/' --data-binary @-
|
||||||
```
|
```
|
||||||
|
|
||||||
成功请求后并不会返回数据,返回一个空的响应体。
|
成功请求后并不会返回数据,返回一个空的响应体。
|
||||||
|
|
||||||
可以通过压缩来传输数据。压缩的数据没有一个标准的格式,但你需要指定一个压缩程序来使用它(sudo apt-get install compressor-metrika-yandex)。
|
在传输数据时,可以使用ClickHouse内部压缩格式。压缩的数据具有非标准格式,您需要使用特殊的`clickhouse-compressor`程序来处理它(它是与`clickhouse-client`包一起安装的)。为了提高数据插入的效率,您可以通过使用[http_native_compression_disable_checksumming_on_decompress](../operations/settings/settings.md#settings-http_native_compression_disable_checksumming_on_decompress)设置禁用服务器端校验。
|
||||||
|
|
||||||
如果在 URL 中指定了 `compress=1` ,服务会返回压缩的数据。
|
如果在URL中指定了`compress=1`,服务会返回压缩的数据。
|
||||||
如果在 URL 中指定了 `decompress=1` ,服务会解压通过 POST 方法发送的数据。
|
如果在URL中指定了`decompress=1`,服务会解压通过POST方法发送的数据。
|
||||||
|
|
||||||
可以通过为每份数据进行立即压缩来减少大规模数据传输中的网络压力。
|
您也可以选择使用[HTTP compression](https://en.wikipedia.org/wiki/HTTP_compression)。发送一个压缩的POST请求,附加请求头`Content-Encoding: compression_method`。为了使ClickHouse响应,您必须附加`Accept-Encoding: compression_method`。ClickHouse支持`gzip`,`br`和`deflate` [compression methods](https://en.wikipedia.org/wiki/HTTP_compression#Content-Encoding_tokens)。要启用HTTP压缩,必须使用ClickHouse[启用Http压缩](../operations/settings/settings.md#settings-enable_http_compression)配置。您可以在[Http zlib压缩级别](#settings-http_zlib_compression_level)设置中为所有压缩方法配置数据压缩级别。
|
||||||
|
|
||||||
可以指定 ‘database’ 参数来指定默认的数据库。
|
您可以使用它在传输大量数据时减少网络流量,或者创建立即压缩的转储。
|
||||||
|
|
||||||
|
通过压缩发送数据的例子:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
#Sending data to the server:
|
||||||
|
$ curl -vsS "http://localhost:8123/?enable_http_compression=1" -d 'SELECT number FROM system.numbers LIMIT 10' -H 'Accept-Encoding: gzip'
|
||||||
|
|
||||||
|
#Sending data to the client:
|
||||||
|
$ echo "SELECT 1" | gzip -c | curl -sS --data-binary @- -H 'Content-Encoding: gzip' 'http://localhost:8123/'
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! note "警告"
|
||||||
|
一些HTTP客户端可能会在默认情况下从服务器解压数据(使用`gzip`和`deflate`),即使您未正确地使用了压缩设置,您也可能会得到解压数据。
|
||||||
|
|
||||||
|
您可以使用`database`URL参数或`X-ClickHouse-Database`头来指定默认数据库。
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
$ echo 'SELECT number FROM numbers LIMIT 10' | curl 'http://localhost:8123/?database=system' --data-binary @-
|
$ echo 'SELECT number FROM numbers LIMIT 10' | curl 'http://localhost:8123/?database=system' --data-binary @-
|
||||||
@ -153,30 +195,38 @@ $ echo 'SELECT number FROM numbers LIMIT 10' | curl 'http://localhost:8123/?data
|
|||||||
9
|
9
|
||||||
```
|
```
|
||||||
|
|
||||||
默认情况下,默认数据库会在服务的配置中注册,默认是 `default`。或者,也可以在表名之前使用一个点来指定数据库。
|
默认情况下,在服务器设置中注册的数据库被用作默认数据库。默认情况下,它是名为`default`的数据库。或者,您可以始终在表名之前使用点来指定数据库。
|
||||||
|
|
||||||
用户名密码可以通过以下两种方式指定:
|
用户名和密码可以通过以下三种方式指定:
|
||||||
|
|
||||||
1. 通过 HTTP Basic Authentication。示例:
|
1. 通过HTTP Basic Authentication。示例:
|
||||||
|
|
||||||
<!-- -->
|
<!-- -->
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
echo 'SELECT 1' | curl 'http://user:password@localhost:8123/' -d @-
|
$ echo 'SELECT 1' | curl 'http://user:password@localhost:8123/' -d @-
|
||||||
```
|
```
|
||||||
|
|
||||||
1. 通过 URL 参数 中的 ‘user’ 和 ‘password’。示例:
|
1. 通过URL参数中的`user`和`password`。示例:
|
||||||
|
|
||||||
<!-- -->
|
<!-- -->
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
echo 'SELECT 1' | curl 'http://localhost:8123/?user=user&password=password' -d @-
|
$ echo 'SELECT 1' | curl 'http://localhost:8123/?user=user&password=password' -d @-
|
||||||
```
|
```
|
||||||
|
|
||||||
如果用户名没有指定,默认的用户是 `default`。如果密码没有指定,默认会使用空密码。
|
1. 使用`X-ClickHouse-User`或`X-ClickHouse-Key`头指定,示例:
|
||||||
可以使用 URL 参数指定配置或者设置整个配置文件来处理单个查询。示例:`http://localhost:8123/?profile=web&max_rows_to_read=1000000000&query=SELECT+1`
|
|
||||||
|
|
||||||
更多信息,参见 «[设置](../operations/settings/index.md#settings)» 部分。
|
<!-- -->
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
$ echo 'SELECT 1' | curl -H 'X-ClickHouse-User: user' -H 'X-ClickHouse-Key: password' 'http://localhost:8123/' -d @-
|
||||||
|
```
|
||||||
|
|
||||||
|
如果未指定用户名,则使用`default`。如果未指定密码,则使用空密码。
|
||||||
|
您还可以使用URL参数来指定处理单个查询或整个设置配置文件的任何设置。例子:`http://localhost:8123/?profile=web&max_rows_to_read=1000000000&query=SELECT+1`
|
||||||
|
|
||||||
|
更多信息,详见[设置](../operations/settings/index.md#settings)部分。
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
$ echo 'SELECT number FROM system.numbers LIMIT 10' | curl 'http://localhost:8123/?' --data-binary @-
|
$ echo 'SELECT number FROM system.numbers LIMIT 10' | curl 'http://localhost:8123/?' --data-binary @-
|
||||||
@ -192,30 +242,386 @@ $ echo 'SELECT number FROM system.numbers LIMIT 10' | curl 'http://localhost:812
|
|||||||
9
|
9
|
||||||
```
|
```
|
||||||
|
|
||||||
更多关于其他参数的信息,参见 «[设置](../operations/settings/index.md#settings)» 部分。
|
有关其他参数的信息,请参考`SET`一节。
|
||||||
|
|
||||||
相比起 TCP 原生接口,HTTP 接口不支持会话和会话设置的概念,不允许中止查询(准确地说,只在少数情况下允许),不显示查询处理的进展。执行解析和数据格式化都是在服务端处理,网络上会比 TCP 原生接口更低效。
|
类似地,您可以在HTTP协议中使用ClickHouse会话。为此,需要向请求添加`session_id`GET参数。您可以使用任何字符串作为会话ID。默认情况下,会话在60秒不活动后终止。要更改此超时配置,请修改服务器配置中的`default_session_timeout`设置,或向请求添加`session_timeout`GET参数。要检查会话状态,使用`session_check=1`参数。一次只能在单个会话中执行一个查询。
|
||||||
|
|
||||||
可选的 `query_id` 参数可能当做 query ID 传入(或者任何字符串)。更多信息,参见 «[设置 replace_running_query](../operations/settings/settings.md)» 部分。
|
您可以在`X-ClickHouse-Progress`响应头中收到查询进度的信息。为此,启用[Http Header携带进度](../operations/settings/settings.md#settings-send_progress_in_http_headers)。示例:
|
||||||
|
|
||||||
可选的 `quota_key` 参数可能当做 quota key 传入(或者任何字符串)。更多信息,参见 «[配额](../operations/quotas.md#quotas)» 部分。
|
``` text
|
||||||
|
X-ClickHouse-Progress: {"read_rows":"2752512","read_bytes":"240570816","total_rows_to_read":"8880128"}
|
||||||
|
X-ClickHouse-Progress: {"read_rows":"5439488","read_bytes":"482285394","total_rows_to_read":"8880128"}
|
||||||
|
X-ClickHouse-Progress: {"read_rows":"8783786","read_bytes":"819092887","total_rows_to_read":"8880128"}
|
||||||
|
```
|
||||||
|
|
||||||
HTTP 接口允许传入额外的数据(外部临时表)来查询。更多信息,参见 «[外部数据查询处理](../engines/table-engines/special/external-data.md)» 部分。
|
显示字段信息:
|
||||||
|
|
||||||
## 响应缓冲 {#xiang-ying-huan-chong}
|
- `read_rows` — 读取的行数。
|
||||||
|
- `read_bytes` — 读取的数据字节数。
|
||||||
|
- `total_rows_to_read` — 读取的数据总行数。
|
||||||
|
- `written_rows` — 写入数据行数。
|
||||||
|
- `written_bytes` — 写入数据字节数。
|
||||||
|
|
||||||
可以在服务器端启用响应缓冲。提供了 `buffer_size` 和 `wait_end_of_query` 两个URL 参数来达此目的。
|
如果HTTP连接丢失,运行的请求不会自动停止。解析和数据格式化是在服务器端执行的,使用Http连接可能无效。
|
||||||
|
|
||||||
`buffer_size` 决定了查询结果要在服务内存中缓冲多少个字节数据. 如果响应体比这个阈值大,缓冲区会写入到 HTTP 管道,剩下的数据也直接发到 HTTP 管道中。
|
可选的`query_id`参数可能当做query ID传入(或者任何字符串)。更多信息,详见[replace_running_query](../operations/settings/settings.md)部分。
|
||||||
|
|
||||||
为了确保整个响应体被缓冲,可以设置 `wait_end_of_query=1`。这种情况下,存入内存的数据会被缓冲到服务端的一个临时文件中。
|
可选的`quota_key`参数可能当做quota key传入(或者任何字符串)。更多信息,详见[Quotas](../operations/quotas.md#quotas)部分。
|
||||||
|
|
||||||
|
HTTP接口允许传入额外的数据(外部临时表)来查询。更多信息,详见[外部数据查询处理](../engines/table-engines/special/external-data.md)部分。
|
||||||
|
|
||||||
|
## 响应缓冲 {#response-buffering}
|
||||||
|
|
||||||
|
可以在服务器端启用响应缓冲。提供了`buffer_size`和`wait_end_of_query`两个URL参数来达此目的。
|
||||||
|
|
||||||
|
`buffer_size`决定了查询结果要在服务内存中缓冲多少个字节数据. 如果响应体比这个阈值大,缓冲区会写入到HTTP管道,剩下的数据也直接发到HTTP管道中。
|
||||||
|
|
||||||
|
为了确保整个响应体被缓冲,可以设置`wait_end_of_query=1`。这种情况下,存入内存的数据会被缓冲到服务端的一个临时文件中。
|
||||||
|
|
||||||
示例:
|
示例:
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
curl -sS 'http://localhost:8123/?max_result_bytes=4000000&buffer_size=3000000&wait_end_of_query=1' -d 'SELECT toUInt8(number) FROM system.numbers LIMIT 9000000 FORMAT RowBinary'
|
$ curl -sS 'http://localhost:8123/?max_result_bytes=4000000&buffer_size=3000000&wait_end_of_query=1' -d 'SELECT toUInt8(number) FROM system.numbers LIMIT 9000000 FORMAT RowBinary'
|
||||||
```
|
```
|
||||||
|
|
||||||
查询请求响应状态码和 HTTP 头被发送到客户端后,若发生查询处理出错,使用缓冲区可以避免这种情况的发生。在这种情况下,响应主体的结尾会写入一条错误消息,而在客户端,只能在解析阶段检测到该错误。
|
查询请求响应状态码和HTTP头被发送到客户端后,若发生查询处理出错,使用缓冲区可以避免这种情况的发生。在这种情况下,响应主体的结尾会写入一条错误消息,而在客户端,只能在解析阶段检测到该错误。
|
||||||
|
|
||||||
|
### 查询参数 {#cli-queries-with-parameters}
|
||||||
|
|
||||||
|
您可以使用参数创建查询,并通过相应的HTTP请求参数为它们传递值。有关更多信息,请参见[CLI查询参数](../interfaces/cli.md#cli-queries-with-parameters)。
|
||||||
|
|
||||||
|
### 示例 {#example}
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
$ curl -sS "<address>?param_id=2¶m_phrase=test" -d "SELECT * FROM table WHERE int_column = {id:UInt8} and string_column = {phrase:String}"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 特定的HTTP接口 {#predefined_http_interface}
|
||||||
|
|
||||||
|
ClickHouse通过HTTP接口支持特定的查询。例如,您可以如下所示向表写入数据:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
$ echo '(4),(5),(6)' | curl 'http://localhost:8123/?query=INSERT%20INTO%20t%20VALUES' --data-binary @-
|
||||||
|
```
|
||||||
|
|
||||||
|
ClickHouse还支持预定义的HTTP接口,可以帮助您更容易与第三方工具集成,如[Prometheus Exporter](https://github.com/percona-lab/clickhouse_exporter).
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
- 首先,将此部分添加到服务器配置文件中:
|
||||||
|
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
``` xml
|
||||||
|
<http_handlers>
|
||||||
|
<rule>
|
||||||
|
<url>/predefined_query</url>
|
||||||
|
<methods>POST,GET</methods>
|
||||||
|
<handler>
|
||||||
|
<type>predefined_query_handler</type>
|
||||||
|
<query>SELECT * FROM system.metrics LIMIT 5 FORMAT Template SETTINGS format_template_resultset = 'prometheus_template_output_format_resultset', format_template_row = 'prometheus_template_output_format_row', format_template_rows_between_delimiter = '\n'</query>
|
||||||
|
</handler>
|
||||||
|
</rule>
|
||||||
|
<rule>...</rule>
|
||||||
|
<rule>...</rule>
|
||||||
|
</http_handlers>
|
||||||
|
```
|
||||||
|
|
||||||
|
- 请求Prometheus格式的URL以获取数据:
|
||||||
|
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
$ curl -v 'http://localhost:8123/predefined_query'
|
||||||
|
* Trying ::1...
|
||||||
|
* Connected to localhost (::1) port 8123 (#0)
|
||||||
|
> GET /predefined_query HTTP/1.1
|
||||||
|
> Host: localhost:8123
|
||||||
|
> User-Agent: curl/7.47.0
|
||||||
|
> Accept: */*
|
||||||
|
>
|
||||||
|
< HTTP/1.1 200 OK
|
||||||
|
< Date: Tue, 28 Apr 2020 08:52:56 GMT
|
||||||
|
< Connection: Keep-Alive
|
||||||
|
< Content-Type: text/plain; charset=UTF-8
|
||||||
|
< X-ClickHouse-Server-Display-Name: i-mloy5trc
|
||||||
|
< Transfer-Encoding: chunked
|
||||||
|
< X-ClickHouse-Query-Id: 96fe0052-01e6-43ce-b12a-6b7370de6e8a
|
||||||
|
< X-ClickHouse-Format: Template
|
||||||
|
< X-ClickHouse-Timezone: Asia/Shanghai
|
||||||
|
< Keep-Alive: timeout=3
|
||||||
|
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0"}
|
||||||
|
<
|
||||||
|
# HELP "Query" "Number of executing queries"
|
||||||
|
# TYPE "Query" counter
|
||||||
|
"Query" 1
|
||||||
|
|
||||||
|
# HELP "Merge" "Number of executing background merges"
|
||||||
|
# TYPE "Merge" counter
|
||||||
|
"Merge" 0
|
||||||
|
|
||||||
|
# HELP "PartMutation" "Number of mutations (ALTER DELETE/UPDATE)"
|
||||||
|
# TYPE "PartMutation" counter
|
||||||
|
"PartMutation" 0
|
||||||
|
|
||||||
|
# HELP "ReplicatedFetch" "Number of data parts being fetched from replica"
|
||||||
|
# TYPE "ReplicatedFetch" counter
|
||||||
|
"ReplicatedFetch" 0
|
||||||
|
|
||||||
|
# HELP "ReplicatedSend" "Number of data parts being sent to replicas"
|
||||||
|
# TYPE "ReplicatedSend" counter
|
||||||
|
"ReplicatedSend" 0
|
||||||
|
|
||||||
|
* Connection #0 to host localhost left intact
|
||||||
|
|
||||||
|
* Connection #0 to host localhost left intact
|
||||||
|
```
|
||||||
|
|
||||||
|
正如您从示例中看到的,如果在`config.xml`文件中配置了`http_handlers`,并且`http_handlers`可以包含许多`规则`。ClickHouse将把接收到的HTTP请求与`rule`中的预定义类型进行匹配,第一个匹配的将运行处理程序。如果匹配成功,ClickHouse将执行相应的预定义查询。
|
||||||
|
|
||||||
|
现在`rule`可以配置`method`, `header`, `url`, `handler`:
|
||||||
|
- `method` 负责匹配HTTP请求的方法部分。 `method`完全符合HTTP协议中[method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods)的定义。这是一个可选的配置。如果它没有在配置文件中定义,那么它与HTTP请求的方法部分不匹配。
|
||||||
|
|
||||||
|
- `url` 负责匹配HTTP请求的URL部分。它匹配[RE2](https://github.com/google/re2)正则表达式。这是一个可选的配置。如果配置文件中没有定义它,则它与HTTP请求的URL部分不匹配。
|
||||||
|
|
||||||
|
- `headers` 负责匹配HTTP请求的头部分。它与RE2的正则表达式兼容。这是一个可选的配置。如果它没有在配置文件中定义,那么它与HTTP请求的头部分不匹配。
|
||||||
|
|
||||||
|
- `handler` 包含主要的处理部分。现在`handler`可以配置`type`, `status`, `content_type`, `response_content`, `query`, `query_param_name`。
|
||||||
|
`type` 目前支持三种类型:[特定查询](#predefined_query_handler), [动态查询](#dynamic_query_handler), [static](#static).
|
||||||
|
|
||||||
|
- `query` — 使用`predefined_query_handler`类型,在调用处理程序时执行查询。
|
||||||
|
|
||||||
|
- `query_param_name` — 与`dynamic_query_handler`类型一起使用,提取并执行HTTP请求参数中与`query_param_name`值对应的值。
|
||||||
|
|
||||||
|
- `status` — 与`static`类型一起使用,响应状态代码。
|
||||||
|
|
||||||
|
- `content_type` — 与`static`类型一起使用,响应信息[content-type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type)。
|
||||||
|
|
||||||
|
- `response_content` — 与`static`类型一起使用,响应发送给客户端的内容,当使用前缀`file://`或`config://`时,从发送给客户端的文件或配置中查找内容。
|
||||||
|
|
||||||
|
接下来是不同`type`的配置方法。
|
||||||
|
|
||||||
|
### 特定查询 {#predefined_query_handler}
|
||||||
|
|
||||||
|
`predefined_query_handler` 支持设置`Settings`和`query_params`参数。您可以将`query`配置为`predefined_query_handler`类型。
|
||||||
|
|
||||||
|
`query` 是一个预定义的`predefined_query_handler`查询,它由ClickHouse在匹配HTTP请求并返回查询结果时执行。这是一个必须的配置。
|
||||||
|
|
||||||
|
以下是定义的[max_threads](../operations/settings/settings.md#settings-max_threads)和`max_alter_threads`设置, 然后查询系统表以检查这些设置是否设置成功。
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
``` xml
|
||||||
|
<http_handlers>
|
||||||
|
<rule>
|
||||||
|
<url><![CDATA[/query_param_with_url/\w+/(?P<name_1>[^/]+)(/(?P<name_2>[^/]+))?]]></url>
|
||||||
|
<method>GET</method>
|
||||||
|
<headers>
|
||||||
|
<XXX>TEST_HEADER_VALUE</XXX>
|
||||||
|
<PARAMS_XXX><![CDATA[(?P<name_1>[^/]+)(/(?P<name_2>[^/]+))?]]></PARAMS_XXX>
|
||||||
|
</headers>
|
||||||
|
<handler>
|
||||||
|
<type>predefined_query_handler</type>
|
||||||
|
<query>SELECT value FROM system.settings WHERE name = {name_1:String}</query>
|
||||||
|
<query>SELECT name, value FROM system.settings WHERE name = {name_2:String}</query>
|
||||||
|
</handler>
|
||||||
|
</rule>
|
||||||
|
</http_handlers>
|
||||||
|
```
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
$ curl -H 'XXX:TEST_HEADER_VALUE' -H 'PARAMS_XXX:max_threads' 'http://localhost:8123/query_param_with_url/1/max_threads/max_alter_threads?max_threads=1&max_alter_threads=2'
|
||||||
|
1
|
||||||
|
max_alter_threads 2
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! note "警告"
|
||||||
|
在一个`predefined_query_handler`中,只支持insert类型的一个`查询`。
|
||||||
|
|
||||||
|
### 动态查询 {#dynamic_query_handler}
|
||||||
|
|
||||||
|
`dynamic_query_handler`时,查询以HTTP请求参数的形式编写。区别在于,在`predefined_query_handler`中,查询是在配置文件中编写的。您可以在`dynamic_query_handler`中配置`query_param_name`。
|
||||||
|
|
||||||
|
ClickHouse提取并执行与HTTP请求URL中的`query_param_name`值对应的值。`query_param_name`的默认值是`/query`。这是一个可选的配置。如果配置文件中没有定义,则不会传入参数。
|
||||||
|
|
||||||
|
为了试验这个功能,示例定义了[max_threads](../operations/settings/settings.md#settings-max_threads)和`max_alter_threads`,`queries`设置是否成功的值。
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
``` xml
|
||||||
|
<http_handlers>
|
||||||
|
<rule>
|
||||||
|
<headers>
|
||||||
|
<XXX>TEST_HEADER_VALUE_DYNAMIC</XXX> </headers>
|
||||||
|
<handler>
|
||||||
|
<type>dynamic_query_handler</type>
|
||||||
|
<query_param_name>query_param</query_param_name>
|
||||||
|
</handler>
|
||||||
|
</rule>
|
||||||
|
</http_handlers>
|
||||||
|
```
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
$ curl -H 'XXX:TEST_HEADER_VALUE_DYNAMIC' 'http://localhost:8123/own?max_threads=1&max_alter_threads=2¶m_name_1=max_threads¶m_name_2=max_alter_threads&query_param=SELECT%20name,value%20FROM%20system.settings%20where%20name%20=%20%7Bname_1:String%7D%20OR%20name%20=%20%7Bname_2:String%7D'
|
||||||
|
max_threads 1
|
||||||
|
max_alter_threads 2
|
||||||
|
```
|
||||||
|
|
||||||
|
### static {#static}
|
||||||
|
|
||||||
|
`static`可以返回[content_type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type), [status](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)和`response_content`。`response_content`可以返回指定的内容。
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
返回信息.
|
||||||
|
|
||||||
|
``` xml
|
||||||
|
<http_handlers>
|
||||||
|
<rule>
|
||||||
|
<methods>GET</methods>
|
||||||
|
<headers><XXX>xxx</XXX></headers>
|
||||||
|
<url>/hi</url>
|
||||||
|
<handler>
|
||||||
|
<type>static</type>
|
||||||
|
<status>402</status>
|
||||||
|
<content_type>text/html; charset=UTF-8</content_type>
|
||||||
|
<response_content>Say Hi!</response_content>
|
||||||
|
</handler>
|
||||||
|
</rule>
|
||||||
|
<http_handlers>
|
||||||
|
```
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
$ curl -vv -H 'XXX:xxx' 'http://localhost:8123/hi'
|
||||||
|
* Trying ::1...
|
||||||
|
* Connected to localhost (::1) port 8123 (#0)
|
||||||
|
> GET /hi HTTP/1.1
|
||||||
|
> Host: localhost:8123
|
||||||
|
> User-Agent: curl/7.47.0
|
||||||
|
> Accept: */*
|
||||||
|
> XXX:xxx
|
||||||
|
>
|
||||||
|
< HTTP/1.1 402 Payment Required
|
||||||
|
< Date: Wed, 29 Apr 2020 03:51:26 GMT
|
||||||
|
< Connection: Keep-Alive
|
||||||
|
< Content-Type: text/html; charset=UTF-8
|
||||||
|
< Transfer-Encoding: chunked
|
||||||
|
< Keep-Alive: timeout=3
|
||||||
|
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0"}
|
||||||
|
<
|
||||||
|
* Connection #0 to host localhost left intact
|
||||||
|
Say Hi!%
|
||||||
|
```
|
||||||
|
|
||||||
|
从配置中查找发送到客户端的内容。
|
||||||
|
|
||||||
|
``` xml
|
||||||
|
<get_config_static_handler><![CDATA[<html ng-app="SMI2"><head><base href="http://ui.tabix.io/"></head><body><div ui-view="" class="content-ui"></div><script src="http://loader.tabix.io/master.js"></script></body></html>]]></get_config_static_handler>
|
||||||
|
|
||||||
|
<http_handlers>
|
||||||
|
<rule>
|
||||||
|
<methods>GET</methods>
|
||||||
|
<headers><XXX>xxx</XXX></headers>
|
||||||
|
<url>/get_config_static_handler</url>
|
||||||
|
<handler>
|
||||||
|
<type>static</type>
|
||||||
|
<response_content>config://get_config_static_handler</response_content>
|
||||||
|
</handler>
|
||||||
|
</rule>
|
||||||
|
</http_handlers>
|
||||||
|
```
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
$ curl -v -H 'XXX:xxx' 'http://localhost:8123/get_config_static_handler'
|
||||||
|
* Trying ::1...
|
||||||
|
* Connected to localhost (::1) port 8123 (#0)
|
||||||
|
> GET /get_config_static_handler HTTP/1.1
|
||||||
|
> Host: localhost:8123
|
||||||
|
> User-Agent: curl/7.47.0
|
||||||
|
> Accept: */*
|
||||||
|
> XXX:xxx
|
||||||
|
>
|
||||||
|
< HTTP/1.1 200 OK
|
||||||
|
< Date: Wed, 29 Apr 2020 04:01:24 GMT
|
||||||
|
< Connection: Keep-Alive
|
||||||
|
< Content-Type: text/plain; charset=UTF-8
|
||||||
|
< Transfer-Encoding: chunked
|
||||||
|
< Keep-Alive: timeout=3
|
||||||
|
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0"}
|
||||||
|
<
|
||||||
|
* Connection #0 to host localhost left intact
|
||||||
|
<html ng-app="SMI2"><head><base href="http://ui.tabix.io/"></head><body><div ui-view="" class="content-ui"></div><script src="http://loader.tabix.io/master.js"></script></body></html>%
|
||||||
|
```
|
||||||
|
|
||||||
|
从发送到客户端的文件中查找内容。
|
||||||
|
|
||||||
|
``` xml
|
||||||
|
<http_handlers>
|
||||||
|
<rule>
|
||||||
|
<methods>GET</methods>
|
||||||
|
<headers><XXX>xxx</XXX></headers>
|
||||||
|
<url>/get_absolute_path_static_handler</url>
|
||||||
|
<handler>
|
||||||
|
<type>static</type>
|
||||||
|
<content_type>text/html; charset=UTF-8</content_type>
|
||||||
|
<response_content>file:///absolute_path_file.html</response_content>
|
||||||
|
</handler>
|
||||||
|
</rule>
|
||||||
|
<rule>
|
||||||
|
<methods>GET</methods>
|
||||||
|
<headers><XXX>xxx</XXX></headers>
|
||||||
|
<url>/get_relative_path_static_handler</url>
|
||||||
|
<handler>
|
||||||
|
<type>static</type>
|
||||||
|
<content_type>text/html; charset=UTF-8</content_type>
|
||||||
|
<response_content>file://./relative_path_file.html</response_content>
|
||||||
|
</handler>
|
||||||
|
</rule>
|
||||||
|
</http_handlers>
|
||||||
|
```
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
$ user_files_path='/var/lib/clickhouse/user_files'
|
||||||
|
$ sudo echo "<html><body>Relative Path File</body></html>" > $user_files_path/relative_path_file.html
|
||||||
|
$ sudo echo "<html><body>Absolute Path File</body></html>" > $user_files_path/absolute_path_file.html
|
||||||
|
$ curl -vv -H 'XXX:xxx' 'http://localhost:8123/get_absolute_path_static_handler'
|
||||||
|
* Trying ::1...
|
||||||
|
* Connected to localhost (::1) port 8123 (#0)
|
||||||
|
> GET /get_absolute_path_static_handler HTTP/1.1
|
||||||
|
> Host: localhost:8123
|
||||||
|
> User-Agent: curl/7.47.0
|
||||||
|
> Accept: */*
|
||||||
|
> XXX:xxx
|
||||||
|
>
|
||||||
|
< HTTP/1.1 200 OK
|
||||||
|
< Date: Wed, 29 Apr 2020 04:18:16 GMT
|
||||||
|
< Connection: Keep-Alive
|
||||||
|
< Content-Type: text/html; charset=UTF-8
|
||||||
|
< Transfer-Encoding: chunked
|
||||||
|
< Keep-Alive: timeout=3
|
||||||
|
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0"}
|
||||||
|
<
|
||||||
|
<html><body>Absolute Path File</body></html>
|
||||||
|
* Connection #0 to host localhost left intact
|
||||||
|
$ curl -vv -H 'XXX:xxx' 'http://localhost:8123/get_relative_path_static_handler'
|
||||||
|
* Trying ::1...
|
||||||
|
* Connected to localhost (::1) port 8123 (#0)
|
||||||
|
> GET /get_relative_path_static_handler HTTP/1.1
|
||||||
|
> Host: localhost:8123
|
||||||
|
> User-Agent: curl/7.47.0
|
||||||
|
> Accept: */*
|
||||||
|
> XXX:xxx
|
||||||
|
>
|
||||||
|
< HTTP/1.1 200 OK
|
||||||
|
< Date: Wed, 29 Apr 2020 04:18:31 GMT
|
||||||
|
< Connection: Keep-Alive
|
||||||
|
< Content-Type: text/html; charset=UTF-8
|
||||||
|
< Transfer-Encoding: chunked
|
||||||
|
< Keep-Alive: timeout=3
|
||||||
|
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0"}
|
||||||
|
<
|
||||||
|
<html><body>Relative Path File</body></html>
|
||||||
|
* Connection #0 to host localhost left intact
|
||||||
|
```
|
||||||
|
|
||||||
[来源文章](https://clickhouse.tech/docs/zh/interfaces/http_interface/) <!--hide-->
|
[来源文章](https://clickhouse.tech/docs/zh/interfaces/http_interface/) <!--hide-->
|
||||||
|
@ -1,19 +1,27 @@
|
|||||||
|
---
|
||||||
|
toc_folder_title: Interfaces
|
||||||
|
toc_priority: 14
|
||||||
|
toc_title: 客户端
|
||||||
|
---
|
||||||
|
|
||||||
# 客户端 {#interfaces}
|
# 客户端 {#interfaces}
|
||||||
|
|
||||||
ClickHouse提供了两个网络接口(两者都可以选择包装在TLS中以提高安全性):
|
ClickHouse提供了两个网络接口(两个都可以选择包装在TLS中以增加安全性):
|
||||||
|
|
||||||
- [HTTP](http.md),记录在案,易于使用.
|
- [HTTP](http.md), 包含文档,易于使用。
|
||||||
- [本地TCP](tcp.md),这有较少的开销.
|
- [Native TCP](../interfaces/tcp.md),简单,方便使用。
|
||||||
|
|
||||||
在大多数情况下,建议使用适当的工具或库,而不是直接与这些工具或库进行交互。 Yandex的官方支持如下:
|
在大多数情况下,建议使用适当的工具或库,而不是直接与它们交互。Yandex官方支持的项目有:
|
||||||
\* [命令行客户端](cli.md)
|
|
||||||
\* [JDBC驱动程序](jdbc.md)
|
|
||||||
\* [ODBC驱动程序](odbc.md)
|
|
||||||
\* [C++客户端库](cpp.md)
|
|
||||||
|
|
||||||
还有许多第三方库可供使用ClickHouse:
|
- [命令行客户端](../interfaces/cli.md)
|
||||||
\* [客户端库](third-party/client-libraries.md)
|
- [JDBC驱动](../interfaces/jdbc.md)
|
||||||
\* [集成](third-party/integrations.md)
|
- [ODBC驱动](../interfaces/odbc.md)
|
||||||
\* [可视界面](third-party/gui.md)
|
- [C++客户端](../interfaces/cpp.md)
|
||||||
|
|
||||||
[来源文章](https://clickhouse.tech/docs/zh/interfaces/) <!--hide-->
|
还有一些广泛的第三方库可供ClickHouse使用:
|
||||||
|
|
||||||
|
- [客户端库](../interfaces/third-party/client-libraries.md)
|
||||||
|
- [第三方集成库](../interfaces/third-party/integrations.md)
|
||||||
|
- [可视化UI](../interfaces/third-party/gui.md)
|
||||||
|
|
||||||
|
[来源文章](https://clickhouse.tech/docs/en/interfaces/) <!--hide-->
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
# JDBC 驱动 {#jdbc-qu-dong}
|
---
|
||||||
|
toc_priority: 22
|
||||||
|
toc_title: JDBC驱动
|
||||||
|
---
|
||||||
|
|
||||||
- **[官方JDBC 的驱动](https://github.com/ClickHouse/clickhouse-jdbc)**
|
# JDBC驱动 {#jdbc-driver}
|
||||||
- 三方提供的 JDBC 驱动:
|
|
||||||
- [掳胫–禄脢鹿脷露胫鲁隆鹿–酶](https://github.com/housepower/ClickHouse-Native-JDBC)
|
- **[官方驱动](https://github.com/ClickHouse/clickhouse-jdbc)**
|
||||||
|
- 第三方驱动:
|
||||||
|
- [ClickHouse-Native-JDBC](https://github.com/housepower/ClickHouse-Native-JDBC)
|
||||||
- [clickhouse4j](https://github.com/blynkkk/clickhouse4j)
|
- [clickhouse4j](https://github.com/blynkkk/clickhouse4j)
|
||||||
|
|
||||||
[来源文章](https://clickhouse.tech/docs/zh/interfaces/jdbc/) <!--hide-->
|
[来源文章](https://clickhouse.tech/docs/zh/interfaces/jdbc/) <!--hide-->
|
||||||
|
@ -1,19 +1,17 @@
|
|||||||
---
|
---
|
||||||
machine_translated: true
|
|
||||||
machine_translated_rev: 72537a2d527c63c07aa5d2361a8829f3895cf2bd
|
|
||||||
toc_priority: 20
|
toc_priority: 20
|
||||||
toc_title: "MySQL\u63A5\u53E3"
|
toc_title: MySQL接口
|
||||||
---
|
---
|
||||||
|
|
||||||
# MySQL接口 {#mysql-interface}
|
# MySQL接口 {#mysql-interface}
|
||||||
|
|
||||||
ClickHouse支持MySQL线协议。 它可以通过启用 [mysql_port](../operations/server-configuration-parameters/settings.md#server_configuration_parameters-mysql_port) 在配置文件中设置:
|
ClickHouse支持MySQL协议。它可以通过[mysql_port](../operations/server-configuration-parameters/settings.md#server_configuration_parameters-mysql_port)在配置文件中设置:
|
||||||
|
|
||||||
``` xml
|
``` xml
|
||||||
<mysql_port>9004</mysql_port>
|
<mysql_port>9004</mysql_port>
|
||||||
```
|
```
|
||||||
|
|
||||||
使用命令行工具连接的示例 `mysql`:
|
使用命令行工具连接`mysql`示例:
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
$ mysql --protocol tcp -u default -P 9004
|
$ mysql --protocol tcp -u default -P 9004
|
||||||
@ -37,8 +35,8 @@ Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
|
|||||||
mysql>
|
mysql>
|
||||||
```
|
```
|
||||||
|
|
||||||
为了与所有MySQL客户端兼容,建议使用以下命令指定用户密码 [双SHA1](../operations/settings/settings-users.md#password_double_sha1_hex) 在配置文件中。
|
为了与所有MySQL客户端兼容,建议在配置文件中使用[双SHA1](../operations/settings/settings-users.md#password_double_sha1_hex)指定用户密码。
|
||||||
如果使用用户密码指定 [SHA256](../operations/settings/settings-users.md#password_sha256_hex),一些客户端将无法进行身份验证(mysqljs和旧版本的命令行工具mysql)。
|
如果使用[SHA256](../operations/settings/settings-users.md#password_sha256_hex)指定用户密码,一些客户端将无法进行身份验证(mysqljs和旧版本的命令行工具mysql)。
|
||||||
|
|
||||||
限制:
|
限制:
|
||||||
|
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
# ODBC 驱动 {#odbc-qu-dong}
|
---
|
||||||
|
toc_priority: 23
|
||||||
|
toc_title: ODBC驱动
|
||||||
|
---
|
||||||
|
|
||||||
- ClickHouse官方有 ODBC 的驱动。 见 [这里](https://github.com/ClickHouse/clickhouse-odbc)。
|
# ODBC驱动 {#odbc-driver}
|
||||||
|
|
||||||
|
- [官方驱动](https://github.com/ClickHouse/clickhouse-odbc)。
|
||||||
|
|
||||||
[来源文章](https://clickhouse.tech/docs/zh/interfaces/odbc/) <!--hide-->
|
[来源文章](https://clickhouse.tech/docs/zh/interfaces/odbc/) <!--hide-->
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
# 原生客户端接口(TCP) {#yuan-sheng-ke-hu-duan-jie-kou-tcp}
|
---
|
||||||
|
toc_priority: 18
|
||||||
|
toc_title: 原生接口(TCP)
|
||||||
|
---
|
||||||
|
|
||||||
本机协议用于 [命令行客户端](cli.md),用于分布式查询处理期间的服务器间通信,以及其他C ++程序。 不幸的是,本机ClickHouse协议还没有正式的规范,但它可以从ClickHouse源代码进行逆向工程 [从这里开始](https://github.com/ClickHouse/ClickHouse/tree/master/src/Client))和/或拦截和分析TCP流量。
|
# 原生接口(TCP){#native-interface-tcp}
|
||||||
|
|
||||||
|
原生接口用于[命令行客户端](cli.md),用于分布式查询处理期间的服务器间通信,以及其他C++程序。可惜的是,原生的ClickHouse协议还没有正式的规范,但它可以从ClickHouse[源代码](https://github.com/ClickHouse/ClickHouse/tree/master/src/Client)通过拦截和分析TCP流量进行反向工程。
|
||||||
|
|
||||||
[来源文章](https://clickhouse.tech/docs/zh/interfaces/tcp/) <!--hide-->
|
[来源文章](https://clickhouse.tech/docs/zh/interfaces/tcp/) <!--hide-->
|
||||||
|
@ -242,7 +242,7 @@ target_link_libraries (clickhouse_common_io
|
|||||||
PUBLIC
|
PUBLIC
|
||||||
common
|
common
|
||||||
${DOUBLE_CONVERSION_LIBRARIES}
|
${DOUBLE_CONVERSION_LIBRARIES}
|
||||||
ryu
|
dragonbox_to_chars
|
||||||
)
|
)
|
||||||
|
|
||||||
if(RE2_LIBRARY)
|
if(RE2_LIBRARY)
|
||||||
|
@ -37,12 +37,16 @@ void encodeSHA256(const void * text, size_t size, unsigned char * out)
|
|||||||
|
|
||||||
String getOpenSSLErrors()
|
String getOpenSSLErrors()
|
||||||
{
|
{
|
||||||
BIO * mem = BIO_new(BIO_s_mem());
|
String res;
|
||||||
SCOPE_EXIT(BIO_free(mem));
|
ERR_print_errors_cb([](const char * str, size_t len, void * ctx)
|
||||||
ERR_print_errors(mem);
|
{
|
||||||
char * buf = nullptr;
|
String & out = *reinterpret_cast<String*>(ctx);
|
||||||
size_t size = BIO_get_mem_data(mem, &buf);
|
if (!out.empty())
|
||||||
return String(buf, size);
|
out += ", ";
|
||||||
|
out.append(str, len);
|
||||||
|
return 1;
|
||||||
|
}, &res);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -216,7 +216,6 @@ std::pair<ResponsePtr, Undo> TestKeeperCreateRequest::process(TestKeeper::Contai
|
|||||||
if (is_sequential)
|
if (is_sequential)
|
||||||
{
|
{
|
||||||
auto seq_num = it->second.seq_num;
|
auto seq_num = it->second.seq_num;
|
||||||
++it->second.seq_num;
|
|
||||||
|
|
||||||
std::stringstream seq_num_str; // STYLE_CHECK_ALLOW_STD_STRING_STREAM
|
std::stringstream seq_num_str; // STYLE_CHECK_ALLOW_STD_STRING_STREAM
|
||||||
seq_num_str.exceptions(std::ios::failbit);
|
seq_num_str.exceptions(std::ios::failbit);
|
||||||
@ -225,18 +224,19 @@ std::pair<ResponsePtr, Undo> TestKeeperCreateRequest::process(TestKeeper::Contai
|
|||||||
path_created += seq_num_str.str();
|
path_created += seq_num_str.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Increment sequential number even if node is not sequential
|
||||||
|
++it->second.seq_num;
|
||||||
|
|
||||||
response.path_created = path_created;
|
response.path_created = path_created;
|
||||||
container.emplace(path_created, std::move(created_node));
|
container.emplace(path_created, std::move(created_node));
|
||||||
|
|
||||||
undo = [&container, path_created, is_sequential = is_sequential, parent_path = it->first]
|
undo = [&container, path_created, parent_path = it->first]
|
||||||
{
|
{
|
||||||
container.erase(path_created);
|
container.erase(path_created);
|
||||||
auto & undo_parent = container.at(parent_path);
|
auto & undo_parent = container.at(parent_path);
|
||||||
--undo_parent.stat.cversion;
|
--undo_parent.stat.cversion;
|
||||||
--undo_parent.stat.numChildren;
|
--undo_parent.stat.numChildren;
|
||||||
|
--undo_parent.seq_num;
|
||||||
if (is_sequential)
|
|
||||||
--undo_parent.seq_num;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
++it->second.stat.cversion;
|
++it->second.stat.cversion;
|
||||||
|
@ -112,9 +112,12 @@ static void validateKeyTypes(const DataTypes & key_types)
|
|||||||
if (key_types.empty() || key_types.size() > 2)
|
if (key_types.empty() || key_types.size() > 2)
|
||||||
throw Exception{"Expected a single IP address or IP with mask", ErrorCodes::TYPE_MISMATCH};
|
throw Exception{"Expected a single IP address or IP with mask", ErrorCodes::TYPE_MISMATCH};
|
||||||
|
|
||||||
const auto & actual_type = key_types[0]->getName();
|
const auto * key_ipv4type = typeid_cast<const DataTypeUInt32 *>(key_types[0].get());
|
||||||
if (actual_type != "UInt32" && actual_type != "FixedString(16)")
|
const auto * key_ipv6type = typeid_cast<const DataTypeFixedString *>(key_types[0].get());
|
||||||
throw Exception{"Key does not match, expected either UInt32 or FixedString(16)", ErrorCodes::TYPE_MISMATCH};
|
|
||||||
|
if (key_ipv4type == nullptr && (key_ipv6type == nullptr || key_ipv6type->getN() != 16))
|
||||||
|
throw Exception{"Key does not match, expected either `IPv4` (`UInt32`) or `IPv6` (`FixedString(16)`)",
|
||||||
|
ErrorCodes::TYPE_MISMATCH};
|
||||||
|
|
||||||
if (key_types.size() > 1)
|
if (key_types.size() > 1)
|
||||||
{
|
{
|
||||||
|
@ -82,10 +82,9 @@ struct KeyHolder<CipherMode::MySQLCompatibility>
|
|||||||
return foldEncryptionKeyInMySQLCompatitableMode(cipher_key_size, key, folded_key);
|
return foldEncryptionKeyInMySQLCompatitableMode(cipher_key_size, key, folded_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
~KeyHolder()
|
/// There is a function to clear key securely.
|
||||||
{
|
/// It makes absolutely zero sense to call it here because
|
||||||
OPENSSL_cleanse(folded_key.data(), folded_key.size());
|
/// key comes from column and already copied multiple times through various memory buffers.
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::array<char, EVP_MAX_KEY_LENGTH> folded_key;
|
std::array<char, EVP_MAX_KEY_LENGTH> folded_key;
|
||||||
@ -119,7 +118,7 @@ inline void validateCipherMode(const EVP_CIPHER * evp_cipher)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw DB::Exception("Unsupported cipher mode " + std::string(EVP_CIPHER_name(evp_cipher)), DB::ErrorCodes::BAD_ARGUMENTS);
|
throw DB::Exception("Unsupported cipher mode", DB::ErrorCodes::BAD_ARGUMENTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <CipherMode mode>
|
template <CipherMode mode>
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#include <IO/DoubleConverter.h>
|
#include <IO/DoubleConverter.h>
|
||||||
#include <IO/WriteBufferFromString.h>
|
#include <IO/WriteBufferFromString.h>
|
||||||
|
|
||||||
#include <ryu/ryu.h>
|
#include <dragonbox/dragonbox_to_chars.h>
|
||||||
|
|
||||||
#include <Formats/FormatSettings.h>
|
#include <Formats/FormatSettings.h>
|
||||||
|
|
||||||
@ -228,14 +228,14 @@ inline size_t writeFloatTextFastPath(T x, char * buffer)
|
|||||||
if (DecomposedFloat64(x).is_inside_int64())
|
if (DecomposedFloat64(x).is_inside_int64())
|
||||||
result = itoa(Int64(x), buffer) - buffer;
|
result = itoa(Int64(x), buffer) - buffer;
|
||||||
else
|
else
|
||||||
result = d2s_buffered_n(x, buffer);
|
result = jkj::dragonbox::to_chars_n(x, buffer) - buffer;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (DecomposedFloat32(x).is_inside_int32())
|
if (DecomposedFloat32(x).is_inside_int32())
|
||||||
result = itoa(Int32(x), buffer) - buffer;
|
result = itoa(Int32(x), buffer) - buffer;
|
||||||
else
|
else
|
||||||
result = f2s_buffered_n(x, buffer);
|
result = jkj::dragonbox::to_chars_n(x, buffer) - buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result <= 0)
|
if (result <= 0)
|
||||||
|
@ -80,8 +80,8 @@ target_link_libraries (parse_date_time_best_effort PRIVATE clickhouse_common_io)
|
|||||||
add_executable (zlib_ng_bug zlib_ng_bug.cpp)
|
add_executable (zlib_ng_bug zlib_ng_bug.cpp)
|
||||||
target_link_libraries (zlib_ng_bug PRIVATE ${ZLIB_LIBRARIES})
|
target_link_libraries (zlib_ng_bug PRIVATE ${ZLIB_LIBRARIES})
|
||||||
|
|
||||||
add_executable (ryu_test ryu_test.cpp)
|
add_executable (dragonbox_test dragonbox_test.cpp)
|
||||||
target_link_libraries (ryu_test PRIVATE ryu)
|
target_link_libraries (dragonbox_test PRIVATE dragonbox_to_chars)
|
||||||
|
|
||||||
add_executable (zstd_buffers zstd_buffers.cpp)
|
add_executable (zstd_buffers zstd_buffers.cpp)
|
||||||
target_link_libraries (zstd_buffers PRIVATE clickhouse_common_io)
|
target_link_libraries (zstd_buffers PRIVATE clickhouse_common_io)
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <ryu/ryu.h>
|
#include <dragonbox/dragonbox_to_chars.h>
|
||||||
|
|
||||||
|
|
||||||
struct DecomposedFloat64
|
struct DecomposedFloat64
|
||||||
{
|
{
|
||||||
@ -84,7 +83,8 @@ int main(int argc, char ** argv)
|
|||||||
double x = argc > 1 ? std::stod(argv[1]) : 0;
|
double x = argc > 1 ? std::stod(argv[1]) : 0;
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
|
||||||
d2s_buffered(x, buf);
|
std::cout << "dragonbox output" << std::endl;
|
||||||
|
jkj::dragonbox::to_chars(x, buf);
|
||||||
std::cout << buf << "\n";
|
std::cout << buf << "\n";
|
||||||
|
|
||||||
std::cout << DecomposedFloat64(x).isInsideInt64() << "\n";
|
std::cout << DecomposedFloat64(x).isInsideInt64() << "\n";
|
@ -349,6 +349,16 @@ void ActionsDAG::removeUnusedActions()
|
|||||||
stack.push(node);
|
stack.push(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// We cannot remove arrayJoin because it changes the number of rows.
|
||||||
|
for (auto & node : nodes)
|
||||||
|
{
|
||||||
|
if (node.type == ActionType::ARRAY_JOIN && visited_nodes.count(&node) == 0)
|
||||||
|
{
|
||||||
|
visited_nodes.insert(&node);
|
||||||
|
stack.push(&node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (!stack.empty())
|
while (!stack.empty())
|
||||||
{
|
{
|
||||||
auto * node = stack.top();
|
auto * node = stack.top();
|
||||||
@ -552,6 +562,15 @@ bool ActionsDAG::hasArrayJoin() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ActionsDAG::hasStatefulFunctions() const
|
||||||
|
{
|
||||||
|
for (const auto & node : nodes)
|
||||||
|
if (node.type == ActionType::FUNCTION && node.function_base->isStateful())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool ActionsDAG::empty() const
|
bool ActionsDAG::empty() const
|
||||||
{
|
{
|
||||||
for (const auto & node : nodes)
|
for (const auto & node : nodes)
|
||||||
@ -670,6 +689,111 @@ ActionsDAGPtr ActionsDAG::makeConvertingActions(
|
|||||||
return actions_dag;
|
return actions_dag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ActionsDAGPtr ActionsDAG::merge(ActionsDAG && first, ActionsDAG && second)
|
||||||
|
{
|
||||||
|
/// first: x (1), x (2), y ==> x (2), z, x (3)
|
||||||
|
/// second: x (1), x (2), x (3) ==> x (3), x (2), x (1)
|
||||||
|
/// merge: x (1), x (2), x (3), y =(first)=> x (3), y, x (2), z, x (4) =(second)=> y, z, x (4), x (2), x (3)
|
||||||
|
|
||||||
|
/// Will store merged result in `first`.
|
||||||
|
|
||||||
|
/// This map contains nodes which should be removed from `first` index, cause they are used as inputs for `second`.
|
||||||
|
std::unordered_set<Node *> removed_first_result;
|
||||||
|
/// Map inputs of `second` to nodes of `first`.
|
||||||
|
std::unordered_map<Node *, Node *> inputs_map;
|
||||||
|
|
||||||
|
/// Update inputs list.
|
||||||
|
{
|
||||||
|
/// Index may have multiple columns with same name. They also may be used by `second`. Order is important.
|
||||||
|
std::unordered_map<std::string_view, std::list<Node *>> first_result;
|
||||||
|
for (auto & node : first.index)
|
||||||
|
first_result[node->result_name].push_back(node);
|
||||||
|
|
||||||
|
for (auto & node : second.inputs)
|
||||||
|
{
|
||||||
|
auto it = first_result.find(node->result_name);
|
||||||
|
if (it == first_result.end() || it->second.empty())
|
||||||
|
{
|
||||||
|
if (first.settings.project_input)
|
||||||
|
throw Exception(ErrorCodes::LOGICAL_ERROR,
|
||||||
|
"Cannot find column {} in ActionsDAG result", node->result_name);
|
||||||
|
|
||||||
|
first.inputs.push_back(node);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
inputs_map[node] = it->second.front();
|
||||||
|
removed_first_result.emplace(it->second.front());
|
||||||
|
it->second.pop_front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Replace inputs from `second` to nodes from `first` result.
|
||||||
|
for (auto & node : second.nodes)
|
||||||
|
{
|
||||||
|
for (auto & child : node.children)
|
||||||
|
{
|
||||||
|
if (child->type == ActionType::INPUT)
|
||||||
|
{
|
||||||
|
auto it = inputs_map.find(child);
|
||||||
|
if (it != inputs_map.end())
|
||||||
|
child = it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto & node : second.index)
|
||||||
|
{
|
||||||
|
if (node->type == ActionType::INPUT)
|
||||||
|
{
|
||||||
|
auto it = inputs_map.find(node);
|
||||||
|
if (it != inputs_map.end())
|
||||||
|
node = it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update index.
|
||||||
|
if (second.settings.project_input)
|
||||||
|
{
|
||||||
|
first.index.swap(second.index);
|
||||||
|
first.settings.project_input = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/// Remove `second` inputs from index.
|
||||||
|
for (auto it = first.index.begin(); it != first.index.end();)
|
||||||
|
{
|
||||||
|
auto cur = it;
|
||||||
|
++it;
|
||||||
|
|
||||||
|
if (removed_first_result.count(*cur))
|
||||||
|
first.index.remove(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto * node : second.index)
|
||||||
|
first.index.insert(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
first.nodes.splice(first.nodes.end(), std::move(second.nodes));
|
||||||
|
|
||||||
|
#if USE_EMBEDDED_COMPILER
|
||||||
|
if (first.compilation_cache == nullptr)
|
||||||
|
first.compilation_cache = second.compilation_cache;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
first.settings.max_temporary_columns = std::max(first.settings.max_temporary_columns, second.settings.max_temporary_columns);
|
||||||
|
first.settings.max_temporary_non_const_columns = std::max(first.settings.max_temporary_non_const_columns, second.settings.max_temporary_non_const_columns);
|
||||||
|
first.settings.min_count_to_compile_expression = std::max(first.settings.min_count_to_compile_expression, second.settings.min_count_to_compile_expression);
|
||||||
|
first.settings.projected_output = second.settings.projected_output;
|
||||||
|
|
||||||
|
/// Drop unused inputs and, probably, some actions.
|
||||||
|
first.removeUnusedActions();
|
||||||
|
|
||||||
|
return std::make_shared<ActionsDAG>(std::move(first));
|
||||||
|
}
|
||||||
|
|
||||||
ActionsDAGPtr ActionsDAG::splitActionsBeforeArrayJoin(const NameSet & array_joined_columns)
|
ActionsDAGPtr ActionsDAG::splitActionsBeforeArrayJoin(const NameSet & array_joined_columns)
|
||||||
{
|
{
|
||||||
/// Split DAG into two parts.
|
/// Split DAG into two parts.
|
||||||
|
@ -143,6 +143,15 @@ public:
|
|||||||
map.erase(it);
|
map.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void remove(std::list<Node *>::iterator it)
|
||||||
|
{
|
||||||
|
auto map_it = map.find((*it)->result_name);
|
||||||
|
if (map_it != map.end() && map_it->second == it)
|
||||||
|
map.erase(map_it);
|
||||||
|
|
||||||
|
list.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
void swap(Index & other)
|
void swap(Index & other)
|
||||||
{
|
{
|
||||||
list.swap(other.list);
|
list.swap(other.list);
|
||||||
@ -176,6 +185,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
ActionsDAG() = default;
|
ActionsDAG() = default;
|
||||||
|
ActionsDAG(ActionsDAG &&) = default;
|
||||||
ActionsDAG(const ActionsDAG &) = delete;
|
ActionsDAG(const ActionsDAG &) = delete;
|
||||||
ActionsDAG & operator=(const ActionsDAG &) = delete;
|
ActionsDAG & operator=(const ActionsDAG &) = delete;
|
||||||
explicit ActionsDAG(const NamesAndTypesList & inputs_);
|
explicit ActionsDAG(const NamesAndTypesList & inputs_);
|
||||||
@ -222,6 +232,7 @@ public:
|
|||||||
ActionsDAGPtr splitActionsBeforeArrayJoin(const NameSet & array_joined_columns);
|
ActionsDAGPtr splitActionsBeforeArrayJoin(const NameSet & array_joined_columns);
|
||||||
|
|
||||||
bool hasArrayJoin() const;
|
bool hasArrayJoin() const;
|
||||||
|
bool hasStatefulFunctions() const;
|
||||||
bool empty() const; /// If actions only contain inputs.
|
bool empty() const; /// If actions only contain inputs.
|
||||||
|
|
||||||
const ActionsSettings & getSettings() const { return settings; }
|
const ActionsSettings & getSettings() const { return settings; }
|
||||||
@ -248,6 +259,12 @@ public:
|
|||||||
MatchColumnsMode mode,
|
MatchColumnsMode mode,
|
||||||
bool ignore_constant_values = false); /// Do not check that constants are same. Use value from result_header.
|
bool ignore_constant_values = false); /// Do not check that constants are same. Use value from result_header.
|
||||||
|
|
||||||
|
/// Create ActionsDAG which represents expression equivalent to applying lhs and rhs actions consequently.
|
||||||
|
/// Is used to replace `(first -> second)` expression chain to single `merge(first, second)` expression.
|
||||||
|
/// If first.settings.project_input is set, then outputs of `first` must include inputs of `second`.
|
||||||
|
/// Otherwise, any two actions may be combined.
|
||||||
|
static ActionsDAGPtr merge(ActionsDAG && first, ActionsDAG && second);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Node & addNode(Node node, bool can_replace = false);
|
Node & addNode(Node node, bool can_replace = false);
|
||||||
Node & getNode(const std::string & name);
|
Node & getNode(const std::string & name);
|
||||||
|
@ -484,6 +484,38 @@ static void tryLiftUpArrayJoin(QueryPlan::Node * parent_node, QueryPlan::Node *
|
|||||||
: filter_step->updateInputStream(array_join_step->getOutputStream(), true);
|
: filter_step->updateInputStream(array_join_step->getOutputStream(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool tryMergeExpressions(QueryPlan::Node * parent_node, QueryPlan::Node * child_node)
|
||||||
|
{
|
||||||
|
auto & parent = parent_node->step;
|
||||||
|
auto & child = child_node->step;
|
||||||
|
/// TODO: FilterStep
|
||||||
|
auto * parent_expr = typeid_cast<ExpressionStep *>(parent.get());
|
||||||
|
auto * child_expr = typeid_cast<ExpressionStep *>(child.get());
|
||||||
|
|
||||||
|
if (parent_expr && child_expr)
|
||||||
|
{
|
||||||
|
const auto & child_actions = child_expr->getExpression();
|
||||||
|
const auto & parent_actions = parent_expr->getExpression();
|
||||||
|
|
||||||
|
/// We cannot combine actions with arrayJoin and stateful function because we not always can reorder them.
|
||||||
|
/// Example: select rowNumberInBlock() from (select arrayJoin([1, 2]))
|
||||||
|
/// Such a query will return two zeroes if we combine actions together.
|
||||||
|
if (child_actions->hasArrayJoin() && parent_actions->hasStatefulFunctions())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto merged = ActionsDAG::merge(std::move(*child_actions), std::move(*parent_actions));
|
||||||
|
|
||||||
|
auto expr = std::make_unique<ExpressionStep>(child_expr->getInputStreams().front(), merged);
|
||||||
|
expr->setStepDescription(parent_expr->getStepDescription() + " + " + child_expr->getStepDescription());
|
||||||
|
|
||||||
|
parent_node->step = std::move(expr);
|
||||||
|
parent_node->children.swap(child_node->children);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void QueryPlan::optimize()
|
void QueryPlan::optimize()
|
||||||
{
|
{
|
||||||
struct Frame
|
struct Frame
|
||||||
@ -503,7 +535,11 @@ void QueryPlan::optimize()
|
|||||||
{
|
{
|
||||||
/// First entrance, try push down.
|
/// First entrance, try push down.
|
||||||
if (frame.node->children.size() == 1)
|
if (frame.node->children.size() == 1)
|
||||||
|
{
|
||||||
tryPushDownLimit(frame.node->step, frame.node->children.front());
|
tryPushDownLimit(frame.node->step, frame.node->children.front());
|
||||||
|
|
||||||
|
while (tryMergeExpressions(frame.node, frame.node->children.front()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frame.next_child < frame.node->children.size())
|
if (frame.next_child < frame.node->children.size())
|
||||||
|
@ -50,6 +50,8 @@
|
|||||||
1
|
1
|
||||||
1
|
1
|
||||||
1
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
***ipv4 trie dict mask***
|
***ipv4 trie dict mask***
|
||||||
1
|
1
|
||||||
1
|
1
|
||||||
@ -111,6 +113,16 @@
|
|||||||
1
|
1
|
||||||
1
|
1
|
||||||
1
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
***ipv6 trie dict***
|
***ipv6 trie dict***
|
||||||
1
|
1
|
||||||
1
|
1
|
||||||
@ -418,8 +430,3 @@
|
|||||||
1
|
1
|
||||||
1
|
1
|
||||||
1
|
1
|
||||||
1
|
|
||||||
1
|
|
||||||
1
|
|
||||||
1
|
|
||||||
1
|
|
||||||
|
@ -95,6 +95,10 @@ SELECT 11212 == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'asn', tuple(I
|
|||||||
|
|
||||||
SELECT 11211 == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'asn', tuple(IPv4StringToNum('202.79.32.2')));
|
SELECT 11211 == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'asn', tuple(IPv4StringToNum('202.79.32.2')));
|
||||||
|
|
||||||
|
-- check that dictionary works with aliased types `IPv4` and `IPv6`
|
||||||
|
SELECT 11211 == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'asn', tuple(toIPv4('202.79.32.2')));
|
||||||
|
SELECT 11212 == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'asn', tuple(toIPv6('::ffff:101.79.55.22')));
|
||||||
|
|
||||||
CREATE TABLE database_for_dict.table_from_ipv4_trie_dict
|
CREATE TABLE database_for_dict.table_from_ipv4_trie_dict
|
||||||
(
|
(
|
||||||
prefix String,
|
prefix String,
|
||||||
@ -217,6 +221,17 @@ SELECT 18 == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv4
|
|||||||
SELECT 19 == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv4StringToNum('127.255.128.255')));
|
SELECT 19 == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv4StringToNum('127.255.128.255')));
|
||||||
SELECT 20 == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv4StringToNum('127.255.255.128')));
|
SELECT 20 == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv4StringToNum('127.255.255.128')));
|
||||||
|
|
||||||
|
SELECT 3 == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv6StringToNum('::ffff:7f00:0')));
|
||||||
|
SELECT 4 == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv6StringToNum('::ffff:7f00:1')));
|
||||||
|
SELECT 3 == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv6StringToNum('::ffff:7f00:7f')));
|
||||||
|
SELECT 2 == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv6StringToNum('::ffff:7f00:ff7f')));
|
||||||
|
SELECT 15 == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv6StringToNum('::ffff:7fff:7f7f')));
|
||||||
|
SELECT 16 == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv6StringToNum('::ffff:7fff:8009')));
|
||||||
|
SELECT 16 == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv6StringToNum('::ffff:7fff:807f')));
|
||||||
|
SELECT 18 == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv6StringToNum('::ffff:7fff:800a')));
|
||||||
|
SELECT 19 == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv6StringToNum('::ffff:7fff:80ff')));
|
||||||
|
SELECT 20 == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv6StringToNum('::ffff:7fff:ff80')));
|
||||||
|
|
||||||
SELECT 1 == dictHas('database_for_dict.dict_ipv4_trie', tuple(IPv4StringToNum('127.0.0.0')));
|
SELECT 1 == dictHas('database_for_dict.dict_ipv4_trie', tuple(IPv4StringToNum('127.0.0.0')));
|
||||||
SELECT 1 == dictHas('database_for_dict.dict_ipv4_trie', tuple(IPv4StringToNum('127.0.0.1')));
|
SELECT 1 == dictHas('database_for_dict.dict_ipv4_trie', tuple(IPv4StringToNum('127.0.0.1')));
|
||||||
SELECT 1 == dictHas('database_for_dict.dict_ipv4_trie', tuple(IPv4StringToNum('127.0.0.127')));
|
SELECT 1 == dictHas('database_for_dict.dict_ipv4_trie', tuple(IPv4StringToNum('127.0.0.127')));
|
||||||
@ -446,7 +461,7 @@ FROM VALUES ('number UInt32', 5, 13, 24, 48, 49, 99, 127);
|
|||||||
|
|
||||||
INSERT INTO database_for_dict.table_ip_trie VALUES ('101.79.55.22', 'JA');
|
INSERT INTO database_for_dict.table_ip_trie VALUES ('101.79.55.22', 'JA');
|
||||||
|
|
||||||
INSERT INTO database_for_dict.table_ipv4_trie
|
INSERT INTO database_for_dict.table_ip_trie
|
||||||
SELECT
|
SELECT
|
||||||
'255.255.255.255/' || toString(number) AS prefix,
|
'255.255.255.255/' || toString(number) AS prefix,
|
||||||
toString(number) AS val
|
toString(number) AS val
|
||||||
@ -607,27 +622,20 @@ SELECT '99' == dictGetString('database_for_dict.dict_ip_trie', 'val', tuple(IPv6
|
|||||||
SELECT '127' == dictGetString('database_for_dict.dict_ip_trie', 'val', tuple(IPv6StringToNum('ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe')));
|
SELECT '127' == dictGetString('database_for_dict.dict_ip_trie', 'val', tuple(IPv6StringToNum('ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe')));
|
||||||
SELECT '127' == dictGetString('database_for_dict.dict_ip_trie', 'val', tuple(IPv6StringToNum('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff')));
|
SELECT '127' == dictGetString('database_for_dict.dict_ip_trie', 'val', tuple(IPv6StringToNum('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff')));
|
||||||
|
|
||||||
|
SELECT '' == dictGetString('database_for_dict.dict_ip_trie', 'val', tuple(IPv4StringToNum('0.0.0.0')));
|
||||||
SELECT '3' == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv4StringToNum('127.0.0.0')));
|
SELECT '' == dictGetString('database_for_dict.dict_ip_trie', 'val', tuple(IPv4StringToNum('128.0.0.0')));
|
||||||
SELECT '4' == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv4StringToNum('127.0.0.1')));
|
SELECT '' == dictGetString('database_for_dict.dict_ip_trie', 'val', tuple(IPv4StringToNum('240.0.0.0')));
|
||||||
SELECT '3' == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv4StringToNum('127.0.0.127')));
|
SELECT '5' == dictGetString('database_for_dict.dict_ip_trie', 'val', tuple(IPv4StringToNum('248.0.0.0')));
|
||||||
SELECT '2' == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv4StringToNum('127.0.255.127')));
|
SELECT '5' == dictGetString('database_for_dict.dict_ip_trie', 'val', tuple(IPv4StringToNum('252.0.0.0')));
|
||||||
SELECT '15' == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv4StringToNum('127.255.127.127')));
|
SELECT '5' == dictGetString('database_for_dict.dict_ip_trie', 'val', tuple(IPv4StringToNum('255.240.0.0')));
|
||||||
SELECT '16' == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv4StringToNum('127.255.128.9')));
|
SELECT '13' == dictGetString('database_for_dict.dict_ip_trie', 'val', tuple(IPv4StringToNum('255.248.0.0')));
|
||||||
SELECT '16' == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv4StringToNum('127.255.128.127')));
|
SELECT '13' == dictGetString('database_for_dict.dict_ip_trie', 'val', tuple(IPv4StringToNum('255.252.0.0')));
|
||||||
SELECT '18' == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv4StringToNum('127.255.128.10')));
|
SELECT '13' == dictGetString('database_for_dict.dict_ip_trie', 'val', tuple(IPv4StringToNum('255.255.254.0')));
|
||||||
SELECT '19' == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv4StringToNum('127.255.128.255')));
|
SELECT '24' == dictGetString('database_for_dict.dict_ip_trie', 'val', tuple(IPv4StringToNum('255.255.255.0')));
|
||||||
SELECT '20' == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv4StringToNum('127.255.255.128')));
|
SELECT '24' == dictGetString('database_for_dict.dict_ip_trie', 'val', tuple(IPv4StringToNum('255.255.255.128')));
|
||||||
|
SELECT '24' == dictGetString('database_for_dict.dict_ip_trie', 'val', tuple(IPv4StringToNum('255.255.255.248')));
|
||||||
SELECT '3' == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv6StringToNum('::ffff:7f00:0')));
|
SELECT '30' == dictGetString('database_for_dict.dict_ip_trie', 'val', tuple(IPv4StringToNum('255.255.255.252')));
|
||||||
SELECT '4' == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv6StringToNum('::ffff:7f00:1')));
|
SELECT '30' == dictGetString('database_for_dict.dict_ip_trie', 'val', tuple(IPv4StringToNum('255.255.255.254')));
|
||||||
SELECT '3' == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv6StringToNum('::ffff:7f00:7f')));
|
SELECT '30' == dictGetString('database_for_dict.dict_ip_trie', 'val', tuple(IPv4StringToNum('255.255.255.255')));
|
||||||
SELECT '2' == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv6StringToNum('::ffff:7f00:ff7f')));
|
|
||||||
SELECT '15' == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv6StringToNum('::ffff:7fff:7f7f')));
|
|
||||||
SELECT '16' == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv6StringToNum('::ffff:7fff:8009')));
|
|
||||||
SELECT '16' == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv6StringToNum('::ffff:7fff:807f')));
|
|
||||||
SELECT '18' == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv6StringToNum('::ffff:7fff:800a')));
|
|
||||||
SELECT '19' == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv6StringToNum('::ffff:7fff:80ff')));
|
|
||||||
SELECT '20' == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'val', tuple(IPv6StringToNum('::ffff:7fff:ff80')));
|
|
||||||
|
|
||||||
DROP DATABASE IF EXISTS database_for_dict;
|
DROP DATABASE IF EXISTS database_for_dict;
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
Expression (Projection)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Header: x UInt8
|
Header: x UInt8
|
||||||
Expression (Before ORDER BY and SELECT)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
Header: dummy UInt8
|
Header: dummy UInt8
|
||||||
1 UInt8
|
ReadFromStorage (SystemOne)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
Header: dummy UInt8
|
Header: dummy UInt8
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Header: dummy UInt8
|
|
||||||
|
@ -1,30 +1,28 @@
|
|||||||
(Expression)
|
(Expression)
|
||||||
ExpressionTransform
|
ExpressionTransform
|
||||||
(Expression)
|
(Aggregating)
|
||||||
ExpressionTransform
|
FinalizingSimpleTransform
|
||||||
(Aggregating)
|
AggregatingSortedTransform 3 → 1
|
||||||
FinalizingSimpleTransform
|
AggregatingInOrderTransform × 3
|
||||||
AggregatingSortedTransform 3 → 1
|
(Expression)
|
||||||
AggregatingInOrderTransform × 3
|
ExpressionTransform × 3
|
||||||
(Expression)
|
(SettingQuotaAndLimits)
|
||||||
ExpressionTransform × 3
|
(Expression)
|
||||||
(SettingQuotaAndLimits)
|
ExpressionTransform × 3
|
||||||
(Expression)
|
(Union)
|
||||||
ExpressionTransform × 3
|
(MergingSorted)
|
||||||
(Union)
|
(Expression)
|
||||||
(MergingSorted)
|
ExpressionTransform
|
||||||
(Expression)
|
(ReadFromStorage)
|
||||||
ExpressionTransform
|
MergeTree 0 → 1
|
||||||
(ReadFromStorage)
|
(MergingSorted)
|
||||||
MergeTree 0 → 1
|
MergingSortedTransform 2 → 1
|
||||||
(MergingSorted)
|
(Expression)
|
||||||
MergingSortedTransform 2 → 1
|
ExpressionTransform × 2
|
||||||
(Expression)
|
(ReadFromStorage)
|
||||||
ExpressionTransform × 2
|
MergeTree × 2 0 → 1
|
||||||
(ReadFromStorage)
|
(MergingSorted)
|
||||||
MergeTree × 2 0 → 1
|
(Expression)
|
||||||
(MergingSorted)
|
ExpressionTransform
|
||||||
(Expression)
|
(ReadFromStorage)
|
||||||
ExpressionTransform
|
MergeTree 0 → 1
|
||||||
(ReadFromStorage)
|
|
||||||
MergeTree 0 → 1
|
|
||||||
|
@ -1,324 +1,252 @@
|
|||||||
Union
|
Union
|
||||||
Expression (Projection)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Before ORDER BY and SELECT)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Union
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Distinct
|
||||||
|
Union
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
ReadFromStorage (SystemOne)
|
ReadFromStorage (SystemOne)
|
||||||
Expression (Projection)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
ReadFromStorage (SystemOne)
|
ReadFromStorage (SystemOne)
|
||||||
Expression (Projection)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Before ORDER BY and SELECT)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Distinct
|
||||||
|
Union
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Distinct
|
||||||
|
Union
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Distinct
|
||||||
|
Union
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
ReadFromStorage (SystemOne)
|
ReadFromStorage (SystemOne)
|
||||||
Union
|
Union
|
||||||
Expression (Projection)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Before ORDER BY and SELECT)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
ReadFromStorage (SystemOne)
|
||||||
ReadFromStorage (SystemOne)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Projection)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
Expression (Before ORDER BY and SELECT)
|
ReadFromStorage (SystemOne)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Distinct
|
|
||||||
Union
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Distinct
|
|
||||||
Union
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Distinct
|
|
||||||
Union
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Distinct
|
|
||||||
Union
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Union
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Distinct
|
Distinct
|
||||||
Union
|
Union
|
||||||
Expression (Projection)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Before ORDER BY and SELECT)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
ReadFromStorage (SystemOne)
|
||||||
ReadFromStorage (SystemOne)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Projection)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
Expression (Before ORDER BY and SELECT)
|
ReadFromStorage (SystemOne)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
ReadFromStorage (SystemOne)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
Expression (Projection)
|
ReadFromStorage (SystemOne)
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Distinct
|
Distinct
|
||||||
Union
|
Union
|
||||||
Expression (Projection)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Distinct
|
|
||||||
Union
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
ReadFromStorage (SystemOne)
|
ReadFromStorage (SystemOne)
|
||||||
Expression (Projection)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
ReadFromStorage (SystemOne)
|
ReadFromStorage (SystemOne)
|
||||||
Expression (Projection)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Before ORDER BY and SELECT)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
ReadFromStorage (SystemOne)
|
ReadFromStorage (SystemOne)
|
||||||
Distinct
|
Distinct
|
||||||
Union
|
Union
|
||||||
Expression (Projection)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Distinct
|
|
||||||
Union
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Union
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
ReadFromStorage (SystemOne)
|
ReadFromStorage (SystemOne)
|
||||||
Expression (Projection)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
ReadFromStorage (SystemOne)
|
ReadFromStorage (SystemOne)
|
||||||
Expression (Projection)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Before ORDER BY and SELECT)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Distinct
|
||||||
|
Union
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Distinct
|
||||||
|
Union
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
ReadFromStorage (SystemOne)
|
ReadFromStorage (SystemOne)
|
||||||
Union
|
Union
|
||||||
Expression (Projection)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Before ORDER BY and SELECT)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Union
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Union
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Distinct
|
||||||
|
Union
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
ReadFromStorage (SystemOne)
|
ReadFromStorage (SystemOne)
|
||||||
Expression (Projection)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
ReadFromStorage (SystemOne)
|
ReadFromStorage (SystemOne)
|
||||||
Expression (Projection)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Before ORDER BY and SELECT)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Distinct
|
||||||
|
Union
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Distinct
|
||||||
|
Union
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
|
ReadFromStorage (SystemOne)
|
||||||
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
ReadFromStorage (SystemOne)
|
ReadFromStorage (SystemOne)
|
||||||
Union
|
Union
|
||||||
Expression (Projection)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Before ORDER BY and SELECT)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
ReadFromStorage (SystemOne)
|
||||||
ReadFromStorage (SystemOne)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Projection)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
Expression (Before ORDER BY and SELECT)
|
ReadFromStorage (SystemOne)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
ReadFromStorage (SystemOne)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
Expression (Projection)
|
ReadFromStorage (SystemOne)
|
||||||
Expression (Before ORDER BY and SELECT)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
ReadFromStorage (SystemOne)
|
ReadFromStorage (SystemOne)
|
||||||
Distinct
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Union
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
Expression (Projection)
|
ReadFromStorage (SystemOne)
|
||||||
Expression (Before ORDER BY and SELECT)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
ReadFromStorage (SystemOne)
|
ReadFromStorage (SystemOne)
|
||||||
Expression (Projection)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Before ORDER BY and SELECT)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
ReadFromStorage (SystemOne)
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Distinct
|
|
||||||
Union
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Distinct
|
|
||||||
Union
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Union
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Distinct
|
Distinct
|
||||||
Union
|
Union
|
||||||
Expression (Projection)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Before ORDER BY and SELECT)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
ReadFromStorage (SystemOne)
|
||||||
ReadFromStorage (SystemOne)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Projection)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
Expression (Before ORDER BY and SELECT)
|
ReadFromStorage (SystemOne)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
ReadFromStorage (SystemOne)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
Expression (Projection)
|
ReadFromStorage (SystemOne)
|
||||||
Expression (Before ORDER BY and SELECT)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
ReadFromStorage (SystemOne)
|
ReadFromStorage (SystemOne)
|
||||||
Expression (Projection)
|
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Union
|
Union
|
||||||
Expression (Projection)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Before ORDER BY and SELECT)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
ReadFromStorage (SystemOne)
|
||||||
ReadFromStorage (SystemOne)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Projection)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
Expression (Before ORDER BY and SELECT)
|
ReadFromStorage (SystemOne)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
ReadFromStorage (SystemOne)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
Expression (Projection)
|
ReadFromStorage (SystemOne)
|
||||||
Expression (Before ORDER BY and SELECT)
|
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Union
|
Union
|
||||||
Expression (Projection)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Before ORDER BY and SELECT)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
ReadFromStorage (SystemOne)
|
||||||
ReadFromStorage (SystemOne)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Projection)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
Expression (Before ORDER BY and SELECT)
|
ReadFromStorage (SystemOne)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
Union
|
Union
|
||||||
Expression (Projection)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Before ORDER BY and SELECT)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
ReadFromStorage (SystemOne)
|
||||||
ReadFromStorage (SystemOne)
|
Expression (Projection + Before ORDER BY and SELECT)
|
||||||
Expression (Projection)
|
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
||||||
Expression (Before ORDER BY and SELECT)
|
ReadFromStorage (SystemOne)
|
||||||
SettingQuotaAndLimits (Set limits and quota after reading from storage)
|
|
||||||
ReadFromStorage (SystemOne)
|
|
||||||
|
@ -72,6 +72,94 @@ If you want to run only a single test such as the `/clickhouse/rbac/syntax/grant
|
|||||||
|
|
||||||
For more information, please see [Filtering](https://testflows.com/handbook/#Filtering) section in the [TestFlows Handbook].
|
For more information, please see [Filtering](https://testflows.com/handbook/#Filtering) section in the [TestFlows Handbook].
|
||||||
|
|
||||||
|
## How To Debug Why Test Failed
|
||||||
|
|
||||||
|
### Step 1: find which tests failed
|
||||||
|
|
||||||
|
If [TestFlows] check does not pass you should look at the end of the `test_run.txt.out.log` to find the list
|
||||||
|
of failing tests. For example,
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clickhouse_testflows_tests_volume
|
||||||
|
Start tests
|
||||||
|
➤ Dec 02,2020 22:22:24 /clickhouse
|
||||||
|
...
|
||||||
|
Failing
|
||||||
|
|
||||||
|
✘ [ Fail ] /clickhouse/rbac/syntax/grant privilege/grant privileges/privilege='SELECT', on=('db0.table0', 'db0.*', '*.*', 'tb0', '*'), allow_column=True, allow_introspection=False
|
||||||
|
✘ [ Fail ] /clickhouse/rbac/syntax/grant privilege/grant privileges
|
||||||
|
✘ [ Fail ] /clickhouse/rbac/syntax/grant privilege
|
||||||
|
✘ [ Fail ] /clickhouse/rbac/syntax
|
||||||
|
✘ [ Fail ] /clickhouse/rbac
|
||||||
|
✘ [ Fail ] /clickhouse
|
||||||
|
```
|
||||||
|
|
||||||
|
In this case the failing test is
|
||||||
|
|
||||||
|
```
|
||||||
|
/clickhouse/rbac/syntax/grant privilege/grant privileges/privilege='SELECT', on=('db0.table0', 'db0.*', '*.*', 'tb0', '*'), allow_column=True, allow_introspection=False
|
||||||
|
```
|
||||||
|
|
||||||
|
while the others
|
||||||
|
|
||||||
|
```
|
||||||
|
✘ [ Fail ] /clickhouse/rbac/syntax/grant privilege/grant privileges
|
||||||
|
✘ [ Fail ] /clickhouse/rbac/syntax/grant privilege
|
||||||
|
✘ [ Fail ] /clickhouse/rbac/syntax
|
||||||
|
✘ [ Fail ] /clickhouse/rbac
|
||||||
|
✘ [ Fail ] /clickhouse
|
||||||
|
```
|
||||||
|
|
||||||
|
failed because the first fail gets "bubble-up" the test execution tree all the way to the top level test which is the
|
||||||
|
`/clickhouse`.
|
||||||
|
|
||||||
|
### Step 2: download `test.log` that contains all raw messages
|
||||||
|
|
||||||
|
You need to download the `test.log` that contains all raw messages.
|
||||||
|
|
||||||
|
### Step 3: get messages for the failing test
|
||||||
|
|
||||||
|
Once you know the name of the failing test and you have the `test.log` that contains all the raw messages
|
||||||
|
for all the tests, you can use `tfs show test messages` command.
|
||||||
|
|
||||||
|
> You get the `tfs` command by installing [TestFlows].
|
||||||
|
|
||||||
|
For example,
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cat test.log | tfs show test messages "/clickhouse/rbac/syntax/grant privilege/grant privileges/privilege='SELECT', on=\('db0.table0', 'db0.\*', '\*.\*', 'tb0', '\*'\), allow_column=True, allow_introspection=False"
|
||||||
|
```
|
||||||
|
|
||||||
|
> Note: that characters that are treated as special in extended regular expressions need to be escaped. In this case
|
||||||
|
> we have to escape the `*`, `(`, and the `)` characters in the test name.
|
||||||
|
|
||||||
|
### Step 4: working with the `test.log`
|
||||||
|
|
||||||
|
You can use the `test.log` with many of the commands provided by the
|
||||||
|
`tfs` utility.
|
||||||
|
|
||||||
|
> See `tfs --help` for more information.
|
||||||
|
|
||||||
|
For example, you can get a list of failing tests from the `test.log` using the
|
||||||
|
`tfs show fails` command as follows
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cat test.log | tfs show fails
|
||||||
|
```
|
||||||
|
|
||||||
|
or get the results using the `tfs show results` command as follows
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cat test.log | tfs show results
|
||||||
|
```
|
||||||
|
|
||||||
|
or you can transform the log to see only the new fails using the
|
||||||
|
`tfs transform fail --new` command as follows
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cat test.log | tfs transform fails --new
|
||||||
|
```
|
||||||
|
|
||||||
[Python 3]: https://www.python.org/
|
[Python 3]: https://www.python.org/
|
||||||
[Ubuntu]: https://ubuntu.com/
|
[Ubuntu]: https://ubuntu.com/
|
||||||
[TestFlows]: https://testflows.com
|
[TestFlows]: https://testflows.com
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
|
v20.11.5.18-stable 2020-12-06
|
||||||
v20.11.4.13-stable 2020-11-20
|
v20.11.4.13-stable 2020-11-20
|
||||||
v20.11.3.3-stable 2020-11-13
|
v20.11.3.3-stable 2020-11-13
|
||||||
v20.11.2.1-stable 2020-11-11
|
v20.11.2.1-stable 2020-11-11
|
||||||
|
v20.10.6.27-stable 2020-12-06
|
||||||
v20.10.5.10-stable 2020-11-20
|
v20.10.5.10-stable 2020-11-20
|
||||||
v20.10.4.1-stable 2020-11-13
|
v20.10.4.1-stable 2020-11-13
|
||||||
v20.10.3.30-stable 2020-10-29
|
v20.10.3.30-stable 2020-10-29
|
||||||
v20.10.2.20-stable 2020-10-23
|
v20.10.2.20-stable 2020-10-23
|
||||||
|
v20.9.7.11-stable 2020-12-07
|
||||||
v20.9.6.14-stable 2020-11-20
|
v20.9.6.14-stable 2020-11-20
|
||||||
v20.9.5.5-stable 2020-11-13
|
v20.9.5.5-stable 2020-11-13
|
||||||
v20.9.4.76-stable 2020-10-29
|
v20.9.4.76-stable 2020-10-29
|
||||||
v20.9.3.45-stable 2020-10-09
|
v20.9.3.45-stable 2020-10-09
|
||||||
v20.9.2.20-stable 2020-09-22
|
v20.9.2.20-stable 2020-09-22
|
||||||
|
v20.8.8.2-lts 2020-12-07
|
||||||
v20.8.7.15-lts 2020-11-20
|
v20.8.7.15-lts 2020-11-20
|
||||||
v20.8.6.6-lts 2020-11-13
|
v20.8.6.6-lts 2020-11-13
|
||||||
v20.8.5.45-lts 2020-10-29
|
v20.8.5.45-lts 2020-10-29
|
||||||
|
|
Loading…
Reference in New Issue
Block a user