> ## Documentation Index
> Fetch the complete documentation index at: https://villagesql.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Rust SDK API 참조

> VillageSQL Rust SDK의 완전한 참조 — InValue, VdfReturn, extension!, func!, custom_type!, custom!, manifest.json 필드.

<Note>
  Rust SDK는 버전 0.0.1입니다.
</Note>

이 페이지는 `villagesql` 크레이트 API에 대한 참조입니다. 시작하기 가이드는 [Rust로 확장 빌드](/docs/ko/mysql-8.4/0.0.4/rust-sdk)를 참조하세요. 사용자 정의 타입에 대해서는 [Rust에서 사용자 정의 타입](/docs/ko/mysql-8.4/0.0.4/rust-custom-types)을 참조하세요.

## InValue

`InValue`은 서버가 각 함수 인수에 대해 전달하는 열거형입니다. 함수는 `args: &[InValue]`를 받으며, 값을 사용하기 전에 각 인수를 확인해야 합니다.

```rust theme={null}
pub enum InValue<'a> {
    String(&'a str),
    Real(f64),
    Int(i64),
    Null,
    Custom(&'a [u8]),
}
```

| 배리언트(Variant)   | Rust 타입        | 해당 SQL 타입                        |
| --------------- | -------------- | -------------------------------- |
| `String(&str)`  | UTF-8 문자열 슬라이스 | `STRING` / `VARCHAR` / `TEXT`    |
| `Real(f64)`     | 64비트 부동소수점     | `REAL` / `DOUBLE` / `FLOAT`      |
| `Int(i64)`      | 64비트 부호 있는 정수  | `INT` / `BIGINT` / `TINYINT`     |
| `Null`          | —              | 모든 타입의 SQL `NULL`                |
| `Custom(&[u8])` | 원시 바이너리 바이트    | `custom_type!`을 통해 등록된 사용자 정의 타입 |

`Null`을 명시적으로 매치해야 합니다. `.unwrap()`을 호출하거나 값 변형만 패턴 매칭하는 것은 버그입니다 — SQL NULL은 오류가 아닌 정상적인 입력입니다.

## VdfReturn

`VdfReturn`은 함수가 서버에 반환하는 것입니다. 연관 함수 중 하나로 구성합니다:

| 생성자                        | SQL 효과                                                 |
| -------------------------- | ------------------------------------------------------ |
| `VdfReturn::null()`        | 이 행에 SQL NULL을 반환합니다                                   |
| `VdfReturn::string(s)`     | `String` 값을 반환합니다; `s`는 `impl Into<String>`입니다         |
| `VdfReturn::real(v)`       | `f64` 값을 반환합니다                                         |
| `VdfReturn::int(v)`        | `i64` 값을 반환합니다                                         |
| `VdfReturn::binary(bytes)` | 사용자 정의 타입 열에 대한 바이너리 바이트를 반환합니다; `bytes`는 `Vec<u8>`입니다 |
| `VdfReturn::warning(msg)`  | 이 행에 NULL을 반환하고 SQL 경고를 추가합니다(실행은 계속됩니다)               |
| `VdfReturn::error(msg)`    | 치명적 오류로 문을 중단합니다                                       |

**경고 vs 오류:**

사용자 입력 검증 실패 시 결과 집합의 나머지 부분을 계속 처리하는 것이 합리적인 경우 `warning`을 사용하세요. 엄격 모드에서는 MySQL이 `INSERT` 및 `UPDATE`에서 경고를 오류로 승격시킵니다. 데이터가 손상되거나 내부 불변 조건 위반과 같은 안전하지 않은 상황에서는 `error`을 사용하세요. 치명적 오류는 전체 문을 중단합니다.

```rust theme={null}
fn validate_impl(args: &[InValue]) -> VdfReturn {
    match args.first() {
        Some(InValue::Int(n)) if *n >= 0 => VdfReturn::int(*n),
        Some(InValue::Int(_)) => VdfReturn::warning("value must be non-negative"),
        Some(InValue::Null) | None => VdfReturn::null(),
        _ => VdfReturn::error("validate: expected an INT argument"),
    }
}
```

## extension! 매크로

`extension!`은 서버가 VEB 파일을 로드할 때 호출하는 VEF 엔트리 포인트를 생성합니다. 이는 크레이트 내에서 정확히 한 번만 나타나야 합니다.

```rust theme={null}
villagesql::extension! {
    funcs: [
        // One or more villagesql::func!(...) declarations
    ],
    types: [
        // One or more villagesql::custom_type!(...) declarations
    ]
}
```

두 섹션 모두 선택 사항입니다. 순수 함수 확장은 `types:`를 생략하고, 타입만 있는 확장은 `funcs:`를 생략합니다. 빈 `extension!` 블록(함수 없음, 타입 없음)은 유효하지만 아무 작업을 하지 않는 확장을 생성합니다.

## func! 매크로

`func!`은 SQL 호출 가능한 함수를 선언합니다. 위치 인수:

```rust theme={null}
villagesql::func!(rust_fn, "sql_name", [param_types] -> return_type)
villagesql::func!(rust_fn, "sql_name", [param_types] -> return_type, deterministic: true)
```

| 인수                    | 설명                                                                                                                   |
| --------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `rust_fn`             | VDF를 구현하는 Rust 함수입니다. 서명: `fn(&[InValue]) -> VdfReturn`.                                                             |
| `"sql_name"`          | SQL 함수 이름을 문자열 리터럴로 지정합니다. 이 이름을 SQL에서 사용자 호출에 사용합니다.                                                                |
| `[param_types]`       | `,`로 구분된 `villagesql::Type::*` 또는 `villagesql::custom!("name")` 값 목록입니다. 0개 인수 함수에는 `[]`를 사용합니다.                     |
| `return_type`         | `villagesql::Type::*` 또는 `villagesql::custom!("name")`입니다.                                                           |
| `deterministic: true` | 선택 사항입니다. 함수가 결정적임을 선언합니다 — 동일한 입력은 항상 동일한 출력을 생성하며, 부작용이 없습니다. 최적화 도구는 동일한 입력에 대한 결과를 캐시할 수 있습니다. 이 값이 참일 때만 설정하세요. |

**타입 상수** (`func!`에서 사용):

| `villagesql::Type::*`      | SQL 타입   |
| -------------------------- | -------- |
| `villagesql::Type::String` | `STRING` |
| `villagesql::Type::Real`   | `REAL`   |
| `villagesql::Type::Int`    | `INT`    |

## custom\_type! 매크로

`custom_type!`은 새로운 열 타입을 등록합니다. `type_name`, `persisted_length`, `max_decode_buffer_length`, `encode`, `decode`, `compare`는 필수이며, `hash`와 `default`는 선택적이지만 권장됩니다.

```rust theme={null}
villagesql::custom_type!(
    type_name: "sql_type_name",
    persisted_length: N,
    max_decode_buffer_length: M,
    encode: encode_fn,
    decode: decode_fn,
    compare: compare_fn,
    hash: hash_fn,
    default: "default_string",
)
```

| 필드                         | 타입                                       | 설명                                                                                              |
| -------------------------- | ---------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `type_name`                | `&str` 리터럴                               | 타입에 대한 SQL 이름입니다. SQL에서 대소문자 구분이 없습니다. 모든 설치된 확장 프로그램 간에 고유해야 합니다.                              |
| `persisted_length`         | `usize`                                  | 디스크에 저장할 때 고정된 바이트 길이입니다. 모든 인코딩된 값은 정확히 이 길이의 바이트를 생성해야 합니다.                                   |
| `max_decode_buffer_length` | `usize`                                  | 디코딩된 문자열의 최대 바이트 길이입니다. `decode` 호출 전 출력 버퍼 크기를 결정하는 데 사용됩니다.                                   |
| `encode`                   | `fn(&str) -> Result<Vec<u8>, String>`    | `INSERT` 시 호출됩니다. SQL 문자열 리터럴을 바이너리로 변환합니다. 입력을 거부하려면 `Err(msg)`를 반환하세요.                        |
| `decode`                   | `fn(&[u8]) -> Result<String, String>`    | 값 표시 시 호출됩니다. 바이너리를 문자열로 변환합니다.                                                                 |
| `compare`                  | `fn(&[u8], &[u8]) -> std::cmp::Ordering` | `ORDER BY`, `MIN`, `MAX`에 호출됩니다. `Less`, `Equal`, 또는 `Greater`를 반환합니다.                          |
| `hash`                     | `fn(&[u8]) -> usize`                     | 선택 사항입니다. `COUNT(DISTINCT)` 및 집합 연산에 호출됩니다. 비교 결과가 `Equal`인 값은 동일한 해시 값을 가져야 합니다. 인덱스 열에 권장됩니다. |
| `default`                  | `&str` 리터럴                               | 선택 사항입니다. 서버가 타입 초기화 시 인코딩하여 콜백이 작동하는지 검증하는 데 사용됩니다. 정확히 `persisted_length` 바이트로 인코딩되어야 합니다.    |

`default` 필드는 열 기본값이 아닙니다 — 시작 확인입니다. 서버는 확장 프로그램을 로드할 때 `encode(default)`를 호출하여 콜백이 작동하는지 확인합니다. `encode`가 기본값에 대해 `Err`를 반환하면 확장 프로그램이 로드되지 않습니다.

## custom! 매크로

`villagesql::custom!("type_name")`은 `func!` 선언에서 사용자 정의 타입의 이름을 참조합니다:

```rust theme={null}
villagesql::func!(
    my_fn,
    "my_sql_func",
    [villagesql::custom!("mytype")] -> villagesql::custom!("mytype"),
    deterministic: true
)
```

`villagesql::Type::*`이 매개변수 목록이나 반환 타입 위치에 나타나는 곳이라면 어디서든 사용할 수 있습니다. 문자열은 해당 `custom_type!`에서 선언된 `type_name`과 일치해야 합니다.

## manifest.json 필드

모든 확장 프로그램은 `Cargo.toml`과 함께 `manifest.json`이 필요합니다:

```json theme={null}
{
  "name": "vsql_my_extension",
  "version": "0.1.0",
  "description": "Brief description of what the extension does",
  "author": "Your Name",
  "license": "GPL-2.0"
}
```

| 필드            | 필수  | 형식                | 설명                                                                                     |
| ------------- | --- | ----------------- | -------------------------------------------------------------------------------------- |
| `name`        | 예   | 소문자, 숫자, `_`, `-` | 확장 프로그램 식별자입니다. `INSTALL EXTENSION` 이름과 일치해야 합니다. 밑줄을 사용하세요 — 대시는 SQL에서 백틱으로 인용해야 합니다. |
| `version`     | 예   | MAJOR.MINOR.PATCH | 세미틱 버전입니다.                                                                             |
| `description` | 아니요 | String            | `INFORMATION_SCHEMA.EXTENSIONS`에 표시됩니다.                                                |
| `author`      | 아니요 | String            | 저자 이름 또는 조직입니다.                                                                        |
| `license`     | 아니요 | String            | 라이선스 식별자입니다. 오픈소스 확장 프로그램에는 `GPL-2.0`이 권장됩니다.                                          |

`name` 검증 규칙: 첫 글자는 알파벳, 마지막 글자는 알파벳 또는 숫자여야 하며, 최대 64자입니다. 유효하지 않은 매니페스트는 `INSTALL EXTENSION`을 실패시킵니다.
