Sintaxe
name especificado. O nome é usado para gerenciar handlers por meio de consultas SQL, em mensagens de diagnóstico e para ordená-los.
Cláusulas
PROTOCOL— opcional. Se um nome de protocolo for especificado, o handler ficará ativo apenas para o protocolo componível indicado. Caso contrário, ficará ativo em todos os endpoints HTTP: as portas integradashttp/httpse todos os listeners de protocolo componível do tipo HTTP.PROTOCOL ANYseleciona explicitamente esse comportamento padrão; emALTER HANDLER, remove uma restrição de protocolo definida anteriormente. Um protocolo chamado literalmenteanypode ser referenciado com crases:PROTOCOL `any`.URL— obrigatória. Pode ser uma URL exata, umURL PREFIXou umURL REGEXP. Para URLs exatas e prefixos, a ambiguidade é verificada no momento da criação ou alteração, e uma exceção é lançada se houver ambiguidade. Para regexp, a ambiguidade não pode ser verificada. A URL é comparada sem a string de consulta?nem o identificador de fragmento#. UmURL PREFIXé comparado como um caminho base, no limite de um segmento de caminho — com a mesma semântica da regraurl_prefixdos handlers definidos na configuração:URL PREFIX '/api/v1'corresponde a/api/v1,/api/v1/e/api/v1/write, mas não a/api/v1beta. A/final do prefixo é ignorada, portanto'/api/v1/'e'/api/v1'têm o mesmo comportamento.METHODS— opcional. A lista de métodos HTTP permitidos. Por padrão, é apenasGET. Os métodos compatíveis sãoGET,POST,PUTeDELETE. Os métodos que modificam dados,POST,PUTeDELETE, podem executar consultas modificadoras; os métodos seguros, comoGETeHEAD, são sempre executados no modoreadonly. Consequentemente, um handler cuja consulta modifica dados (por exemplo,INSERTou DDL) deve permitir pelo menos um método que modifica dados — criar esse handler apenas com métodos somente leitura (por exemplo, oGETpadrão) lança uma exceção. Consultas cujos efeitos colaterais persistem no modoreadonlysão um caso especial:BACKUPeRESTOREtêm efeitos colaterais duradouros; as instruções que alteram a sessãoSET,SET ROLE,USE,BEGIN TRANSACTION,COMMIT,ROLLBACKeSET TRANSACTION SNAPSHOTalteram o estado da sessão ou da transação, que persiste entre solicitações quandosession_idestá em uso; eCREATE TEMPORARY TABLE/CREATE TEMPORARY VIEWcriam um objeto que existe durante a sessão — ainda assim, o modoreadonlydos métodos seguros não bloqueia nenhum deles. As mutações de uma tabela temporária existente também não são bloqueadas pelo modoreadonly; por isso, consultas que possam ter uma tabela temporária como destino são tratadas da mesma forma: umINSERTcuja tabela de destino não seja qualificada com um banco de dados (um nome não qualificado pode ser resolvido como uma tabela temporária da sessão), umDROP TEMPORARY TABLE, umDROP TABLE/TRUNCATE TABLEde uma tabela não qualificada com um banco de dados e umALTERde uma tabela não qualificada com um banco de dados (ALTER TEMPORARY TABLEé a mesma instrução). Um destino qualificado com banco de dados nunca pode ser uma tabela temporária; portanto, essas consultas não estão sujeitas a essa regra. O HTTP exige que os métodos seguros não tenham efeitos colaterais (um handler declarado paraGETtambém atende aHEAD, no qual o corpo da resposta é suprimido e o efeito seria invisível). Portanto, um handler que execute esse tipo de consulta deve listar apenas métodos que modificam dados — criá-lo ou alterá-lo para incluir um método seguro lança uma exceção. As instruções compostas são analisadas internamente: parastatement1 PARALLEL WITH statement2 ...eEXECUTE AS <user> <statement>, as regras acima se aplicam às instruções encapsuladas, pois são elas que são executadas (cada uma em uma cópia do contexto do handler, que mantém o modoreadonly). UmEXECUTE AS <user>sem instrução faz com que toda a sessão seja executada como outro usuário; portanto, conta como uma alteração de sessão por si só. Além disso, qualquer handlerEXECUTE AS— sem instrução ou encapsulando uma instrução — deve permitir pelo menos um método que modifica dados: a personificação exige o privilégioIMPERSONATE, que o modoreadonlydos métodos seguros nega.TYPE— opcional. Por enquanto, o único tipo compatível équery.AS— a consulta SQL que será invocada por este manipulador. A consulta pode ser parametrizada. Sua correção sintática é verificada durante a criação ou alteração do manipulador, mas ela não é analisada semanticamente — por exemplo, as tabelas às quais a consulta faz referência podem não existir no momento da criação do manipulador. As cláusulasFORMATe semelhantes pertencem à consulta, não à instruçãoCREATE/ALTERcomo um todo. A consulta pode ser colocada entre parênteses para eliminar ambiguidades. Uma consultaINSERTnão pode conter dados inline após a cláusulaVALUESouFORMAT— a criação ou alteração desse manipulador lança uma exceção, pois o payload inline não pode ser preservado na definição do manipulador; espera-se que os dados sejam fornecidos no corpo da requisição HTTP (ou calculados por umINSERT ... SELECT). Uma requisição para um manipulador cuja consulta lê o corpo — umINSERTque recebe seus dados do corpo ou uma consulta que usa o parâmetro_request_body— deve declarar seu tamanho: uma requisição não fragmentada sem o cabeçalhoContent-Lengthrecebe a resposta411 Length Required, pois, caso contrário, o corpo seria lido até o fim do fluxo, e uma conexão interrompida seria aceita como uma requisição completa. Todos os métodos desse manipulador também devem permitir corpo (POST,PUTouDELETE) — criá-lo com um método seguro na cláusulaMETHODS(por exemplo, oGETpadrão) lança uma exceção, pois um método seguro nunca fornece um corpo de requisição e a consulta leria silenciosamente um corpo vazio; umGETdeclarado também atende aHEAD, portanto misturar métodos seguros com métodos que permitem corpo manteria essas invocações acessíveis. UmINSERT ... SELECTnão lê o corpo (seus dados vêm doSELECT), portanto não está sujeito a esses requisitos — exceto se oSELECTler da função de tabelainput, que é alimentada pelo corpo da requisição. UmINSERTque lê o corpo deve ser a própria consulta do manipulador:EXECUTE ASePARALLEL WITHexecutam as instruções que encapsulam sem o corpo da requisição; portanto, encapsulá-lo em um deles é rejeitado na criação, em vez de descartar silenciosamente cada upload. Uma consulta que lê o corpo também não pode usar o parâmetro_request_body: há um único corpo de requisição, e a vinculação de_request_bodyo consome antes que a consulta leia seus dados de entrada; portanto, esse manipulador é rejeitado na criação, em vez de perder silenciosamente cada upload — use a entrada de corpo da própria consulta ou_request_body, mas não ambos. Manipuladores que não leem o corpo não têm esse requisito; o corpo de uma requisição para esse tipo de manipulador é ignorado e nunca é anexado à consulta do manipulador. O texto da consulta armazenada é analisado novamente pelo servidor com profundidade do analisador e número de retrocessos ilimitados sempre que o manipulador é recarregado ou invocado; assim, um manipulador criado em uma sessão commax_parser_depth/max_parser_backtrackselevados continua podendo ser carregado e invocado sob limites normais de sessão.
Priority
Parâmetros
- parâmetros de URL HTTP na string de consulta, usando a convenção
param_<name>(por exemplo,?param_id=42associa{id:Type}); - grupos de captura nomeados em uma
URL REGEXP(por exemplo,URL REGEXP '/users/(?P<id>\d+)'associa{id:Type}); - campos de formulário do corpo da requisição, para um handler cuja consulta declara parâmetros: um corpo
application/x-www-form-urlencoded(por exemplo,curl -d 'param_id=42') e os campos de um corpomultipart/form-dataassociam parâmetros{name:Type}da mesma forma que os parâmetros de URL, nos métodos que aceitam corpoPOST,PUTeDELETE. Um parâmetro presente tanto na URL quanto no corpo assume o valor da URL. Um corpo analisado como formulário é consumido pela camada do handler: ele não é enviado à consulta como dados deINSERT. Um handler cujo único uso do corpo é_request_bodyrecebe o corpo bruto em vez de analisá-lo como formulário; um handler que declara_request_bodyjunto com outros parâmetros recebe ambos — uma cópia do corpo bruto, não analisado, é preservada em_request_body(sujeita ahttp_max_request_param_data_size) antes que o corpo seja analisado como formulário.
X-ClickHouse-Database, X-ClickHouse-User e X-ClickHouse-Key) são tratados normalmente ao invocar um handler.
As funções currentHandler e currentRequestURL podem ser usadas para personalizar o comportamento da consulta de acordo com o handler invocado e a URL da requisição.
Controle de acesso
CREATE HANDLER, DROP HANDLER e ALTER HANDLER exigem as permissões CREATE HANDLER, DROP HANDLER e ALTER HANDLER, respectivamente.
A leitura da tabela system.handlers exige a permissão SHOW HANDLERS. Os Secrets que podem estar embutidos na consulta de um handler são mascarados nessa tabela, a menos que o usuário também tenha permissão para visualizar Secrets (consulte system.handlers).
A invocação de um handler não exige uma permissão específica, mas as permissões são verificadas normalmente durante a execução da consulta, e a autenticação funciona como de costume. Para encapsular o acesso a determinadas consultas, crie uma VIEW com SQL SECURITY DEFINER e defina um handler que execute uma instrução SELECT nessa view.
Armazenamento
query_rules_storage do arquivo de configuração:
ON CLUSTER explícita é redundante e faria com que cada réplica tentasse criar o mesmo handler. Habilite a configuração ignore_on_cluster_for_replicated_handler_queries para que CREATE, ALTER e DROP HANDLER ignorem ON CLUSTER quando o armazenamento for replicado, espelhando ignore_on_cluster_for_replicated_named_collections_queries.
ALTER HANDLER
ALTER pode incluir apenas um subconjunto de cláusulas; por exemplo, pode ser usada para alterar somente a URL ou a consulta. As cláusulas não especificadas mantêm seus valores anteriores. PROTOCOL ANY remove uma restrição de protocolo existente, reativando o handler em todos os endpoints HTTP.
DROP HANDLER
Introspecção
system.handlers lista todos os handlers definidos em SQL. A tabela system.query_log registra, nas colunas http_handler_name e http_request_url, o nome do handler e o caminho da requisição HTTP (sem a string de consulta) de cada consulta.
Exemplo
CREATE HANDLER faz parte da família de instruções CREATE e está relacionado às instruções ALTER e DROP.