> ## 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 构建扩展

> 开始使用 VillageSQL Rust SDK — 使用安全的 Rust 编写扩展函数，将其打包为 VEB 文件，并将其安装到 VillageSQL 中。

<Warning>
  Rust SDK 处于 alpha 阶段 — 各版本之间可能会有破坏性的 API 变更。
  仅支持函数扩展和自定义类型（encode、decode、compare、hash）。聚合函数、
  `prerun()`、`VarArgs`、系统变量和状态变量、密钥环访问以及列存储 ABI
  目前仅支持 C++ — 如果您需要其中任何一项，请使用
  [C++ SDK](/docs/zh/mysql-8.4/0.0.5/create)。
</Warning>

<Note>
  如果您更喜欢 C++，请参阅 [使用 C++ 创建扩展](/docs/zh/mysql-8.4/0.0.5/create)，了解 C++ SDK 的操作指南。
</Note>

可以使用 `villagesql` crate 用 Rust 编写 VillageSQL 扩展。SDK 处理所有 FFI 编组 — 您可以使用普通的 Rust 类型，`extension!` 宏会在加载时生成服务器调用的 C 入口点。

## 先决条件

在开始之前，请先从源代码构建 VillageSQL — 扩展会链接到服务器的构建树。请先按照 [从源代码构建](/docs/zh/mysql-8.4/0.0.5/source) 指南操作。

您还需要：

* **Rust 稳定工具链** — 在 [rustup.rs](https://rustup.rs) 上安装
* **Git** — 用于克隆 SDK 和您的扩展仓库
* **cargo-vsql** — Cargo 的子命令，用于打包、安装和测试扩展
* **VillageSQL 构建目录** — 将 `VillageSQL_BUILD_DIR` 设置为服务器的构建路径，以便 `cargo vsql install` 和 `cargo vsql test` 正常工作
* **基本的 Rust 知识** — 熟悉 Cargo、枚举和模式匹配

从 SDK 仓库安装 `cargo-vsql`：

```bash theme={null}
git clone https://github.com/villagesql/vsql-rust-sdk
cd vsql-rust-sdk
cargo install --path cargo-vsql
```

验证它是否可用：

```bash theme={null}
cargo vsql --help
```

## 创建一个新的 crate

创建一个新的 Rust 库 crate：

```bash theme={null}
cargo new --lib vsql_rot13
cd vsql_rot13
```

编辑 `Cargo.toml` 以设置 crate 类型并添加 `villagesql` 依赖项：

```toml theme={null}
[package]
name = "vsql_rot13"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
villagesql = "0.0.1"
```

`cdylib` crate 类型告诉 Cargo 生成一个共享库（Linux 上的 `.so`，macOS 上的 `.dylib`），服务器可以加载它。

## 编写您的第一个函数

将 `src/lib.rs` 替换为完整的扩展：

```rust theme={null}
use villagesql::{InValue, VdfReturn};

fn rot13_impl(args: &[InValue]) -> VdfReturn {
    match args.first() {
        Some(InValue::String(s)) => VdfReturn::string(rot13(s)),
        Some(InValue::Null) | None => VdfReturn::null(),
        _ => VdfReturn::error("vsql_rot13: expected a STRING argument"),
    }
}

fn rot13(s: &str) -> String {
    s.chars()
        .map(|c| match c {
            'a'..='m' | 'A'..='M' => (c as u8 + 13) as char,
            'n'..='z' | 'N'..='Z' => (c as u8 - 13) as char,
            _ => c,
        })
        .collect()
}

villagesql::extension! {
    funcs: [
        villagesql::func!(rot13_impl, "vsql_rot13", [villagesql::Type::String] -> villagesql::Type::String),
    ]
}
```

`func!` 宏将 `rot13_impl` 绑定到 SQL 名称 `vsql_rot13`，签名是 `STRING -> STRING`。

函数签名是 `fn(&[InValue]) -> VdfReturn`。`InValue` 是服务器传递的 SQL 类型枚举。`VdfReturn` 是您返回的内容。在访问值之前，检查 `args.first()` 以处理 NULL 情况和类型错误的情况。

如果您的函数对于相同的输入始终返回相同的输出，请声明为确定性函数 — 优化器可以缓存相同输入的结果：

```rust theme={null}
villagesql::func!(rot13_impl, "vsql_rot13", [villagesql::Type::String] -> villagesql::Type::String, deterministic: true)
```

## 添加 manifest.json

在 crate 根目录（`Cargo.toml` 旁边）创建 `manifest.json`：

```json theme={null}
{
  "name": "vsql_rot13",
  "version": "0.1.0",
  "description": "ROT-13 encoding for VillageSQL",
  "author": "Your Name",
  "license": "GPL-2.0"
}
```

服务器会在安装时读取此文件。`name` 字段必须与您传递给 `INSTALL EXTENSION` 的内容匹配。

## 构建和安装

<Note>
  从扩展目录（`Cargo.toml` 和 `manifest.json` 所在的位置）运行 `cargo vsql package`、`cargo vsql install` 和 `cargo vsql test`，而不是从工作区根目录运行。
</Note>

将扩展打包到 `.veb` 文件中：

```bash theme={null}
cargo vsql package
```

这将生成 `dist/vsql_rot13.veb`。要将 VEB 打包并直接复制到您的 VillageSQL 构建目录：

```bash theme={null}
export VillageSQL_BUILD_DIR=/path/to/villagesql/build
cargo vsql install
```

要在开发期间使用本地副本覆盖依赖项，请传递 `--config KEY=VALUE`（可重复）：

```bash theme={null}
cargo vsql install --config 'patch.crates-io.villagesql.path="/path/to/villagesql"'
```

您应该看到 VEB 复制到扩展目录。验证其是否已正确放置：

```bash theme={null}
ls "$VillageSQL_BUILD_DIR/veb_dir/"
# vsql_rot13.veb
```

## 测试

在 `mysql-test/t/rot13_basic.test` 中编写一个测试文件：

```sql theme={null}
INSTALL EXTENSION vsql_rot13;
SELECT vsql_rot13('Hello');
SELECT vsql_rot13('');
SELECT vsql_rot13(NULL);
UNINSTALL EXTENSION vsql_rot13;
```

生成预期的结果：

```bash theme={null}
cargo vsql test --record
```

运行测试套件：

```bash theme={null}
cargo vsql test
```

在修改函数的行为后，重新运行 `cargo vsql test --record` 以更新预期的结果，然后运行 `cargo vsql test` 以确认。

## 在 SQL 中安装

VEB 位于扩展目录中后，安装它：

```sql theme={null}
INSTALL EXTENSION vsql_rot13;
```

验证：

```sql theme={null}
SELECT * FROM INFORMATION_SCHEMA.EXTENSIONS WHERE EXTENSION_NAME = 'vsql_rot13';
```

调用它：

```sql theme={null}
SELECT vsql_rot13('Hello, World!');
-- → Uryyb, Jbeyq!
```

## 后续步骤

<CardGroup cols={2}>
  <Card title="Rust 中的自定义类型" icon="shapes" href="/docs/zh/mysql-8.4/0.0.5/rust-custom-types">
    定义具有二进制存储、排序和哈希的新列类型。
  </Card>

  <Card title="Rust API 参考" icon="book" href="/docs/zh/mysql-8.4/0.0.5/rust-api-reference">
    InValue、VdfReturn、extension!、func! 和 custom\_type! — 所有字段。
  </Card>

  <Card title="C++ SDK（创建扩展）" icon="code" href="/docs/zh/mysql-8.4/0.0.5/create">
    C++ 方案 — 类型化包装器、构建器 API 和 CMake 设置。
  </Card>

  <Card title="扩展架构" icon="sitemap" href="/docs/zh/mysql-8.4/0.0.5/architecture">
    VEB 文件如何加载、生命周期钩子和符号隔离。
  </Card>

  <Card title="测试依赖网络的扩展" icon="network-wired" href="/docs/zh/mysql-8.4/0.0.5/testing-network">
    针对会启动 HTTP 服务器或外部监听器的扩展的 MTR 端口模式 — 同样适用于 Rust 和 C++ 扩展。
  </Card>
</CardGroup>
