> ## 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.

# 拡張機能と ABI の動作

> このページでは、VillageSQL 拡張機能の ABI について解説します。サーバーが所有するもの、拡張機能が所有するもの、そしてその分担がクラッシュリカバリ、レプリケーション、リストア、スキーマ操作全体でどのように機能するかを説明します。

VillageSQL 拡張フレームワーク（VEF）は、MySQL サーバーコードの所定の場所で拡張機能のコードを呼び出します。拡張機能の出力に対して発生するすべての処理（クラッシュリカバリ、レプリケーション、スキーマ操作、バックアップ）は、組み込みの列型を処理するのと同じ方法でサーバーによって処理されます。このドキュメントでは、その境界について説明します。VEF が何を行い、拡張機能が何を行い、その結果として得られるシステムが運用時にどのように動作するかを解説します。

このページ全体の例では、[vsql-uuid](https://github.com/villagesql/vsql-uuid) 拡張機能を使用して、データの流れを説明します。

## ABI の境界

VillageSQL 拡張機能は、バイナリインターフェース（ABI）を通じてサーバーと相互作用し、拡張機能とサーバーの間で所有権が明確に分離されています。

**サーバーが所有するもの:**

* ストレージ: InnoDB はバイトの読み書きを行いますが、その内容は解釈しません。
* スキーマ: 列型のメタデータと、どの拡張機能が各型を登録したかという情報は、VillageSQL システムテーブルに保存され、再起動後も保持されます。
* リカバリ、レプリケーション、バックアップ: これらは、組み込みの列型と同様に、生のバイトを操作します。
* 拡張機能の登録: 名前、バージョン、および関数/型の登録は、起動時に VillageSQL システムテーブルから再ロードされます。

**拡張機能が所有するもの:**

* バイナリ形式: `from_string` エンコード関数が、ディスクに書き込まれる内容を定義します。`to_string` は、出力時にそれを読み戻します。
* ビジネスルール: 検証、比較、ハッシュ化、エラー処理。
* 状態: 拡張機能は、サーバーが保存するバイト以外には何も永続化しません。

完全なバイナリインターフェース（構造体、関数ポインタの typedef、プロトコルのバージョン管理）については、サーバーリポジトリの [`villagesql/sdk/include/villagesql/abi/types.h`](https://github.com/villagesql/villagesql-server/blob/main/villagesql/sdk/include/villagesql/abi/types.h) を参照してください。

## カスタム型の保存方法

列を `UUID`（vsql-uuid の例）として宣言すると、サーバーは行ごとに固定長の生バイトブロックを保存します。人間が読める形式（`d7d665f3-bb13-4c2f-b10f-d2126eb40cba` など）は、境界にのみ存在します。`from_string` は書き込み時にそれをバイナリにエンコードし、`to_string` は読み取り時にそれをデコードして戻します。その間のすべて（ストレージ、redo ログ、クラッシュリカバリ、バイナリログ）は、内容を解釈せずにそれらのバイトを操作します。

## クラッシュリカバリ

拡張機能は、サーバーの再起動時に自動的に再ロードされます。手動による介入は不要です。これは `INFORMATION_SCHEMA.EXTENSION_REGISTRATION` で確認できます。再起動後も、再起動前と同じ登録エントリが表示されます。

行データは、InnoDB の通常のクラッシュリカバリを通じて保持されます。拡張機能のバイナリ形式が特別扱いされることはありません。InnoDB は、UUID 列を `VARBINARY` 列と何ら変わりなく処理します。

## バイナリログ形式

行形式のレプリケーション（デフォルト）では、カスタム型の値は、バイナリログ内を生のバイナリとして流れます。再エンコードのステップはありません。binlog の書き込み時に拡張機能の `from_string` は呼び出されず、`to_string` はクライアントが値を読み戻すときにのみ呼び出されます。

UUID 列の行レベルのバイナリログエントリは、次のようになります。

```
### INSERT INTO `abi_test`.`t1`
### SET
###   @1='\xd7\xd6\x65\xf3\xbb\x13\x4c\x2f\xb1\x0f\xd2\x12\x6e\xb4\x0c\xba'
###   @2='alpha'
```

これら 16 個の生バイトは、変更されずにバイナリログを流れます。拡張機能がインストールされているコンシューマは、`to_string` を介してそれらを読み取り可能な値にデコードできます。拡張機能がないコンシューマ（外部の CDC パイプラインや binlog リーダー）には、生のバイトのみが表示されます。

## リストア

VillageSQL サーバーのリストアは、クラッシュリカバリと同じように機能します。サーバーが起動し、拡張機能の登録を読み取り、各拡張機能を自動的にロードします。拡張機能型の列に特別な処理は必要ありません。生のバイトはバックアップ内にあり、拡張機能はオンデマンドでそれらをデコードします。

拡張機能はデータベース内には保存されず、ディスク上の `veb_dir` に `.veb` ファイルとして存在します。リストアしたインスタンスでサーバーが起動するときに VEB ファイルが見つからない場合、起動は `VEB file not found` で中止されます。`.veb_expansion_cache` は、`.veb` 自体の代わりにはなりません。拡張機能を配布するときは、バックアップやサーバー移行の際に、データディレクトリと一緒に `veb_dir` を含める必要があることをユーザーに周知してください。

## スキーマ操作

拡張機能型の列を持つテーブルに対する `ALTER TABLE` は、組み込み型の場合とまったく同じように動作します。サーバーは、列の拡張機能バインディングをスキーマメタデータで追跡し、そのバインディングはテーブルの再構築後も保持されます。vsql-uuid の `id` 列を持つテーブルに他の列を追加または変更しても、UUID データはそのまま残ります。
