前提条件
この記事の例では、以下が必要です。
- 稼働中の ClickHouse server インスタンス
curlがインストールされていること。Ubuntu または Debian では、sudo apt install curlを実行するか、インストール方法についてはこのドキュメントを参照してください。
概要
HTTPインターフェイスを使用すると、任意のプラットフォーム上で、任意のプログラミング言語から、REST API の形式で ClickHouse を利用できます。HTTPインターフェイスはネイティブインターフェイスより機能が制限されていますが、より幅広い言語をサポートしています。
デフォルトでは、clickhouse-server は次のポートで待ち受けます。
- HTTP はポート 8123
- HTTPS はポート 8443 (有効にした場合)
パラメータを指定せずに GET / リクエストを送信すると、文字列 "Ok." とともに 200 のレスポンスコードが返されます。
$ curl 'http://localhost:8123/'
Ok."Ok." は http_server_default_response で定義されているデフォルト値で、必要に応じて変更できます。
あわせて参照してください: HTTPレスポンスコードに関する注意点。
Webユーザーインターフェイス
ClickHouse には Webユーザーインターフェイスが含まれており、次のアドレスからアクセスできます。
http://localhost:8123/playWeb UI は、クエリ実行中の進行状況の表示、クエリのキャンセル、結果のストリーミングに対応しています。 また、クエリパイプラインのチャートやグラフを表示するための隠し機能も備えています。
クエリが正常に実行されるとダウンロードボタンが表示され、CSV、TSV、JSON、JSONLines、Parquet、Markdown、または ClickHouse がサポートする任意のカスタムフォーマットなど、さまざまなフォーマットでクエリ結果をダウンロードできます。このダウンロード機能では、クエリを再実行せずに結果を効率よく取得するためにクエリキャッシュを使用します。UI に多数あるページのうち 1 ページしか表示されていない場合でも、完全な結果セットがダウンロードされます。
Web UI は、プロフェッショナルユーザー向けに設計されています。

ヘルスチェック用スクリプトでは GET /ping リクエストを使用してください。このハンドラーは常に "Ok." を返します (末尾に改行付き) 。バージョン 18.12.13 以降で利用できます。レプリカの遅延を確認するには、関連項目として /replicas_status も参照してください。
$ curl 'http://localhost:8123/ping'
Ok.
$ curl 'http://localhost:8123/replicas_status'
Ok.HTTP/HTTPS 経由でのクエリ
HTTP/HTTPS 経由でクエリを実行する方法は 3 つあります。
- リクエストを URL の 'query' パラメータとして送信する
- POST メソッドを使用する
- クエリの先頭を 'query' パラメータで送り、残りを POST で送信する
成功した場合は、レスポンスコード 200 と結果がレスポンスボディで返されます。 エラーが発生した場合は、レスポンスコード 500 とエラーの説明テキストがレスポンスボディで返されます。
GET リクエストは 'readonly' です。つまり、データを変更するクエリでは POST メソッドしか使用できません。 クエリ自体は、POST ボディまたは URL パラメータのいずれかで送信できます。いくつか例を見てみましょう。
以下の例では、curl を使用してクエリ SELECT 1 を送信しています。スペースには URL エンコード %20 を使用している点に注意してください。
curl 'http://localhost:8123/?query=SELECT%201'1この例では、-nv (非冗長) および -O- パラメータを指定した wget を使用し、結果をターミナルに出力します。
この場合、スペースを URL エンコードする必要はありません。
wget -nv -O- 'http://localhost:8123/?query=SELECT 1'1この例では、生のHTTPリクエストをパイプでnetcatに渡します:
echo -ne 'GET /?query=SELECT%201 HTTP/1.0\r\n\r\n' | nc localhost 8123HTTP/1.0 200 OK
X-ClickHouse-Summary: {"read_rows":"1","read_bytes":"1","written_rows":"0","written_bytes":"0","total_rows_to_read":"1","result_rows":"0","result_bytes":"0","elapsed_ns":"4505959","memory_usage":"1111711"}
Date: Tue, 11 Nov 2025 18:16:01 GMT
Connection: Close
Content-Type: text/tab-separated-values; charset=UTF-8
Access-Control-Expose-Headers: X-ClickHouse-Query-Id,X-ClickHouse-Summary,X-ClickHouse-Server-Display-Name,X-ClickHouse-Format,X-ClickHouse-Timezone,X-ClickHouse-Exception-Code,X-ClickHouse-Exception-Tag
X-ClickHouse-Server-Display-Name: MacBook-Pro.local
X-ClickHouse-Query-Id: ec0d8ec6-efc4-4e1d-a14f-b748e01f5294
X-ClickHouse-Format: TabSeparated
X-ClickHouse-Timezone: Europe/London
X-ClickHouse-Exception-Tag: dngjzjnxkvlwkeua
1ご覧のとおり、curl コマンドはやや扱いづらく、空白は URL エスケープする必要があります。
wget はすべて自動的にエスケープしてくれますが、keep-alive と Transfer-Encoding: chunked を使用する HTTP 1.1 では正常に動作しないため、使用は推奨していません。
$ 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で送ると、これら2つのデータ部分の間に改行が挿入されます。 たとえば、これは動作しません。
$ echo 'ECT 1' | curl 'http://localhost:8123/?query=SEL' --data-binary @-
Code: 59, e.displayText() = DB::Exception: Syntax error: failed at position 0: SEL
ECT 1
, expected One of: SHOW TABLES, SHOW DATABASES, SELECT, INSERT, CREATE, ATTACH, RENAME, DROP, DETACH, USE, SET, OPTIMIZE., e.what() = DB::Exceptionデフォルトでは、データは TabSeparated フォーマットで返されます。
別のフォーマットを指定するには、クエリで FORMAT 句を使用します。例:
wget -nv -O- 'http://localhost:8123/?query=SELECT 1, 2, 3 FORMAT JSON'{
"meta":
[
{
"name": "1",
"type": "UInt8"
},
{
"name": "2",
"type": "UInt8"
},
{
"name": "3",
"type": "UInt8"
}
],
"data":
[
{
"1": 1,
"2": 2,
"3": 3
}
],
"rows": 1,
"statistics":
{
"elapsed": 0.000515,
"rows_read": 1,
"bytes_read": 1
}
}TabSeparated 以外のデフォルトフォーマットを指定するには、default_format URL パラメータを使用できます。X-ClickHouse-Format ヘッダーを使用すると、レスポンスのフォーマットを明示的に指定できます。これは output_format 設定のエイリアスであるため、クエリ内の FORMAT 句もオーバーライドします。INSERT のリクエストボディの解析方法が変更されることはありません。その場合は input_format または format を使用してください。
$ echo 'SELECT 1 FORMAT Pretty' | curl 'http://localhost:8123/?' --data-binary @-
┏━━━┓
┃ 1 ┃
┡━━━┩
│ 1 │
└───┘POSTメソッドでは、パラメータ化クエリを使用できます。パラメータは、{name:Type} のように、パラメータ名と型を中かっこで囲んで指定します。パラメータの値は param_name で渡します。
$ curl -X POST -F 'query=select {p1:UInt8} + {p2:UInt8}' -F "param_p1=3" -F "param_p2=4" 'http://localhost:8123/'
7URL パス経由でテーブルにアクセスし、クエリを構築する
ClickHouse 26.8 以降で利用できます。
HTTP インターフェイスでは、URL パスをデータベース、テーブル、出力フォーマット、圧縮方式として解釈できます。URL パラメータで結果を指定できるため、単純な読み取りリクエストに SQL は必要ありません。これらの機能はデフォルトで無効になっているため、明示的に有効化する必要があります。
パスルーティングを有効にする
パスの解釈は、次の 2 つのレベルで有効化されます。
- HTTP インターフェイスがパス形式のリクエストをクエリハンドラーにルーティングできるようにする、サーバーレベルの
http_allow_path_requests構成設定を有効にします。
<clickhouse>
<http_allow_path_requests>1</http_allow_path_requests>
</clickhouse>- 必要なユーザーごとの設定を有効にします。
| 設定 | 効果 |
|---|---|
http_allow_table_as_file |
最後のパス要素をtable、table.format、またはtable.format.compressionとして解釈します。 |
http_allow_database_as_path |
先頭の/database/パス要素を現在のデータベースとして解釈します。 |
http_allow_filters_as_path |
Hive形式の/name=value/パス要素をWHEREフィルターとして解釈します。 |
http_allow_filters_as_unrecognized_url_parameters |
認識されないURLパラメータをWHEREフィルターとして解釈します。 |
ファイルとしてテーブルにアクセスする
http_allow_table_as_file を有効にすると、/table.format.compression へのリクエストは SELECT * FROM table として処理されます。/database/table.format.compression を使用するには、http_allow_database_as_path を有効にします。
# SELECT * FROM my_db.hits, formatted as CSV
curl 'http://localhost:8123/my_db/hits.csv'
# The same result, compressed with gzip
curl 'http://localhost:8123/my_db/hits.csv.gz' | gzip -dフォーマットおよび圧縮の拡張子は大文字と小文字を区別せずに認識されるため、hits.csv と hits.CSV は同等です。
明示的に指定した format または output_format URL パラメータは、パス内のフォーマットを上書きします。一方、default_format は上書きしません。これは、他の指定でフォーマットが選択されていない場合にのみ使用するフォーマットを指定するものであり、パスの拡張子のほうが優先されるためです。明示的に指定した compression パラメータは、パス内の圧縮と一致している必要があります。値が競合する場合は例外が発生します。
クエリを構築する
以下の設定では、ベースクエリを派生テーブルとしてラップします。これらは互いに、また既存のクエリと組み合わせて使用できます。HTTP URL パラメータ、クエリ内の SETTINGS 句、またはユーザープロファイルで指定できます。
| 設定 | 効果 |
|---|---|
select |
SELECT <expression_list> FROM (…) |
filter |
WHERE <expression> を追加します。複数の filter URL パラメータは AND で結合されます。 |
order |
ORDER BY <expression_list> を追加します。 |
sort |
識別子またはカラム位置をカンマ区切りで指定したリストに基づいて ORDER BY を追加します。各項目には、sort=a,-b のように、任意で + (昇順) または - (降順) のプレフィックスを付けられます。order と組み合わせることはできません。 |
limit and offset |
LIMIT <n> OFFSET <m> を追加します。どちらも、末尾選択用の負の値と、行の割合を表す小数値を受け付けます。 |
page |
offset = limit * (page - 1) を設定します。limit が必要であり、offset と組み合わせることはできません。 |
# Filter my_db.hits, sort by a descending, and return the first 10 rows
curl 'http://localhost:8123/my_db/hits?filter=a%3E0&sort=-a&limit=10'
# Return the second page of 100 rows
curl 'http://localhost:8123/my_db/hits?limit=100&page=2'既存のクエリを変更する
構築設定はパスリクエストだけに適用されるものではなく、自分で記述したクエリにも影響します。クエリは派生テーブルになるため、設定はクエリにマージされるのではなく、その結果に適用されます。たとえば、?query=SELECT a, b FROM hits&filter=a > 0&sort=-b&limit=10 は次のように実行されます。
SELECT * FROM (SELECT a, b FROM hits) WHERE a > 0 ORDER BY b DESC LIMIT 10これは、保存済みダッシュボードのクエリ、predefined_query_handler、または URL パラメータのみを追加できるクライアントなど、別の場所で定義されたクエリの結果をページング、ソート、絞り込む場合に便利です。
# Page through the result of an arbitrary query without editing the query text
curl 'http://localhost:8123/?query=SELECT+a,+b+FROM+hits+GROUP+BY+a,+b&limit=100&page=3'
# Keep only some of the resulting columns and rows
curl -G 'http://localhost:8123/' --data-urlencode 'query=SELECT * FROM hits' --data-urlencode 'select=a, b' --data-urlencode 'filter=b != 0'
# The last 5 rows of an aggregate (a negative `limit` selects from the tail)
curl 'http://localhost:8123/?query=SELECT+a,+count()+FROM+hits+GROUP+BY+a+ORDER+BY+a&limit=-5'設定はクエリを書き換えるのではなくラップするため、FORMAT 句やクエリ内の ORDER BY と併用でき、INSERT が書き込む行を変更することもありません。INSERT ... SELECT ステートメントに指定した構築設定は、ソースの SELECT ではなく、そのステートメント自体の (空の) 結果を形成します。ソースを形成するには、設定を SELECT 自体の SETTINGS 句に指定します。
-- Inserts all 10 rows: `limit` applies to the INSERT statement, not to its SELECT
INSERT INTO t SETTINGS limit = 2 SELECT number FROM numbers(10);
-- Inserts 2 rows: `limit` applies to the SELECT itself
INSERT INTO t SELECT number FROM numbers(10) SETTINGS limit = 2;フォーマットと圧縮のオーバーライド
| 設定 | 効果 |
|---|---|
output_format |
出力フォーマットをオーバーライドします。クエリの FORMAT 句、パス拡張子、format、default_format よりも優先されます。X-ClickHouse-Format ヘッダーでも設定できます。 |
input_format |
INSERT の入力フォーマットをオーバーライドします。クエリの FORMAT 句および format よりも優先されます。 |
format |
方向固有の設定が指定されていない場合、入出力両方のフォーマットをオーバーライドします。 |
default_format |
クエリに FORMAT 句やパス拡張子がなく、他のフォーマットのオーバーライドもない場合に、出力フォーマットを設定します。 |
compression |
たとえば compression=gz を指定して、レスポンスボディを圧縮します。これは HTTP Content-Encoding および ClickHouse ネイティブの compress パラメータとは別のものです。 |
フォーマット設定は、ネイティブクライアントや clickhouse-local など、他のプロトコルでも使用できます。input_format と output_format は、それぞれ --input-format および --output-format オプションに対応します。--format オプションは、clickhouse-local では双方向の format 設定に対応しますが、clickhouse-client では従来どおり出力専用として扱われ、output_format に対応します。
compression は HTTP レスポンスの整形に固有で、クエリ実行前に処理されます。HTTP URL パラメータ、パス拡張子、またはユーザープロファイルで指定してください。クエリ内の SETTINGS 句では使用できません。
バイナリまたは圧縮された HTTP レスポンスには、Content-Disposition: attachment; filename=… ヘッダーが含まれます。ファイル名は URL パスから導出され、パスから取得できない場合は result.<format>.<compression> が使用されます。
クエリでパステーブルを使用する
パスがテーブルを示し、query パラメータも指定した場合、パステーブルは implicit_table_at_top_level を介して公開されます。FROM 句のない SELECT はパステーブルから読み取ります。
# Read columns a and b from my_db.hits without a FROM clause
curl 'http://localhost:8123/my_db/hits.CSV?query=SELECT+a,+b'クエリにすでに FROM 句が含まれている場合、パス部分ではダウンロードするファイル名のみを指定します。
HTTP/HTTPS 経由の INSERT クエリ
INSERT クエリでは、データの送信に POST メソッドを使用する必要があります。この場合、クエリの先頭部分を URL パラメーターに記述し、挿入するデータは POST で渡せます。挿入するデータとしては、たとえば MySQL のタブ区切りの dump を使用できます。このように、INSERT クエリは MySQL の LOAD DATA LOCAL INFILE の代替として使用できます。
例
テーブルを作成するには:
$ echo 'CREATE TABLE t (a UInt8) ENGINE = Memory' | curl 'http://localhost:8123/' --data-binary @-データを挿入するには、使い慣れた INSERT クエリを使用します。
$ echo 'INSERT INTO t VALUES (1),(2),(3)' | curl 'http://localhost:8123/' --data-binary @-クエリとは別にデータを送信するには、
$ echo '(4),(5),(6)' | curl 'http://localhost:8123/?query=INSERT%20INTO%20t%20VALUES' --data-binary @-任意のデータフォーマットを指定できます。たとえば、INSERT INTO t VALUES の記述時に使用するものと同じ 'Values' フォーマットを指定できます:
$ echo '(7),(8),(9)' | curl 'http://localhost:8123/?query=INSERT%20INTO%20t%20FORMAT%20Values' --data-binary @-タブ区切りのダンプからデータを挿入するには、適切なフォーマットを指定します。
$ echo -ne '10\n11\n12\n' | curl 'http://localhost:8123/?query=INSERT%20INTO%20t%20FORMAT%20TabSeparated' --data-binary @-テーブルの内容を表示するには:
$ curl 'http://localhost:8123/?query=SELECT%20a%20FROM%20t'
7
8
9
10
11
12
1
2
3
4
5
6テーブルを削除するには:
$ echo 'DROP TABLE t' | curl 'http://localhost:8123/' --data-binary @-データテーブルを返さない正常なリクエストでは、レスポンスボディは空になります。
圧縮
圧縮は、大量のデータを送信する際のネットワークトラフィックを削減したり、圧縮済みのダンプを直接作成したりする場合に利用できます。
データ送信時には、ClickHouse の内部圧縮フォーマットを使用できます。圧縮されたデータは標準的ではないフォーマットのため、扱うには clickhouse-compressor プログラムが必要です。これは clickhouse-client パッケージとともにデフォルトでインストールされます。
データの insert 効率を高めるには、http_native_compression_disable_checksumming_on_decompress 設定を使用して、サーバー側のチェックサム検証を無効にしてください。
URL に compress=1 を指定すると、サーバーは送信するデータを圧縮します。URL に decompress=1 を指定すると、サーバーは POST method で渡されたデータを展開します。
HTTP 圧縮 を使用することもできます。ClickHouse は次の圧縮方式をサポートしています。
gzipbrdeflatexzzstdlz4bz2snappy
圧縮された POST リクエストを送信するには、リクエスト header に Content-Encoding: compression_method を追加してください。
ClickHouse にレスポンスを圧縮させるには、リクエストに Accept-Encoding: compression_method header を追加してください。
すべての圧縮方式で、http_zlib_compression_level 設定を使用してデータの圧縮レベルを設定できます。
例
圧縮データをサーバーへ送信するには:
echo "SELECT 1" | gzip -c | \
curl -sS --data-binary @- -H 'Content-Encoding: gzip' 'http://localhost:8123/'サーバーから圧縮データアーカイブを受け取るには:
curl -vsS "http://localhost:8123/?enable_http_compression=1" \
-H 'Accept-Encoding: gzip' --output result.gz -d 'SELECT number FROM system.numbers LIMIT 3'
zcat result.gz
0
1
2サーバーから圧縮データを受信し、gunzip で展開後のデータを受け取るには:
curl -sS "http://localhost:8123/?enable_http_compression=1" \
-H 'Accept-Encoding: gzip' -d 'SELECT number FROM system.numbers LIMIT 3' | gunzip -
0
1
2デフォルトデータベース
database URL パラメータまたは X-ClickHouse-Database ヘッダーで、デフォルトのデータベースを指定できます。
echo 'SELECT number FROM numbers LIMIT 10' | curl 'http://localhost:8123/?database=system' --data-binary @-
0
1
2
3
4
5
6
7
8
9デフォルトでは、サーバー設定に登録されているデータベースが既定のデータベースとして使用されます。初期状態では、これは default という名前のデータベースです。別の方法として、テーブル名の前にドット区切りでデータベース名を付けて、いつでもデータベースを指定できます。
認証
ユーザー名とパスワードは、次の3つの方法のいずれかで指定できます。
- HTTP Basic認証を使用する方法。
例:
echo 'SELECT 1' | curl 'http://user:password@localhost:8123/' -d @-userおよびpasswordの URL パラメータ内
例:
echo 'SELECT 1' | curl 'http://localhost:8123/?user=user&password=password' -d @-- 'X-ClickHouse-User' および 'X-ClickHouse-Key' ヘッダーを使用する
例:
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$ echo 'SELECT number FROM system.numbers LIMIT 10' | curl 'http://localhost:8123/?' --data-binary @-
0
1
2
3
4
5
6
7
8
9詳細については、以下を参照してください。
HTTPプロトコルでClickHouseセッションを使用する
HTTPプロトコルでもClickHouseセッションを使用できます。これを行うには、リクエストに session_id GET パラメータを追加する必要があります。セッションIDには任意の文字列を使用できます。
デフォルトでは、セッションは60秒間非アクティブな状態が続くと終了します。このタイムアウト (秒単位) を変更するには、サーバー設定の default_session_timeout を変更するか、リクエストに session_timeout GET パラメータを追加します。
セッションの状態を確認するには、session_check=1 パラメータを使用します。1つのセッション内で同時に実行できるクエリは1つだけです。
クエリの進行状況に関する情報は、X-ClickHouse-Progress レスポンスヘッダーで受け取ることができます。これを行うには、send_progress_in_http_headers を有効にします。
以下はヘッダーシーケンスの例です:
X-ClickHouse-Progress: {"read_rows":"261636","read_bytes":"2093088","total_rows_to_read":"1000000","elapsed_ns":"14050417","memory_usage":"22205975"}
X-ClickHouse-Progress: {"read_rows":"654090","read_bytes":"5232720","total_rows_to_read":"1000000","elapsed_ns":"27948667","memory_usage":"83400279"}
X-ClickHouse-Progress: {"read_rows":"1000000","read_bytes":"8000000","total_rows_to_read":"1000000","elapsed_ns":"38002417","memory_usage":"80715679"}使用可能なヘッダーフィールドは次のとおりです。
| Header field | Description |
|---|---|
read_rows |
読み取られた行数。 |
read_bytes |
読み取られたデータ量 (バイト) 。 |
total_rows_to_read |
読み取る予定の行の総数。 |
written_rows |
書き込まれた行数。 |
written_bytes |
書き込まれたデータ量 (バイト) 。 |
elapsed_ns |
クエリの実行時間 (ナノ秒) 。 |
memory_usage |
クエリで使用されたメモリ量 (バイト) 。 (v25.11 以降で利用可能) |
実行中のリクエストは、HTTP接続が失われても自動的には停止しません。パースとデータのフォーマットはサーバー側で行われるため、ネットワーク越しでは非効率になる場合があります。
次のオプションパラメーターがあります。
| Parameters | Description |
|---|---|
query_id (optional) |
クエリ ID として渡せます (任意の文字列) 。replace_running_query |
quota_key (optional) |
クォータキーとして渡せます (任意の文字列) 。"クォータ" |
HTTP インターフェイスでは、クエリのために外部データ (外部一時テーブル) を渡すこともできます。詳細については、"クエリ処理用の外部データ" を参照してください。
レスポンスのバッファリング
レスポンスのバッファリングはサーバー側で有効にできます。このために、次のURLパラメータが用意されています。
buffer_sizewait_end_of_query
次の設定も使用できます。
buffer_size は、サーバーのメモリ内で結果をバッファリングするバイト数を決定します。結果のボディがこのしきい値を超える場合、バッファはHTTPチャネルに書き込まれ、残りのデータはHTTPチャネルに直接送信されます。
レスポンス全体が確実にバッファリングされるようにするには、wait_end_of_query=1 を設定します。この場合、メモリに格納されないデータは、一時サーバーファイルにバッファリングされます。
たとえば:
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'クエリパラメータでロールを設定する
この機能は ClickHouse 24.4 で追加されました。
状況によっては、ステートメント自体を実行する前に、まず付与済みのロールを設定する必要があります。
ただし、マルチステートメントは許可されていないため、SET ROLE とステートメントを一緒に送信することはできません。
curl -sS "http://localhost:8123" --data-binary "SET ROLE my_role;SELECT * FROM my_table;"上記のコマンドを実行すると、エラーが発生します:
Code: 62. DB::Exception: Syntax error (Multi-statements are not allowed)この制限を回避するには、代わりに role クエリパラメータを使用してください。
curl -sS "http://localhost:8123?role=my_role" --data-binary "SELECT * FROM my_table;"これは、ステートメントの前に SET ROLE my_role を実行するのと同じです。
さらに、複数の role クエリパラメータを指定することも可能です。
curl -sS "http://localhost:8123?role=my_role&role=my_other_role" --data-binary "SELECT * FROM my_table;"この場合、?role=my_role&role=my_other_role は、ステートメントの前に SET ROLE my_role, my_other_role を実行するのと同じように機能します。
HTTPレスポンスコードに関する注意点
HTTPプロトコルの制約上、HTTP 200のレスポンスコードでも、クエリが成功したとは限りません。
以下に例を示します。
curl -v -Ss "http://localhost:8123/?max_block_size=1&query=select+sleepEachRow(0.001),throwIf(number=2)from+numbers(5)"
* Trying 127.0.0.1:8123...
...
< HTTP/1.1 200 OK
...
Code: 395. DB::Exception: Value passed to 'throwIf' function is non-zero: while executing 'FUNCTION throwIf(equals(number, 2) :: 1) -> throwIf(equals(number, 2))この挙動が発生するのは、HTTP プロトコル の性質によるものです。まず HTTP ヘッダー が HTTP ステータスコード 200 とともに送信され、その後に HTTP ボディ が続き、さらにエラーがプレーンテキストとして ボディ 内に挿入されます。
この挙動は、Native、TSV、JSON など、どのフォーマットを使用しているかに関係ありません。エラーメッセージは常にレスポンスストリームの途中に現れます。
この問題は、wait_end_of_query=1 (レスポンスのバッファリング) を有効にすることで緩和できます。この場合、HTTP ヘッダー の送信はクエリ全体の処理が完了するまで遅延されます。ただし、これでも問題が完全に解決するわけではありません。結果は依然として http_response_buffer_size の範囲内に収まる必要があり、さらに send_progress_in_http_headers などの設定によって ヘッダー の送信遅延が妨げられることもあるためです。
ClickHouse では、このような例外は http_write_exception_in_output_format=0 (デフォルト) の場合、使用するフォーマット (Native、TSV、JSON など) に関係なく、以下のような一貫した例外フォーマットになります。そのため、クライアント側でエラーメッセージを簡単にパースして抽出できます。
\r\n
__exception__\r\n
<TAG>\r\n
<error message>\r\n
<message_length> <TAG>\r\n
__exception__\r\nここで、<TAG> は 16 バイトのランダムなタグで、X-ClickHouse-Exception-Tag レスポンスヘッダーで送信されるタグと同じものです。
<error message> は実際の例外メッセージです (正確な長さは <message_length> で確認できます) 。上で説明した例外ブロック全体のサイズは最大 16 KiB です。
以下は JSON フォーマットの例です
$ curl -v -Ss "http://localhost:8123/?max_block_size=1&query=select+sleepEachRow(0.001),throwIf(number=2)from+numbers(5)+FORMAT+JSON"
...
{
"meta":
[
{
"name": "sleepEachRow(0.001)",
"type": "UInt8"
},
{
"name": "throwIf(equals(number, 2))",
"type": "UInt8"
}
],
"data":
[
{
"sleepEachRow(0.001)": 0,
"throwIf(equals(number, 2))": 0
},
{
"sleepEachRow(0.001)": 0,
"throwIf(equals(number, 2))": 0
}
__exception__
dmrdfnujjqvszhav
Code: 395. DB::Exception: Value passed to 'throwIf' function is non-zero: while executing 'FUNCTION throwIf(equals(__table1.number, 2_UInt8) :: 1) -> throwIf(equals(__table1.number, 2_UInt8)) UInt8 : 0'. (FUNCTION_THROW_IF_VALUE_IS_NON_ZERO) (version 25.11.1.1)
262 dmrdfnujjqvszhav
__exception__以下はCSVフォーマットの同様の例です
$ curl -v -Ss "http://localhost:8123/?max_block_size=1&query=select+sleepEachRow(0.001),throwIf(number=2)from+numbers(5)+FORMAT+CSV"
...
<
0,0
0,0
__exception__
rumfyutuqkncbgau
Code: 395. DB::Exception: Value passed to 'throwIf' function is non-zero: while executing 'FUNCTION throwIf(equals(__table1.number, 2_UInt8) :: 1) -> throwIf(equals(__table1.number, 2_UInt8)) UInt8 : 0'. (FUNCTION_THROW_IF_VALUE_IS_NON_ZERO) (version 25.11.1.1)
262 rumfyutuqkncbgau
__exception__パラメータ付きクエリ
パラメータ付きのクエリを作成し、対応する HTTP リクエストパラメータから値を渡せます。詳しくは、CLI のパラメータ付きクエリを参照してください。
例
$ curl -sS "<address>?param_id=2¶m_phrase=test" -d "SELECT * FROM table WHERE int_column = {id:UInt8} and string_column = {phrase:String}"URL パラメータ内のタブ
クエリパラメータは escaped フォーマットとして解析されます。これには、たとえば NULL を \N として曖昧さなく解析できるといった利点があります。つまり、タブ文字は \t (または \ とタブ文字) としてエンコードする必要があります。たとえば、次の例では abc と 123 の間に実際のタブが含まれており、入力文字列は 2 つの値に分割されます。
curl -sS "http://localhost:8123" -d "SELECT splitByChar('\t', 'abc 123')"['abc','123']ただし、URLパラメータで %09 を使って実際のタブ文字をエンコードしようとしても、正しくパースされません:
curl -sS "http://localhost:8123?param_arg1=abc%09123" -d "SELECT splitByChar('\t', {arg1:String})"
Code: 457. DB::Exception: Value abc 123 cannot be parsed as String for query parameter 'arg1' because it isn't parsed completely: only 3 of 7 bytes was parsed: abc. (BAD_QUERY_PARAMETER) (version 23.4.1.869 (official build))URL パラメータを使用する場合、\t は %5C%09 にエンコードする必要があります。例:
curl -sS "http://localhost:8123?param_arg1=abc%5C%09123" -d "SELECT splitByChar('\t', {arg1:String})"['abc','123']事前定義済み HTTP インターフェイス
ClickHouse は、HTTP インターフェイス経由で特定のクエリをサポートしています。たとえば、次のようにテーブルにデータを書き込むことができます。
$ echo '(4),(5),(6)' | curl 'http://localhost:8123/?query=INSERT%20INTO%20t%20VALUES' --data-binary @-ClickHouse は、Prometheus exporter のようなサードパーティーツールとの連携を容易にする、事前定義済み HTTP インターフェイスもサポートしています。では、例を見てみましょう。
まず、このセクションをサーバー設定ファイルに追加します。
http_handlers は複数の rule を含むように設定します。ClickHouse は受信した HTTP リクエストを rule で事前定義された種類に照らして照合し、最初に一致したルールのハンドラーを実行します。一致に成功すると、ClickHouse は対応する事前定義済みクエリを実行します。
<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 に直接リクエストできます。
$ 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=10
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0","elapsed_ns":"662334","memory_usage":"8451671"}
<
# HELP "Query" "実行中のクエリ数"
# TYPE "Query" counter
"Query" 1
# HELP "Merge" "実行中のバックグラウンドマージ数"
# TYPE "Merge" counter
"Merge" 0
# HELP "PartMutation" "ミューテーション数 (ALTER DELETE/UPDATE)"
# TYPE "PartMutation" counter
"PartMutation" 0
# HELP "ReplicatedFetch" "レプリカからフェッチ中のデータパーツ数"
# TYPE "ReplicatedFetch" counter
"ReplicatedFetch" 0
# HELP "ReplicatedSend" "レプリカへ送信中のデータパーツ数"
# TYPE "ReplicatedSend" counter
"ReplicatedSend" 0
* Connection #0 to host localhost left intact
* Connection #0 to host localhost left intacthttp_handlers の設定オプションは次のとおりです。
rule では、以下のパラメータを設定できます。
methodheadersurlfull_urlhandler
各項目については以下で説明します。
-
methodは、HTTPリクエストの method 部分の照合を担当します。methodは、HTTPプロトコルにおける [method] (https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) の定義に完全に準拠しています。これは任意の設定です。設定ファイルで定義されていない場合、 HTTPリクエストの method 部分は照合されません。 -
urlは、HTTPリクエストの URL 部分 (パスとクエリ文字列) の照合を担当します。urlにregex:プレフィックスが付いている場合は、RE2 の正規表現を使用します。 これは任意の設定です。設定ファイルで定義されていない場合、HTTPリクエストの URL 部分は照合されません。 -
full_urlはurlと同じですが、schema://host:port/path?query_stringのような完全な URL を含みます。 注意: ClickHouse は "virtual hosts" をサポートしていないため、hostは IP アドレスです (Hostヘッダーの値ではありません) 。 -
empty_query_string- リクエストにクエリ文字列 (?query_string) が含まれていないことを保証します -
headersは、HTTPリクエストのヘッダー部分の照合を担当します。RE2 の正規表現と互換性があります。これは任意の 設定です。設定ファイルで定義されていない場合、HTTPリクエストのヘッダー部分は照合されません。 -
handlerには主要な処理部分が含まれます。指定できる
typeは次のとおりです:また、次のパラメータがあります:
query—predefined_query_handlertype で使用し、ハンドラーが呼び出されたときにクエリを実行します。query_param_name—dynamic_query_handlertype で使用し、HTTPリクエストパラメータからquery_param_nameの値に対応する値を抽出して実行します。status—statictype で使用し、レスポンスのステータスコードを指定します。content_type— 任意の type で使用し、レスポンスの content-type を指定します。http_response_headers— 任意の type で使用し、レスポンスヘッダーの map を指定します。content type の設定にも使用できます。response_content—statictype で使用し、クライアントに送信するレスポンス内容を指定します。プレフィックス 'file://' または 'config://' を使用する場合は、file または設定から内容を取得してクライアントに送信します。user- クエリの実行に使用する user です (default user はdefaultです) 。 注意: この user の password を指定する必要はありません。
異なる type の設定方法については、次で説明します。
predefined_query_handler
predefined_query_handler では、Settings と query_params の値を設定できます。predefined_query_handler 型では query を設定できます。
query の値は predefined_query_handler 用の事前定義済みクエリで、HTTP リクエストが一致すると ClickHouse によって実行され、その結果が返されます。これは必須の設定です。
次の例では、max_threads および max_final_threads の設定値を定義し、その後 system table にクエリして、これらの設定が正しく適用されたかどうかを確認します。
たとえば:
<http_handlers>
<rule>
<url><![CDATA[regex:/query_param_with_url/(?P<name_1>[^/]+)]]></url>
<methods>GET</methods>
<headers>
<XXX>TEST_HEADER_VALUE</XXX>
<PARAMS_XXX><![CDATA[regex:(?P<name_2>[^/]+)]]></PARAMS_XXX>
</headers>
<handler>
<type>predefined_query_handler</type>
<query>
SELECT name, value FROM system.settings
WHERE name IN ({name_1:String}, {name_2:String})
</query>
</handler>
</rule>
<defaults/>
</http_handlers>curl -H 'XXX:TEST_HEADER_VALUE' -H 'PARAMS_XXX:max_final_threads' 'http://localhost:8123/query_param_with_url/max_threads?max_threads=1&max_final_threads=2'
max_final_threads 2
max_threads 1仮想パラメータ _request_body
URLパラメータ、ヘッダー、クエリパラメータに加えて、predefined_query_handler は特殊な仮想パラメータ _request_body もサポートしています。
これは、生の HTTP リクエストボディを文字列として保持します。
これにより、任意のデータフォーマットを受け付け、それをクエリ内で処理できる柔軟な REST API を作成できます。
たとえば、_request_body を使用して、POST リクエストで JSON データを受け取り、それをテーブルに挿入する REST エンドポイント を実装できます。
<http_handlers>
<rule>
<methods>POST</methods>
<url>/api/events</url>
<handler>
<type>predefined_query_handler</type>
<query>
INSERT INTO events (id, data)
SELECT {id:UInt32}, {_request_body:String}
</query>
</handler>
</rule>
<defaults/>
</http_handlers>その後、このエンドポイントへデータを送信できます。
curl -X POST 'http://localhost:8123/api/events?id=123' \
-H 'Content-Type: application/json' \
-d '{"user": "john", "action": "login", "timestamp": "2024-01-01T10:00:00Z"}'dynamic_query_handler
dynamic_query_handler では、クエリを HTTP リクエストのパラメータとして記述します。predefined_query_handler との違いは、predefined_query_handler ではクエリを設定ファイルに記述する点です。query_param_name は dynamic_query_handler で設定できます。
ClickHouse は、HTTP リクエストの URL から query_param_name に対応する値を取り出して実行します。query_param_name のデフォルト値は /query です。これは任意の設定です。設定ファイルに定義がない場合、このパラメータは渡されません。
この機能を試すために、次の例では max_threads と max_final_threads の値を定義し、設定が正常に反映されたかどうかを確認する queries を実行します。
例:
<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>
<defaults/>
</http_handlers>curl -H 'XXX:TEST_HEADER_VALUE_DYNAMIC' 'http://localhost:8123/own?max_threads=1&max_final_threads=2¶m_name_1=max_threads¶m_name_2=max_final_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_final_threads 2static
static では、content_type、status、および response_content を返せます。response_content では、指定した内容を返せます。
例えば、"Say Hi!" というメッセージを返すには:
<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>
<http_response_headers>
<Content-Language>en</Content-Language>
<X-My-Custom-Header>43</X-My-Custom-Header>
</http_response_headers>
<response_content>Say Hi!</response_content>
</handler>
</rule>
<defaults/>
</http_handlers>http_response_headers を使うと、content_type の代わりにコンテンツタイプを設定できます。
<http_handlers>
<rule>
<methods>GET</methods>
<headers><XXX>xxx</XXX></headers>
<url>/hi</url>
<handler>
<type>static</type>
<status>402</status>
#begin-highlight
<http_response_headers>
<Content-Type>text/html; charset=UTF-8</Content-Type>
<Content-Language>en</Content-Language>
<X-My-Custom-Header>43</X-My-Custom-Header>
</http_response_headers>
#end-highlight
<response_content>Say Hi!</response_content>
</handler>
</rule>
<defaults/>
</http_handlers>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=10
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0","elapsed_ns":"662334","memory_usage":"8451671"}
<
* Connection #0 to host localhost left intact
Say Hi!%クライアントに送信されるconfigurationの内容を見つけます。
<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>$ 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=10
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0","elapsed_ns":"662334","memory_usage":"8451671"}
<
* 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>%クライアントに送信するファイルの内容を確認するには:
<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>
<http_response_headers>
<ETag>737060cd8c284d8af7ad3082f209582d</ETag>
</http_response_headers>
<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>
<http_response_headers>
<ETag>737060cd8c284d8af7ad3082f209582d</ETag>
</http_response_headers>
<response_content>file://./relative_path_file.html</response_content>
</handler>
</rule>
</http_handlers>$ 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=10
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0","elapsed_ns":"662334","memory_usage":"8451671"}
<
<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=10
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0","elapsed_ns":"662334","memory_usage":"8451671"}
<
<html><body>Relative Path File</body></html>
* Connection #0 to host localhost left intactredirect
redirect は location に 302 リダイレクトします
たとえば、ClickHouse play の play に set user を自動的に追加するには、次のようにします:
<clickhouse>
<http_handlers>
<rule>
<methods>GET</methods>
<url>/play</url>
<handler>
<type>redirect</type>
<location>/play?user=play</location>
</handler>
</rule>
</http_handlers>
</clickhouse>HTTP レスポンスヘッダー
ClickHouse では、設定可能なあらゆる種類のハンドラーに適用できるカスタム HTTP レスポンスヘッダーを設定できます。これらのヘッダーは http_response_headers 設定で指定でき、ヘッダー名とその値を表すキー・バリューのペアを受け付けます。この機能は、カスタムのセキュリティヘッダーや CORS ポリシー、その他 ClickHouse HTTP インターフェイス全体で必要となる HTTP ヘッダー要件に対応する際に特に便利です。
たとえば、次のものに対してヘッダーを設定できます。
- 通常のクエリエンドポイント
- Web UI
- ヘルスチェック
また、common_http_response_headers を指定することもできます。これらは、設定で定義されたすべての HTTP ハンドラーに適用されます。
ヘッダーは、設定された各ハンドラーの HTTP レスポンスに含まれます。
以下の例では、すべてのサーバーからのレスポンスに 2 つのカスタムヘッダー X-My-Common-Header と X-My-Custom-Header が含まれます。
<clickhouse>
<http_handlers>
<common_http_response_headers>
<X-My-Common-Header>Common header</X-My-Common-Header>
</common_http_response_headers>
<rule>
<methods>GET</methods>
<url>/ping</url>
<handler>
<type>ping</type>
<http_response_headers>
<X-My-Custom-Header>Custom indeed</X-My-Custom-Header>
</http_response_headers>
</handler>
</rule>
</http_handlers>
</clickhouse>HTTP streaming 中の例外発生時に有効な JSON/XML レスポンス
HTTP 経由でクエリを実行している際、データの一部がすでに送信された後で例外が発生することがあります。通常、例外はプレーンテキストでクライアントに送信されます。
データの出力に特定のデータフォーマットを使用していた場合、その出力は指定したデータフォーマットとしては無効になる可能性があります。
これを防ぐには、設定 http_write_exception_in_output_format (デフォルトでは無効) を使用します。この設定により、ClickHouse は指定したフォーマットで例外を書き出します (現在は XML および JSON* フォーマットをサポートしています) 。
例:
$ curl 'http://localhost:8123/?query=SELECT+number,+throwIf(number>3)+from+system.numbers+format+JSON+settings+max_block_size=1&http_write_exception_in_output_format=1'
{
"meta":
[
{
"name": "number",
"type": "UInt64"
},
{
"name": "throwIf(greater(number, 2))",
"type": "UInt8"
}
],
"data":
[
{
"number": "0",
"throwIf(greater(number, 2))": 0
},
{
"number": "1",
"throwIf(greater(number, 2))": 0
},
{
"number": "2",
"throwIf(greater(number, 2))": 0
}
],
"rows": 3,
"exception": "Code: 395. DB::Exception: Value passed to 'throwIf' function is non-zero: while executing 'FUNCTION throwIf(greater(number, 2) :: 2) -> throwIf(greater(number, 2)) UInt8 : 1'. (FUNCTION_THROW_IF_VALUE_IS_NON_ZERO) (version 23.8.1.1)"
}$ curl 'http://localhost:8123/?query=SELECT+number,+throwIf(number>2)+from+system.numbers+format+XML+settings+max_block_size=1&http_write_exception_in_output_format=1'
<?xml version='1.0' encoding='UTF-8' ?>
<result>
<meta>
<columns>
<column>
<name>number</name>
<type>UInt64</type>
</column>
<column>
<name>throwIf(greater(number, 2))</name>
<type>UInt8</type>
</column>
</columns>
</meta>
<data>
<row>
<number>0</number>
<field>0</field>
</row>
<row>
<number>1</number>
<field>0</field>
</row>
<row>
<number>2</number>
<field>0</field>
</row>
</data>
<rows>3</rows>
<exception>Code: 395. DB::Exception: Value passed to 'throwIf' function is non-zero: while executing 'FUNCTION throwIf(greater(number, 2) :: 2) -> throwIf(greater(number, 2)) UInt8 : 1'. (FUNCTION_THROW_IF_VALUE_IS_NON_ZERO) (version 23.8.1.1)</exception>
</result>