vsql_allow_preview_extensions = ON が設定されている場合にのみインストールできます(プレビュー層の有効化を参照)—プレビュー機能を使用しない拡張機能は、この設定に関係なく通常通りインストールされます。
プレビュー層の有効化
プレビュー機能を使用する拡張機能をインストールする前に、SET PERSIST を使用して vsql_allow_preview_extensions = ON を設定します:
SET GLOBAL はこの変数に対して拒否されます — サーバーは設定を再起動後に保持するために SET PERSIST を要求します。プレビュー機能を持つ拡張機能は起動時にロードされるため、サーバーが起動する時点でこの変数が ON である必要があります。
mysqld を直接起動する場合(例:サーバーを初めて起動するインストールスクリプトから)、コマンドライン引数でフラグを渡してください — mysqld-auto.cnf がまだ存在しないため、永続化された値を保持できません:
機能インデックス
登録パターン
プレビュー機能を使用するには、ファイルスコープで機能オブジェクトを値として宣言し、make_extension() 内の .with() に参照で渡します。サーバーは登録時にオブジェクトの abi ポインタを設定します:
.with(capability) はサーバーに拡張機能が必要とする機能を伝えます。拡張機能をインストールする際に vsql_allow_preview_extensions がオフの場合、サーバーはその機能名を示すエラーを返してインストールを拒否します。
Keyring アクセス
keyring 機能(vsql::preview::keyring)は、MySQL keyring コンポーネントに格納されたシークレットを拡張機能が読み書きできるようにします。APIキー、暗号化キー、またはSQLテーブルに保存したくないその他のシークレットに使用します。
機能名 VEF_PREVIEW_KEYRING_NAME は "vsql::preview::keyring" です。
読み書きが成功するには、MySQLサーバーに keyring コンポーネントがインストールされている必要があります。インストールされていない場合、操作は KeyringCapability::Status::UNAVAILABLE を返します。
ステータス値
KeyringCapability::Status は read()(ReadResult 内)および write() から返されるスコープ付き列挙型です:
機能の宣言
ヘッダーを含め、ファイルスコープで機能オブジェクトを宣言し、.with() に渡します:
g_keyring オブジェクトはロード時にサーバーによって初期化されます。keyring コンポーネントがインストールされていない場合、read() および write() は実行時に Status::UNAVAILABLE を返します — 別の利用可能性チェックで処理をガードする代わりに、各呼び出しでステータスを確認してください。
読み書き
data_id はキー識別子です。auth_id は所有ユーザーです — 内部キー(特定のユーザーに関連付けられていない)を読み書きするには空文字列(または read では省略、デフォルトは {})を渡します。
read は値で ReadResult を返します。構造化バインディングでバインドします:
Status::OK 以外のステータスの場合、value は空です。
write は直接 Status を返し、data を data_id / auth_id で格納します。
完全な例
これはサーバーに同梱されるvsql_keyring_reader テスト拡張機能の簡略化されたバージョンです。2つの VDF を登録します:keyring_read および keyring_store。
ステータス変数
status_var 機能(vsql::preview::status_var)は、拡張機能が MySQL ステータス変数として long long および double カウンターを公開できるようにします。拡張機能はストレージを所有し、値を書き込みます。サーバーはステータス変数がクエリされるたびにポインタ経由で読み取ります。
vsql::preview_status_var::make_capability() で機能を構築し、make_int(name, value_ptr) または make_double(name, value_ptr) から得られる記述子のブレースリストを渡します。テンプレートはブレースリストからカウントを推測するため、明示的なサイズは必要ありません。
完全な例
make_int には long long * が必要です。make_double には double * が必要です。これらがサポートされる唯一の2つの型です。
SQL からのアクセス
INSTALL EXTENSION my_ext 後、変数は拡張機能名をプレフィックスとして表示されます:
++ で同時にインクリメントする場合、まれに値が失われる可能性がありますが、SHOW STATUS で公開される近似カウンターとしては許容されます。
システム変数
sys_var 機能(vsql::preview::sys_var)は、拡張機能所有のストレージに紐付けられた MySQL システム変数を登録できるようにします。3つの型がサポートされます:BOOL(bool *)、INT(long long *)、STR(char **)。INT 記述子には min_val および max_val の境界が含まれます。すべての記述子にはデフォルト値とコメントが含まれます。
vsql::preview_sys_var::make_capability() で機能を構築し、対応するファクトリ関数 make_bool、make_int、make_str を使用します。機能オブジェクトは get() および set() を公開し、拡張機能コードからのプログラム的アクセスを可能にします。両方とも成功時に false を返します。
値の変更に反応するには、記述子に .on_change<&fn>() をチェーンします。コールバックは var_name() および型アクセス(as_int()、as_real()、as_str())を備えた sv::SysVarChange を受け取ります。
機能オブジェクトは静的ストレージ持続期間でなければなりません。MySQL はユーザーが変数を設定する際にストレージポインタに直接書き込みます。
完全な例
SQL からのアクセス
INSTALL EXTENSION my_ext 後、変数には拡張機能名をコンポーネントプレフィックスとしてアクセスできます:
拡張機能コードからの読み書き
INT および BOOL 変数については、グローバルストレージポインタを直接読み取ります — MySQL はそれらをアトミックに更新します。MySQL を介して変数を更新するには(ロック、範囲検証、永続化をサーバーが処理するため)、SYS_VARS.set(extension_name, var_name, scope, value) を呼び出します。set および get は成功時に false を返します。
scope 引数は永続化を制御します:
スレッドワーカー
thread worker 機能(vsql::preview::thread_worker)は、サーバーによって駆動されるバックグラウンドスレッドを拡張機能が実行できるようにします。スレッドは、サーバーが拡張機能ロード時に登録する制御システム変数を介して開始および停止されます。サーバーは、定期タイマー、ファイルディスクリプタの準備完了(レディ状態)、有効/無効イベントに応じて拡張機能の作業関数を呼び出します。
機能名 VEF_PREVIEW_THREAD_WORKER_NAME は "vsql::preview::thread_worker" です。
機能の宣言
ヘッダーを含め、ファイルスコープで作業関数をインスタンス化したThreadWorkerCapability を宣言し、.with() に渡します:
ThreadWorkerCapability<&my_work>)として渡されるため、以下のシグネチャを持つ関数でなければなりません。最初のコンストラクタ引数はスレッド名サフィックスです。オプションの2番目の引数は制御 sys var 名をオーバーライドします。
作業関数シグネチャ
reason はサーバーが関数を呼び出した理由を示します。thread はサーバー所有のハンドルです(最初の VEF_WAKEUP_ENABLE 呼び出し時は NULL — 以下参照)。arg は記述子に登録された不透明ポインタで、変更されずに渡されます。
Wakeup ライフサイクル
サーバーは4つの理由のいずれかで作業関数を呼び出します:
理由が
VEF_WAKEUP_ENABLE の場合、thread パラメータは NULL です。この時点でスレッドハンドルはまだ存在しないためです。他の3つの理由では thread は非 NULL です。
Wakeup 戻り値
vef_next_wakeup_t を返し、次回のワーカー起動設定を更新します。各フィールドのゼロ値は「現在の設定を維持」を意味します — 両方を変更しない場合は値初期化構造体を返します(return {};)。
新しい poll ファイルディスクリプタを設定するには、その値を返します(0より大きい必要があります)。既存の poll ファイルディスクリプタをクリアするには、poll_fd に -1 を返します。
理由が VEF_WAKEUP_DISABLE の場合、戻り値は無視されます。
スレッド名と制御変数
記述子の2つのフィールドが命名を制御します:suffix— スレッド名サフィックス。サーバーは拡張機能名を前置し、my_ext/monitorのようなスレッド名を生成します。var_name— オプション。NULL でない場合、サーバーはこの名前を制御システム変数として登録します。NULL の場合、サーバーはデフォルトパターン{suffix}_enabledを使用します。
SET GLOBAL {suffix}_enabled = ON、無効化するには OFF に設定します。
完全な例
単一の定期ワーカーを備えた最小限の拡張機能で、タイマー刻みごとにハートビートカウンターをインクリメントします。vsql_allow_preview_extensions = ON が設定されている場合)、サーバーは heartbeat_enabled システム変数を登録します。ワーカーを有効化するには:
SQL クエリ
sql_query 機能(vsql::preview::sql_query)は、バックグラウンドスレッドから SQL 文を実行できるようにします。クエリは機能の vtable を介してサーバー内部で実行され、拡張機能は MySQL クライアントライブラリをリンクしません。
機能名 VEF_PREVIEW_SQL_QUERY_NAME は "vsql::preview::sql_query" です。
機能の宣言
ヘッダーを含め、ファイルスコープでSqlQueryCapability を宣言し、.with() に渡します。通常、ThreadWorkerCapability と共に登録されます。セッションはワーカーのコールバックから開かれるためです:
g_sql.open(handle) は Session を返します。使用前に operator bool でチェックしてください。無効な Session は機能 vtable がバインドされていないか、サーバーがセッションを割り当てられなかったことを示します。Session はムーブオンリーで、破棄時に自動的に閉じられます。
クエリの実行
Session は session.sql(sv) で SqlQuery を生成します。クエリは2つのモードで実行できます:
execute()— 文を実行し、完全な結果セットをResultにバッファリングします。next()を呼び出して行をイテレートします。for_each(fn)— 文を実行し、行が生成されるたびにfnを1回呼び出します。バッファリングしません。返されるResultには診断情報のみ(行なし)が含まれます。
Result を返します。非 NULL の Result は文が成功したことを意味しません — has_error() を呼び出して確認してください。
バッファリング(execute):
column_str() は string_view を返します。これは次の next() 呼び出しまたは Result 破棄まで有効です。より長い寿命が必要な場合はコピーしてください。data() == nullptr の string_view は SQL NULL を示します。
ストリーミング(for_each):
Row はコールバックの実行中のみ有効です — 行間で参照を保持しないでください。for_each が返す Result はバッファリングされた行を持たず、next() はデータを返しません。has_error()、error()、warning_count()、warning(i) のみに使用してください。
診断
execute() および for_each() は返される Result を介して診断情報を返します。診断は1つの Diag です:
Result は以下を公開します:
error() は文が成功した場合、デフォルト構築された Diag(errno_ == 0)を返します。warning(i) は i >= warning_count() の場合、デフォルト構築された Diag を返します。
sqlstate および message のビューは Result が所有するストレージを指しており、Result が破棄されると無効になります — Result の生存期間を超えて保持する必要がある場合はコピーしてください。
完全な例
タイマー刻みごとに1つのバッファリングクエリと1つのストリーミングクエリを実行し、両方の診断をログ出力するワーカー:カラムストレージ
カラムストレージは、拡張機能が InnoDB に直接カスタム型のバイナリディスクレイアウトを登録できるようにします。これにより、VARBINARYペイロード経由で型のバイトをルーティングするのではなく、カスタム型のディスク形状を直接表現できます。例えば、専用ページに格納される必要のある圧縮浮動小数点配列など、VARBINARYが表現できないディスク形状が必要な場合に使用します。これは新しいストレージレイアウトを可能にする機能追加であり、既存のレイアウトのチューニングスイッチではありません。機能の宣言
2つのプレビュー機能が連携して動作します:vsql::preview::storage— InnoDB ストレージインフラストラクチャ(ミニトランザクション、セグメント、ページ)へのアクセスを提供します。ファイルスコープでStorageCapabilityを宣言します。vsql::preview::column_store— 拡張機能のカスタム型の1つに、1つのストレージ実装をバインドします。make_column_store<Ctx>(TYPE).…build()を使用してファイルスコープでColumnStoreCapabilityを宣言します。
make_extension() の .with() に渡す必要があります:
make_column_store<MyCtx>(MY_TYPE) は実装を同じ拡張機能で登録された1つのカスタム型に紐付けます。build() 時に7つのスロットが必要です。各スロットは InnoDB が通常動作中に到達するカラムライフサイクルの異なるポイントに対応します。
7つのストレージ関数
すべての関数はstorage::Column::StorageCtx<MyCtx>* を受け取ります。user() アクセサは拡張機能のカラムごとの状態を返し、arena() は補助オブジェクトのサーバー管理割り当てを提供します。すべての関数は成功時に false を返し、エラー時に true を返し、error_msg(容量 error_msg_len)にメッセージを書き込みます。
mark_delete と purge は区別されます。InnoDB MVCC では、削除された行は purge が実行されるまで古いスナップショットで読み取り可能でなければなりません。
カラムごとのコンテキストとアリーナ
C++ SDK はcreate または load を呼び出す前に MyCtx をデフォルト構築します — 関数が実行される時点で ctx->user() には既に値が設定されています。MyCtx はデフォルト構築可能でなければなりません。C++ SDK は引数なしで T() を呼び出します。
ctx->user() を直接使用して状態を初期化します。ctx->arena().construct<MyCtx>() を呼び出さないでください — これは不要なインスタンスを割り当てますが、ctx->user() はその領域を指していません。
load も同様のパターンです — ctx->user() には既に値が設定されており、storage_ref は create で ctx->set_ref() が格納したパックされた値を保持します:
ctx->arena() は MyCtx に直接埋め込むことができないほど大きいか動的な補助オブジェクトを割り当てる場合にのみ使用します。C++ SDK はアリーナを破棄し(~MyCtx() を呼び出し)、drop が成功するかどうかに関係なく、drop が返した後自動的に破棄します。
InnoDB アクセスユーティリティ
InnoDB プリミティブには<villagesql/preview/storage_api.h> を含めます。すべてのページ読み書きはミニトランザクション内で行われます:
create 時に予約されます — セグメントのセットアップパターンについては、上記の「カラムごとのコンテキスト」の create および load 例を参照してください。DML操作中、ルートページからセグメント参照を取得して新しいページを割り当てます:
mtr_ref を書き込み呼び出しに渡します:
ヘッダーまたはトレーラー領域内での読み取りまたは書き込みはページを破損させます — InnoDB はこれらのバイト範囲を自身の管理およびチェックサムに使用しています。
ステートメントイベント
statement event 機能(vsql::preview::statement_event)は、各クエリの実行完了後に拡張機能提供のハンドラを実行します。サーバーはハンドラをクエリ自身のスレッドで同期的に呼び出し、実行メタデータ — クエリテキスト、タイミング、行数、接続元の識別情報、オプティマイザ品質インジケータ — を渡します。スロークエリのログ記録、監査、メトリクス収集に使用します。
機能名 VEF_PREVIEW_STATEMENT_EVENT_NAME は "vsql::preview::statement_event" です。
機能の宣言
発火フェーズとハンドラ関数でインスタンス化したStatementEventCapability をファイルスコープで宣言し、.with() に渡します:
vef_statement_event_phase_t 値です。VEF_STATEMENT_EVENT_POSTEXECUTE はクエリの実行完了後に、成功または失敗にかかわらず発火し、このバージョンで実装されている唯一のフェーズです。その他の vef_statement_event_phase_t 値は予約されており、そのいずれかに対してハンドラを宣言すると、サーバーは INSTALL EXTENSION を拒否します。
ハンドラ引数
StatementEventArgs は完了したクエリの読み取り専用ビューです。POSTEXECUTE フェーズではすべてのフィールドに値が設定されています。主なアクセサ:
query() は存在する場合サーバーの書き換え形式を返すため、認証情報を含む文はシークレットが平文ではなく難読化された状態で到着し、一般ログ、スローログ、バイナリログが既にそれらを難読化(伏字化)する方法と一致します:SET PASSWORD、CREATE/ALTER USER ... IDENTIFIED BY、CHANGE REPLICATION SOURCE ... SOURCE_PASSWORD、CREATE SERVER ... OPTIONS(PASSWORD ...)。書き換えルールのない文はそのまま配信されます。
query()、sqlstate()、error_message() などの文字列アクセサは、ハンドラ呼び出しの実行中のみ有効なストレージを指しています — ハンドラが返った後にそれらが必要な場合はバイトをコピーしてください。
StatementEventResult::error_msg(fmt, ...) は printf 形式のメッセージを書き込みます。POSTEXECUTE フェーズでは、メッセージは参考情報(アドバイザリ)であり、サーバーはログに記録しますが、クライアントには伝播しません。
完全な例
サーバーに同梱されるvsql_slow_query_log テスト拡張機能の簡略化された形式です。実行時間がしきい値を超える各クエリをログに記録し、statement event 機能をシステム変数と組み合わせて実行時設定を行います:

