CREATE HANDLER
CREATE HANDLER
서버 구성 파일을 편집하지 않고 SQL로 정의된 사용자 지정 HTTP 핸들러를 만들어요. SQL 정의 핸들러는 구성 기반 HTTP 인터페이스 핸들러의 대안입니다.
출처: 문서
본문
Syntax
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 쿼리로 핸들러를 관리하고, 진단 메시지에 쓰이며, 핸들러 순서를 정할 때 사용됩니다.
Clauses
PROTOCOL— 선택 사항이에요. 프로토콜 이름이 지정되면 핸들러는 지정된 구성 가능한 프로토콜(composable protocol)에 대해서만 활성화됩니다. 그렇지 않으면 핸들러는 모든 HTTP 엔드포인트 — 내장http/https포트와 모든 HTTP 유형 구성 가능한 프로토콜 리스너 — 에서 활성화됩니다.PROTOCOL ANY는 후자의 기본 동작을 명시적으로 선택하며,ALTER HANDLER에서는 이전에 설정된 프로토콜 제한을 제거합니다. 리터럴로any라는 이름의 프로토콜은 백쿼트로 참조할 수 있어요:PROTOCOLany.URL— 필수에요. 정확한 URL,URL PREFIX, 또는URL REGEXP형태일 수 있습니다. 정확한 URL과 접두사의 경우 생성/변경 시 모호성이 검사되고 모호하면 예외가 던져집니다. regexp의 경우 모호성을 검사할 수 없습니다. 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)가 있는 핸들러는 적어도 하나의 변형 메서드를 허용해야 합니다. 읽기 전용 메서드만(예: 기본GET)으로 그러한 핸들러를 만들면 예외가 던져집니다.readonly모드를 견디는 부작용이 있는 쿼리는 특수한 경우입니다.BACKUP과RESTORE는 지속적인 부작용이 있고, 세션 변형 문SET,SET ROLE,USE,BEGIN TRANSACTION,COMMIT,ROLLBACK,SET TRANSACTION SNAPSHOT은session_id를 사용할 때 요청 사이에 지속되는 세션 또는 트랜잭션 상태를 변경하며,CREATE TEMPORARY TABLE/CREATE TEMPORARY VIEW는 세션에 사는 객체를 만듭니다 — 그러나 안전한 메서드의readonly모드는 그중 어느 것도 차단하지 않습니다. 기존 임시 테이블의 mutation도readonly모드에 의해 차단되지 않으므로, 그것을 대상으로 할 수 있는 쿼리는 같은 방식으로 취급됩니다. 데이터베이스로 한정되지 않은 테이블을 대상으로 하는INSERT(한정되지 않은 이름은 세션 임시 테이블로 해석될 수 있음),DROP TEMPORARY TABLE, 데이터베이스로 한정되지 않은 테이블의DROP TABLE/TRUNCATE TABLE, 데이터베이스로 한정되지 않은 테이블의ALTER(ALTER TEMPORARY TABLE은 같은 문). 데이터베이스로 한정된 대상은 임시 테이블일 수 없으므로 그러한 쿼리는 이 규칙에 해당하지 않습니다. HTTP는 안전한 메서드가 부작용이 없어야 한다고 요구합니다(GET으로 선언된 핸들러는 응답 본문이 억제되어 효과가 보이지 않는HEAD에도 서빙됩니다). 따라서 그러한 쿼리를 실행하는 핸들러는 변형 메서드만 나열해야 합니다. 안전한 메서드를 포함하도록 만들거나 변경하면 예외가 던져집니다. 복합 문은 살펴봅니다.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에서 옴). 따라서input테이블 함수에서 읽는 것이 아니라면 이러한 요구 사항의 대상이 아닙니다. 본문을 읽는INSERT는 핸들러 자신의 쿼리여야 합니다.EXECUTE AS와PARALLEL WITH는 요청 본문 없이 감싼 문을 실행하므로, 그것들로 감싸는 것은 조용한 것 대신 생성 시 거부됩니다.
Priority
서버 구성에서 정의된 핸들러가 SQL 정의 핸들러보다 우선합니다. SQL 정의 핸들러는 이름의 사전적 순서로 매칭됩니다.
Parameters
파라미터화된 쿼리의 쿼리 파라미터는 구성 정의 핸들러와 마찬가지로 다음에서 제공됩니다:
param_<name>관례를 사용하는 쿼리 문자열의 HTTP URL 파라미터(예:?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본문의 필드는 URL 파라미터와 같은 방식으로{name:Type}파라미터를 바인딩하며, 본문 나르는 메서드POST,PUT,DELETE에서 그렇습니다. 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와 currentRequestURL을 사용해 호출된 핸들러와 요청 URL에 따라 쿼리 동작을 사용자 정의할 수 있습니다.
Access control
CREATE HANDLER, DROP HANDLER, ALTER HANDLER는 각각 CREATE HANDLER, DROP HANDLER, ALTER HANDLER 권한이 필요합니다.
system.handlers 테이블을 읽으려면 SHOW HANDLERS 권한이 필요합니다. 핸들러의 쿼리에 포함될 수 있는 비밀은 사용자가 비밀을 볼 수 있도록 추가로 허용되지 않는 한 여기서 마스킹됩니다(system.handlers 참조).
핸들러를 호출하는 것은 별도 권한이 필요하지 않지만, 쿼리 호출 중에 권한은 평소처럼 검사되고 인증은 평소 방식으로 동작합니다. 특정 쿼리에 대한 접근을 캡슐화하려면 SQL SECURITY DEFINER를 가진 VIEW를 만들고 그 뷰에서 select하는 핸들러를 정의하세요.
Storage
핸들러는 명명된 콜렉션(named collections)과 유사하게 로컬 또는 Keeper 저장소가 될 수 있는 저장소에 저장되며, 구성 파일의 query_rules_storage 섹션에 구성됩니다:
<query_rules_storage>
<type>local</type> <!-- or zookeeper -->
<path>/var/lib/clickhouse/handlers/</path>
</query_rules_storage>
Keeper 저장소를 사용하면 핸들러가 모든 리플리카에서 자동으로 동기화되므로, 명시적 ON CLUSTER 절은 중복되며 모든 리플리카가 같은 핸들러를 만들려고 할 것입니다. 저장소가 복제될 때 CREATE, ALTER, DROP HANDLER가 ON CLUSTER를 무시하게 하려면 ignore_on_cluster_for_replicated_handler_queries 설정을 활성화하세요. ignore_on_cluster_for_replicated_named_collections_queries를 반영합니다.
ALTER HANDLER
ALTER HANDLER name
[PROTOCOL protocol_name|ANY]
[URL [PREFIX|REGEXP] '/path']
[METHODS (GET, POST)]
[TYPE query]
[AS SELECT ...]
핸들러를 새 것으로 교체해요. ALTER 쿼리는 절의 일부만 포함할 수 있습니다(예: URL이나 쿼리만 변경하는 데 사용). 지정되지 않은 절은 이전 값을 유지합니다. PROTOCOL ANY는 기존 프로토콜 제한을 제거해 핸들러가 모든 HTTP 엔드포인트에서 다시 활성화되게 합니다.
DROP HANDLER
DROP HANDLER [IF EXISTS] name
지정된 이름의 핸들러를 버려요.
Introspection
system.handlers 테이블은 모든 SQL 정의 핸들러를 나열합니다. system.query_log 테이블은 각 쿼리의 핸들러 이름과 HTTP 요청 경로(쿼리 문자열 없이)를 http_handler_name 및 http_request_url 컬럼에 기록합니다.
Example
CREATE HANDLER my_handler URL '/my_handler' AS SELECT version();
$ curl 'http://localhost:8123/my_handler'
regexp URL이 있는 파라미터화된 핸들러:
CREATE HANDLER get_user URL REGEXP '/users/(?P<id>\d+)' AS SELECT * FROM users WHERE id = {id:UInt64};
$ curl 'http://localhost:8123/users/42'
Related statements
CREATE HANDLER는 CREATE 문 계열의 일부이며 ALTER 및 DROP과 관련이 있습니다.