Skip to main content
이 페이지는 확장 개발자용 참조입니다. 단계별 튜토리얼은 확장 만들기를 참조하세요. 사용자 정의 열 유형은 사용자 정의 유형 만들기를 참조하세요.

VDF 함수 계약

이 계약은 VDF 구현 함수가 VEF 런타임과 상호작용하는 방식을 규정합니다. make_func<>를 통해 등록된 모든 함수는 이 계약을 따라야 합니다. 아래에서 참조하는 타입은 #include <villagesql/vsql.h>를 통해 사용할 수 있습니다.

Part A: VDF 함수 계약

1. VDF 구현 함수는 void입니다 — 값은 절대 반환하지 않습니다.
성공, NULL, 경고, 오류를 전달하려면 결과 래퍼의 종료 메서드 중 하나를 호출하세요: 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()를 호출하는 것은 정의되지 않은 동작입니다.
4. 문자열 결과의 경우, out.buffer()에 쓰고 out.set_length(n)을 호출하세요. 쓰기 전에 out.buffer().size()를 확인하세요.
  • out.buffer()는 서버 관리 버퍼에 대한 Span<char>을 반환합니다.
  • out.set_length(n)은 쓴 바이트 수를 기록합니다.
  • out.buffer().size()는 최대 용량입니다. 항상 쓰기 전에 확인하세요.
5. 오류 메시지를 out.error(msg)에 전달하세요. 필요 시 메시지는 VEF_MAX_ERROR_LEN(512바이트)로 자릅니다. out.error(msg)std::string_view를 허용합니다. 메시지를 서버 관리 버퍼에 복사하고 결과 상태를 오류로 설정하는 한 번의 호출로 처리합니다.

래퍼 함수 구현

구현 함수는 타입화된 인수 및 결과 래퍼를 사용합니다:

NULL 값 처리

is_null()을 통해 NULL을 확인하고 set_null()을 호출하여 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))

프리런/포스트런을 통한 문장별 상태

프리런 및 포스트런 후크는 타입화된 래퍼를 사용합니다. 필수 서명은 다음과 같습니다:
원시 ABI 서명(vef_prerun_args_t* / vef_postrun_args_t*)은 .prerun<&Hook>().postrun<&Hook>()에서 static_assert로 컴파일 타임에 거부됩니다.
PrerunArgsPostrunArgs 메서드 세부 사항은 개발 가이드의 문장별 상태를 참조하세요.
대부분의 확장은 프리런/포스트런 후크가 필요하지 않습니다. 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 문서는 미리보기 기능을 참조하세요.
미리보기 헤더는 안정적이지 않습니다. 미리보기 헤더를 기반으로 빌드된 확장은 서버가 업데이트될 때 깨질 수 있습니다. 기능이 안정화되면 해당 헤더는 버전화된 안정 SDK 경로로 이동됩니다.

트리거

트리거는 사용자 정의 유형 열이 있는 테이블에서 발생합니다. 트리거 본문은 NEWOLD에서 사용자 정의 유형이 아닌 열을 참조할 수 있습니다. 트리거 본문 내에서 사용자 정의 유형 열 값을 접근하는 기능은 아직 지원되지 않습니다.