VDF 함수 계약
이 계약은 VDF 구현 함수가 VEF 런타임과 상호작용하는 방식을 규정합니다.make_func<>를 통해 등록된 모든 함수는 이 계약을 따라야 합니다. 아래에서 참조하는 타입은 #include <villagesql/vsql.h>를 통해 사용할 수 있습니다.
Part A: VDF 함수 계약
1. VDF 구현 함수는void입니다 — 값은 절대 반환하지 않습니다.
out.set(...) / out.set_length(n), out.set_null(), out.warning(msg), 또는 out.error(msg).
2. result->type을 네 개의 결과 상수 중 정확히 하나로 설정하세요.
vef_return_value_type_t에는 네 개의 상수가 있습니다:
타입별 변형은 없습니다.
VEF_RESULT_VALUE는 문자열, 정수, 실수, 사용자 정의 유형 모두에 대한 유일한 성공 상수입니다. 출력 타입은 함수가 받는 결과 래퍼(StringResult, IntResult, RealResult, CustomResult)에 따라 결정됩니다.
3. input.value()를 호출하기 전에 input.is_null()을 확인하세요.
is_null()이 true를 반환하면 value()를 호출하는 것은 정의되지 않은 동작입니다.
out.buffer()에 쓰고 out.set_length(n)을 호출하세요. 쓰기 전에 out.buffer().size()를 확인하세요.
out.buffer()는 서버 관리 버퍼에 대한Span<char>을 반환합니다.out.set_length(n)은 쓴 바이트 수를 기록합니다.out.buffer().size()는 최대 용량입니다. 항상 쓰기 전에 확인하세요.
out.error(msg)에 전달하세요. 필요 시 메시지는 VEF_MAX_ERROR_LEN(512바이트)로 자릅니다.
out.error(msg)는 std::string_view를 허용합니다. 메시지를 서버 관리 버퍼에 복사하고 결과 상태를 오류로 설정하는 한 번의 호출로 처리합니다.
래퍼 함수 구현
구현 함수는 타입화된 인수 및 결과 래퍼를 사용합니다:NULL 값 처리
is_null()을 통해 NULL을 확인하고 set_null()을 호출하여 NULL을 반환하세요:
- 입력 NULL 확인:
input.is_null() - NULL 반환:
out.set_null() - 값 반환:
out.set(v)(숫자/사용자 정의) 또는out.buffer()에 쓴 후out.set_length(n)(문자열) - 경고 반환:
out.warning(msg)— 이 행에 대해 NULL을 반환하고 SQL 경고를 추가하며 실행을 계속합니다. 엄격 모드에서는 MySQL이 INSERT/UPDATE 시 이를 오류로 승격시킵니다.out.set()대신 호출하고, 추가로 호출하지 마세요. - 오류 반환:
out.error(msg)— 문장 실행을 중단합니다
오류 처리
검증 실패나 잘못된 입력 시 사용자 정의 메시지로 오류를 반환하세요:VEF_RESULT_VALUE- 성공 (out.set(v)/out.set_length(n))VEF_RESULT_NULL- NULL 값 (out.set_null())VEF_RESULT_WARNING- 행 수준 경고 (NULL 반환, SQL 경고 추가, 실행 계속; 엄격 모드에서 INSERT/UPDATE 시 오류로 승격) (out.warning(msg))VEF_RESULT_ERROR- 치명적 오류, 문장 실행 중단 (out.error(msg))
프리런/포스트런을 통한 문장별 상태
프리런 및 포스트런 후크는 타입화된 래퍼를 사용합니다. 필수 서명은 다음과 같습니다:vef_prerun_args_t* / vef_postrun_args_t*)은 .prerun<&Hook>() 및 .postrun<&Hook>()에서 static_assert로 컴파일 타임에 거부됩니다.
PrerunArgs 및 PostrunArgs 메서드 세부 사항은 개발 가이드의 문장별 상태를 참조하세요.
대부분의 확장은 프리런/포스트런 후크가 필요하지 않습니다. VEF SDK는 일반적인 경우(예: 타입 검사 및 결과 버퍼 크기 조정)를 자동으로 처리합니다 — STRING 반환 및 CUSTOM 반환 VDF 모두에서 VDF 본문 실행 전 결과 버퍼가 해석된 반환 타입에 맞게 확장됩니다. 비용이 많이 드는 문장별 설정(예: 연결 열기)이 행별이 아닌 문장별로 발생해야 할 때만 프리런/포스트런을 사용하세요.사용 사례에서 프리런/포스트런이 필요하다면 VillageSQL Discord에서 시나리오를 공유하세요 — 팀이 자동으로 처리할 수 있는 SDK 지원을 추가할 수 있습니다.
집계 함수
내장 집계 함수 COUNT(DISTINCT), MIN, MAX, GROUP_CONCAT은 사용자 정의 유형과 별도의 설정 없이 바로 사용 가능합니다. MIN 및 MAX는 유형에 등록된 비교 함수가 필요합니다. 사용자 정의 집계 VDF도 지원됩니다.make_aggregate_func<State, &result_fn>("name")으로 등록한 후 .returns(), .param(), .clear<>(), .accumulate<>()를 호출한 다음 .build()를 호출하세요. .clear<>() 및 .accumulate<>() 모두 필수입니다. 빌더 API 및 콜백 서명은 집계 VDF를 참조하세요.
사용자 정의 유형과 함께 작동하는 내장 집계 연산:
- 각 함수 호출은 자체 결과 버퍼를 사용하여 한 행을 처리합니다(스레드 안전)
prerun/postrun은 문장별 설정/정리 제공- 글로벌 상태 피하기 - 함수 매개변수와 반환 값 사용
- 글로벌 상태를 사용해야 할 경우, 뮤텍스/락으로 보호하세요
윈도우 함수
다음 창 함수는 사용자 정의 유형과 함께 작동합니다:임시 테이블
사용자 정의 유형은 임시 테이블에서 작동합니다.CREATE TEMPORARY TABLE, INSERT, ALTER TABLE은 영구 테이블과 동일하게 작동합니다.
미리보기 API
일부 VEF 기능은 SDK 포함 트리의villagesql/preview/ 아래 옵트인 헤더로 사용할 수 있습니다. ABI 및 API는 여전히 개발 중이며 예고 없이 변경될 수 있습니다.
옵트인하려면 확장 소스에 포함을 추가하세요. 예를 들어:
<villagesql/vsql.h>에 의해 포함되지 않으므로, 옵트인할 때 직접 포함해야 합니다.
vsql::preview 아래의 네임스페이스 레이아웃은 기능별로 구성됩니다 — 단일 통합 패턴이 없습니다. 키링 API는 vsql::preview_keyring::KeyringCapability을 사용하고, 스레드 워커 API는 vsql::preview_thread_worker::ThreadWorkerCapability을 사용하며, SQL 쿼리 API는 vsql::preview_sql_query::SqlQueryCapability을 사용하고 백그라운드 워커 스레드 핸들(vef_thread_handle_t *)에서 열어야 합니다. 각 헤더의 정확한 네임스페이스 및 클래스 이름을 확인하세요.
전체 미리보기 API 문서는 미리보기 기능을 참조하세요.
트리거
트리거는 사용자 정의 유형 열이 있는 테이블에서 발생합니다. 트리거 본문은NEW 및 OLD에서 사용자 정의 유형이 아닌 열을 참조할 수 있습니다. 트리거 본문 내에서 사용자 정의 유형 열 값을 접근하는 기능은 아직 지원되지 않습니다.

