構文
nameのハンドラーを作成します。この名前は、SQLクエリによるハンドラーの管理、診断メッセージ、およびハンドラーの順序付けに使用されます。
句
PROTOCOL— 任意。プロトコル名を指定した場合、ハンドラーは指定された合成可能プロトコルでのみ有効になります。指定しない場合、ハンドラーは組み込みのhttp/httpsポートと、すべての HTTP 型合成可能プロトコルリスナーを含む、すべての HTTP エンドポイントで有効になります。PROTOCOL ANYは後者のデフォルト動作を明示的に選択します。ALTER HANDLERでは、以前に設定したプロトコル制限を解除します。文字どおりanyという名前のプロトコルは、バッククォートで参照できます:PROTOCOL `any`。URL— 必須。完全一致 URL、URL PREFIX、またはURL REGEXPの形式を指定できます。完全一致 URL とプレフィックスでは、作成時または変更時に曖昧性が検査され、曖昧性がある場合は例外がスローされます。正規表現では、曖昧性を検査できません。URL は、?クエリ文字列および#フラグメント識別子を除いて照合されます。URL PREFIXは、パスセグメントの境界においてベースパスとして照合されます。これは設定で定義されたハンドラーの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を引き上げたセッションで作成されたハンドラーは、通常のセッション制限下でもロードおよび呼び出し可能です。
優先順位
パラメータ
- クエリ文字列内の 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の制限対象) 。
X-ClickHouse-Database、X-ClickHouse-User、X-ClickHouse-Key など) が通常どおり使用されます。
関数 currentHandler および currentRequestURL を使用すると、呼び出されたハンドラーとリクエスト URL に応じてクエリの動作をカスタマイズできます。
アクセス制御
CREATE HANDLER、DROP HANDLER、ALTER HANDLER を実行するには、それぞれ CREATE HANDLER、DROP HANDLER、ALTER HANDLER 権限が必要です。
system.handlers テーブルを読み取るには、SHOW HANDLERS 権限が必要です。ハンドラーのクエリに埋め込まれている可能性のあるシークレットは、ユーザーにシークレットの閲覧も許可されていない限り、このテーブルではマスクされます (system.handlers を参照) 。
ハンドラーの呼び出しに個別の権限は必要ありませんが、クエリの呼び出し時には通常どおり権限が確認され、認証も通常どおり行われます。特定のクエリへのアクセスをカプセル化するには、SQL SECURITY DEFINER を指定した VIEW を作成し、そのビューから選択するハンドラーを定義します。
ストレージ
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 と同様の動作です。
ALTER HANDLER
ALTER クエリには一部の句のみを含めることができ、たとえば URL またはクエリだけを変更できます。指定しない句は以前の値を保持します。PROTOCOL ANY を指定すると既存のプロトコル制限が解除され、ハンドラーは再びすべての HTTP エンドポイントで有効になります。
DROP HANDLER
イントロスペクション
system.handlers テーブルには、SQL で定義されたすべてのハンドラーが一覧表示されます。system.query_log テーブルには、各クエリのハンドラー名と HTTP リクエストのパス (クエリ文字列を除く) が、http_handler_name および http_request_url カラムに記録されます。
例
CREATE HANDLER は CREATE ステートメントファミリーに属し、ALTER および DROP と関連しています。