Skip to main content
Rust SDK는 알파 단계입니다 — 릴리스 간에 호환성이 깨지는 API 변경이 발생할 수 있습니다. 함수 전용 확장, 집계 함수, 가변 인자 함수, 그리고 사용자 정의 타입(encode, decode, compare, hash)이 지원되며, sys_var, status_var, thread_worker, keyring 미리보기 기능도 지원됩니다. 컬럼 저장 ABI는 현재 C++ 전용입니다 — 이 기능이 필요하다면 C++ SDK를 사용하세요.
사용자 정의 타입을 통해 RATIONAL, VECTOR, 또는 INET과 같은 새로운 컬럼 타입을 정의할 수 있습니다. 이러한 타입은 ORDER BY, 인덱스, 및 집계 함수와 함께 작동합니다. Rust SDK는 custom_type! 매크로를 통해, 그리고 저장 크기가 컬럼 매개변수에 따라 달라지는 타입에 대해서는 parameterized_type!을 통해 이를 지원합니다(매개변수화된 타입 참조). 이 페이지는 이미 Rust에서 확장 빌드를 완료했음을 전제로 합니다. 설정(Cargo.toml, manifest.json, cargo-vsql)은 동일합니다.

사용자 정의 타입을 사용해야 하는 경우

다음과 같은 경우 사용자 정의 타입을 사용하세요:
  • 표준 SQL 타입으로 표현할 수 없는 디스크 상의 이진 레이아웃이 필요할 때(압축된 부동소수점, 고정 폭 정수, 이진 식별자)
  • 타입 자체가 사전식 문자열 정렬과 다른 순서 의미론을 가질 때
  • 서버가 ORDER BY, COUNT(DISTINCT), 및 집합 연산을 위해 값들을 올바르게 인덱싱하고 해시하도록 하려 할 때
SQL 호출 가능한 함수만 필요하고 데이터를 STRING, INT, 또는 REAL 컬럼에 무리 없이 담을 수 있을 경우, 사용자 정의 타입이 필요하지 않습니다.

custom_type! 매크로

모든 사용자 정의 타입은 4개의 콜백(인코딩, 디코딩, 비교, 해시)과 기본값이 필요합니다. 전체 매크로 서명은 다음과 같습니다:
type_name, persisted_length, max_decode_buffer_length, encode, decode, compare는 필수입니다. hashdefault는 선택적이지만 권장됩니다 — hash는 올바른 COUNT(DISTINCT) 및 집합 연산을 위해 필요하며, default는 타입 초기화 검증을 위해 필요합니다.

이진 값 수신 및 반환

사용자 정의 타입을 받거나 반환하는 함수는 원시 바이트를 다룹니다. 입력InValue::Custom(b)는 저장된 이진 데이터를 &[u8]로 전달합니다:
출력VdfReturn::Binary(bytes)는 이진 바이트를 서버로 전송합니다:
func! 선언에서 사용자 정의 타입을 참조하려면 villagesql::custom!("type_name")을 사용합니다:

예시: 유리수 타입

SDK 리포지토리의 examples/vsql_rationalRATIONAL 타입을 구현하는 작동하는 확장입니다. 이 타입은 유리수를 리틀 엔디안 바이트 순서로 16바이트의 i64 값 쌍(분자, 분모)으로 저장하고 산술 함수를 제공합니다. 다음은 핵심 인코딩, 디코딩, 비교, 해시 구현입니다:
custom_type! 등록 및 산술 VDF(rational_add, rational_sub 등)는 examples/vsql_rational/src/lib.rs의 전체 소스에 있습니다. 확장이 설치된 후:
rational_to_real(r RATIONAL) -> REAL은 분자를 분모로 나누어 RATIONAL 값을 64비트 부동소수점 근사치로 변환합니다. 표시나 비교를 위해 근사 소수를 필요로 하지만 열에 손실형 표현을 저장하고 싶지 않을 때 유용합니다.

매개변수화된 타입

매개변수화된 타입은 저장 크기를 알기 위해 CREATE TABLE 시점에 읽는 값이 필요합니다 — VECTOR(3)3 같은 값입니다. custom_type!은 이를 표현할 수 없습니다: 그 persisted_length는 모든 컬럼에 대해 하나의 고정 상수입니다. parameterized_type!은 매개변수화된 대응물로, 저장 길이가 고정되는 대신 int_to_paramsresolve_params를 통해 선언된 매개변수로부터 컬럼마다 계산됩니다.
type_name, max_persisted_length, max_decode_buffer_length, encode, decode, compare, int_to_params, resolve_params, params_type, params_parse, params_to_strings는 필수입니다. hashdefault는 선택적입니다. intrinsic_default_fn(기본값이 매개변수에 따라 달라질 때 &P로부터 기본값을 계산하는 함수) 또한 선택적이며 default와 상호 배타적입니다. 다음은 padint입니다 — 고정된 8바이트에 저장되는 i64이며, width 매개변수가 0으로 채워지는 표시 폭을 제어합니다:
매개변수화된 사용자 정의 타입 인수를 받는 함수는 일반 InValue::Custom(bytes)가 아니라 InValue::CustomWithParams { bytes, params }를 봅니다 — params는 컬럼에 선언된 key=value 쌍에 대한 읽기 전용, 무복사 뷰인 [TypeParams]입니다.

extension! 블록과 타입

함수와 타입을 모두 등록할 때, extension! 블록은 두 개의 섹션을 가집니다:
함수만 포함하는 확장은 types:를 생략합니다. 타입만 포함하는 확장은 funcs: []를 유지하며 그 밖의 것은 생략하지 않습니다.

다음 단계

Rust API 참조

InValue, VdfReturn, 및 모든 매크로에 대한 완전한 참조.

Rust에서 확장 빌드

시작하기 — Cargo 설정, 첫 번째 함수, 패키징 및 테스트.

C++ 사용자 정의 타입

C++에서의 사용자 정의 타입 — make_type<>, 인코딩/디코딩/비교/해시, ALTER TABLE 규칙.

확장 아키텍처

사용자 정의 타입이 해석, 캐시, 저장되는 방식.