> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> CREATE HANDLER のリファレンス

# CREATE HANDLER

サーバー設定ファイルを編集せずに、SQL で定義したカスタム HTTP ハンドラーを作成します。SQL で定義したハンドラーは、設定ベースの[HTTP インターフェイスハンドラー](/docs/ja/concepts/features/interfaces/http)の代替手段です。

<div id="syntax">
  ## 構文
</div>

```sql theme={null}
CREATE HANDLER [IF NOT EXISTS] name [ON CLUSTER cluster]
[PROTOCOL protocol_name|ANY]
URL [PREFIX|REGEXP] '/path'
[METHODS (GET, POST)]
[TYPE query]
AS [SELECT|INSERT|...] ...
```

指定した`name`のハンドラーを作成します。この名前は、SQLクエリによるハンドラーの管理、診断メッセージ、およびハンドラーの順序付けに使用されます。

<div id="clauses">
  ## 句
</div>

* `PROTOCOL` — 任意。プロトコル名を指定した場合、ハンドラーは指定された[合成可能プロトコル](/docs/ja/concepts/features/configuration/server-config/composable-protocols)でのみ有効になります。指定しない場合、ハンドラーは組み込みの `http`/`https` ポートと、すべての HTTP 型[合成可能プロトコル](/docs/ja/concepts/features/configuration/server-config/composable-protocols)リスナーを含む、すべての HTTP エンドポイントで有効になります。`PROTOCOL ANY` は後者のデフォルト動作を明示的に選択します。`ALTER HANDLER` では、以前に設定したプロトコル制限を解除します。文字どおり `any` という名前のプロトコルは、バッククォートで参照できます: ``PROTOCOL `any` ``。
* `URL` — 必須。完全一致 URL、`URL PREFIX`、または `URL REGEXP` の形式を指定できます。完全一致 URL とプレフィックスでは、作成時または変更時に曖昧性が検査され、曖昧性がある場合は例外がスローされます。正規表現では、曖昧性を検査できません。URL は、`?` クエリ文字列および `#` フラグメント識別子を除いて照合されます。`URL PREFIX` は、パスセグメントの境界においてベースパスとして照合されます。これは[設定で定義されたハンドラー](/docs/ja/concepts/features/interfaces/http)の `url_prefix` ルールと同じセマンティクスです。`URL PREFIX '/api/v1'` は `/api/v1`、`/api/v1/`、`/api/v1/write` に一致しますが、`/api/v1beta` には一致しません。プレフィックス末尾の `/` は無視されるため、`'/api/v1/'` と `'/api/v1'` は同じように動作します。
* `METHODS` — 任意。許可する HTTP メソッドのリストです。デフォルトは `GET` のみです。サポートされるメソッドは `GET`、`POST`、`PUT`、`DELETE` です。データ変更メソッドである `POST`、`PUT`、`DELETE` では、データを変更するクエリを実行できます。一方、`GET` や `HEAD` などの安全なメソッドは常に `readonly` モードで実行されます。したがって、データを変更するクエリ (たとえば `INSERT` や DDL) を実行するハンドラーでは、少なくとも 1 つのデータ変更メソッドを許可する必要があります。読み取り専用メソッドのみ (たとえばデフォルトの `GET`) を指定してこのようなハンドラーを作成すると、例外がスローされます。`readonly` モードでも副作用が残るクエリは特殊なケースです。`BACKUP` と `RESTORE` には永続的な副作用があり、セッションを変更するステートメント `SET`、`SET ROLE`、`USE`、`BEGIN TRANSACTION`、`COMMIT`、`ROLLBACK`、`SET TRANSACTION SNAPSHOT` は、`session_id` の使用時にリクエスト間で維持されるセッションまたはトランザクションの状態を変更します。また、`CREATE TEMPORARY TABLE` / `CREATE TEMPORARY VIEW` はセッション内に存在するオブジェクトを作成します。しかし、安全なメソッドの `readonly` モードでは、これらはいずれもブロックされません。*既存の*一時テーブルに対する変更も `readonly` モードではブロックされないため、そのようなテーブルをターゲットにする可能性があるクエリも同様に扱われます。具体的には、データベースで修飾されていないターゲットテーブルを持つ `INSERT` (修飾されていない名前はセッション一時テーブルに解決される可能性があります) 、`DROP TEMPORARY TABLE`、データベースで修飾されていないテーブルに対する `DROP TABLE` / `TRUNCATE TABLE`、およびデータベースで修飾されていないテーブルに対する `ALTER` (`ALTER TEMPORARY TABLE` は同じステートメントです) が該当します。データベースで修飾されたターゲットが一時テーブルになることはないため、そのようなクエリにはこのルールは適用されません。HTTP では、安全なメソッドに副作用がないことが求められます (`GET` 用に宣言されたハンドラーは `HEAD` にも応答し、その場合レスポンス本文は抑制されるため、副作用は見えません) 。したがって、このようなクエリを実行するハンドラーには、データ変更メソッド*のみ*を列挙する必要があります。安全なメソッドを含めて作成または変更すると、例外がスローされます。複合ステートメントは内部のステートメントまで検査されます。`statement1 PARALLEL WITH statement2 ...` および `EXECUTE AS <user> <statement>` では、実際に実行されるラップされたステートメントに上記のルールが適用されます (各ステートメントは、`readonly` モードを維持するハンドラーのコンテキストのコピーで実行されます) 。単独の `EXECUTE AS <user>` はセッション全体を別のユーザーとして実行するため、それ自体がセッション変更として扱われます。さらに、単独の場合でもステートメントをラップする場合でも、すべての `EXECUTE AS` ハンドラーでは少なくとも 1 つのデータ変更メソッドを許可する必要があります。権限借用には `IMPERSONATE` 権限が必要であり、安全なメソッドの `readonly` モードではこれが拒否されるためです。
* `TYPE` — 任意。現時点でサポートされる唯一の型は `query` です。
* `AS` — このハンドラーで実行されるSQLクエリです。クエリはパラメーター化できます。クエリはハンドラーの作成または変更時に構文の正しさが解析されますが、意味解析は行われません。たとえば、ハンドラーの作成時点では、クエリが参照するテーブルが存在しない場合があります。`FORMAT` 句や類似の句は、`CREATE`/`ALTER` ステートメント全体ではなくクエリに属します。曖昧さを解消するため、クエリを括弧で囲むことができます。`INSERT` クエリには、`VALUES` または `FORMAT` 句の後にインラインデータを含めてはなりません。このようなハンドラーを作成または変更すると、例外がスローされます。インラインペイロードをハンドラー定義に保持できないためです。データはHTTPボディで提供する必要があります (または `INSERT ... SELECT` で生成されます) 。ボディを読み取るクエリを持つハンドラーへのリクエスト、つまりボディからデータを取得する `INSERT`、または `_request_body` パラメーターを使用するクエリでは、長さを宣言する必要があります。`Content-Length` ヘッダーのない非チャンク化リクエストには `411 Length Required` が返されます。そうしないと、ボディがストリーム終端まで読み取られ、接続が切断されても完全なリクエストとして受け入れられてしまうためです。このようなハンドラーのすべてのメソッドも、ボディを伴うメソッド (`POST`、`PUT`、または `DELETE`) である必要があります。`METHODS` 句で安全なメソッド (たとえばデフォルトの `GET`) を指定して作成すると、例外がスローされます。安全なメソッドではリクエストボディが提供されないため、クエリが空のボディを暗黙的に読み取ってしまうからです。宣言された `GET` は `HEAD` に対しても提供されるため、安全なメソッドとボディを伴うメソッドを混在させると、それらの呼び出しが到達可能なままになります。`INSERT ... SELECT` はボディを読み取りません (データは `SELECT` から取得されます) 。したがって、`SELECT` がリクエストボディから供給される `input` テーブル関数を読み取る場合を除き、これらの要件は適用されません。ボディを読み取る `INSERT` は、ハンドラー自身のクエリである必要があります。`EXECUTE AS` および `PARALLEL WITH` は、それらがラップするステートメントをリクエストボディなしで実行するため、これらでラップした場合は、すべてのアップロードが暗黙的に破棄されるのではなく、作成時に拒否されます。ボディを読み取るクエリでは、`_request_body` パラメーターも使用してはなりません。リクエストボディは1つしかなく、`_request_body` をバインドするとクエリが入力データを読み取る前にそのボディが消費されるためです。そのため、このようなハンドラーは、すべてのアップロードが暗黙的に失われるのではなく、作成時に拒否されます。クエリ自身のボディ入力か `_request_body` のいずれか一方のみを使用し、両方を使用しないでください。ボディを読み取らないハンドラーには、このような要件はありません。そのようなハンドラーへのリクエストのボディは無視され、ハンドラーのクエリに追加されることはありません。保存されたクエリテキストは、ハンドラーが再ロードまたは呼び出されるたびに、無制限のパーサー深度とバックトラック数でサーバーにより再解析されます。そのため、`max_parser_depth` / `max_parser_backtracks` を引き上げたセッションで作成されたハンドラーは、通常のセッション制限下でもロードおよび呼び出し可能です。

<div id="priority">
  ## 優先順位
</div>

server configuration で定義されたハンドラーは、SQL で定義されたハンドラーよりも優先されます。SQL で定義されたハンドラーは、名前の辞書式順序に従って照合されます。

<div id="parameters">
  ## パラメータ
</div>

パラメータ化クエリのクエリパラメータは、構成で定義されたハンドラーと同様に、次の方法で指定します。

* クエリ文字列内の HTTP URL パラメータ。`param_<name>` 形式を使用します (例: `?param_id=42` は `{id:Type}` にバインドされます) 。
* `URL REGEXP` 内の名前付きキャプチャグループ (例: `URL REGEXP '/users/(?P<id>\d+)'` は `{id:Type}` にバインドされます) 。
* クエリでパラメータを宣言しているハンドラーでは、リクエストボディのフォームフィールド。`application/x-www-form-urlencoded` ボディ (例: `curl -d 'param_id=42'`) および `multipart/form-data` ボディのフィールドは、ボディを含む `POST`、`PUT`、`DELETE` メソッドで、URL パラメータと同様に `{name:Type}` パラメータにバインドされます。パラメータが URL とボディの両方に存在する場合は、URL の値が使用されます。フォームとしてパースされたボディはハンドラーレイヤーで消費され、`INSERT` データとしてクエリに渡されません。ボディを `_request_body` にのみ使用するハンドラーは、フォームとしてパースされず、生のボディを受け取ります。ほかのパラメータとともに `_request_body` を宣言するハンドラーは、両方を受け取ります。ボディがフォームとしてパースされる前に、生の未パースボディのコピーが `_request_body` に保持されます (`http_max_request_param_data_size` の制限対象) 。

ハンドラーの呼び出し時には、標準の ClickHouse HTTP ヘッダー (`X-ClickHouse-Database`、`X-ClickHouse-User`、`X-ClickHouse-Key` など) が通常どおり使用されます。

関数 [`currentHandler`](/docs/ja/reference/functions/regular-functions/other-functions#currentHandler) および [`currentRequestURL`](/docs/ja/reference/functions/regular-functions/other-functions#currentRequestURL) を使用すると、呼び出されたハンドラーとリクエスト URL に応じてクエリの動作をカスタマイズできます。

<div id="access-control">
  ## アクセス制御
</div>

`CREATE HANDLER`、`DROP HANDLER`、`ALTER HANDLER` を実行するには、それぞれ `CREATE HANDLER`、`DROP HANDLER`、`ALTER HANDLER` 権限が必要です。

[`system.handlers`](/docs/ja/reference/system-tables/handlers) テーブルを読み取るには、`SHOW HANDLERS` 権限が必要です。ハンドラーのクエリに埋め込まれている可能性のあるシークレットは、ユーザーにシークレットの閲覧も許可されていない限り、このテーブルではマスクされます ([`system.handlers`](/docs/ja/reference/system-tables/handlers) を参照) 。

ハンドラーの呼び出しに個別の権限は必要ありませんが、クエリの呼び出し時には通常どおり権限が確認され、認証も通常どおり行われます。特定のクエリへのアクセスをカプセル化するには、[`SQL SECURITY DEFINER` を指定した `VIEW`](/docs/ja/reference/statements/create/view#sql_security) を作成し、そのビューから選択するハンドラーを定義します。

<div id="storage">
  ## ストレージ
</div>

ハンドラーは、[名前付きコレクション](/docs/ja/concepts/features/configuration/server-config/named-collections)と同様に、設定ファイルの`query_rules_storage`セクションで設定されるローカルストレージまたはKeeperストレージに保存されます。

```xml theme={null}
<query_rules_storage>
    <type>local</type> <!-- or zookeeper -->
    <path>/var/lib/clickhouse/handlers/</path>
</query_rules_storage>
```

Keeper ストレージでは、ハンドラーはすべてのレプリカ間で自動的に同期されるため、明示的な `ON CLUSTER` 句は不要です。指定すると、すべてのレプリカが同じハンドラーを作成しようとします。`ignore_on_cluster_for_replicated_handler_queries` 設定を有効にすると、ストレージがレプリケートされている場合、`CREATE`、`ALTER`、`DROP HANDLER` は `ON CLUSTER` を無視します。これは `ignore_on_cluster_for_replicated_named_collections_queries` と同様の動作です。

<div id="alter-handler">
  ## ALTER HANDLER
</div>

```sql theme={null}
ALTER HANDLER name
[PROTOCOL protocol_name|ANY]
[URL [PREFIX|REGEXP] '/path']
[METHODS (GET, POST)]
[TYPE query]
[AS SELECT ...]
```

ハンドラーを新しいものに置き換えます。`ALTER` クエリには一部の句のみを含めることができ、たとえば URL またはクエリだけを変更できます。指定しない句は以前の値を保持します。`PROTOCOL ANY` を指定すると既存のプロトコル制限が解除され、ハンドラーは再びすべての HTTP エンドポイントで有効になります。

<div id="drop-handler">
  ## DROP HANDLER
</div>

```sql theme={null}
DROP HANDLER [IF EXISTS] name
```

指定した名前のハンドラーを削除します。

<div id="introspection">
  ## イントロスペクション
</div>

[`system.handlers`](/docs/ja/reference/system-tables/handlers) テーブルには、SQL で定義されたすべてのハンドラーが一覧表示されます。[`system.query_log`](/docs/ja/reference/system-tables/query_log) テーブルには、各クエリのハンドラー名と HTTP リクエストのパス (クエリ文字列を除く) が、`http_handler_name` および `http_request_url` カラムに記録されます。

<div id="example">
  ## 例
</div>

```sql theme={null}
CREATE HANDLER my_handler URL '/my_handler' AS SELECT version();
```

```bash theme={null}
$ curl 'http://localhost:8123/my_handler'
```

正規表現 URL を使用するパラメーター化ハンドラー:

```sql theme={null}
CREATE HANDLER get_user URL REGEXP '/users/(?P<id>\d+)' AS SELECT * FROM users WHERE id = {id:UInt64};
```

```bash theme={null}
$ curl 'http://localhost:8123/users/42'
```

<div id="related-statements">
  ## 関連ステートメント
</div>

`CREATE HANDLER` は `CREATE` ステートメントファミリーに属し、`ALTER` および `DROP` と関連しています。
