API がこのような形になっている理由が気になりますか?型付き引数/結果 API や
prerun()、可変長引数などの低レベルフックの背後にある設計思想については、
Happy Path, Escape Hatch,
and the Space Between を参照してください。VDF 関数コントラクト
これらのコントラクトは、VDF 実装関数が VEF ランタイムとどのように連携するかを規定します。make_func<> を使用して登録されたすべての関数は、これらに従う必要があります。以下に参照されている型は、#include <villagesql/vsql.h> を介して利用できます。
1. VDF 実装関数は void 型であり、値を返しません。
out.set(...) / out.set_length(n)、out.set_null()、out.warning(msg)、または out.error(msg)。
2. input.value() を呼び出す前に、input.is_null() を確認します。
is_null() が true を返す場合、value() を呼び出すと未定義の動作になります。
out.buffer() に書き込み、out.set_length(n) を呼び出します。書き込む前に、out.buffer().size() を確認します。
out.buffer()は、サーバーが管理するバッファーに対するSpan<char>を返します。out.set_length(n)は、書き込まれたバイト数を記録します。out.buffer().size()は、最大容量です。書き込む前に必ず確認してください。
out.error(msg) に渡します。メッセージは、必要に応じて VEF_MAX_ERROR_LEN (512 バイト) に切り捨てられます。
out.error(msg) は std::string_view を受け入れます。1 回の呼び出しで、メッセージをサーバーが管理するバッファーにコピーし、結果の状態をエラーに設定します。
関数の実装
実装関数は、型付きの引数と結果型を使用します。NULL 値の処理
is_null() を使用して NULL をチェックし、set_null() を呼び出して NULL を返します。
NULL 値の処理オプション:
- 入力 NULL チェック:
input.is_null() - NULL 値を返す:
out.set_null() - 戻り値:
out.set(v)(数値/カスタム) または、文字列の場合、out.buffer()に書き込んだ後にout.set_length(n) - 警告を返す:
out.warning(msg)— この行に対して NULL を返し、SQL 警告を追加し、実行を継続します。厳密モードでは、MySQL は INSERT/UPDATE でこれをエラーに昇格させます。out.set()の代わりとして呼び出し、併用(同時呼び出し)はしないでください。 - エラーを返す:
out.error(msg)— ステートメントの実行を中止します。
エラー処理
検証の失敗または無効な入力に対して、カスタムメッセージを使用してエラーを返します。プリラン/ポストランによるステートメントごとの状態
フックは.prerun<>() および .postrun<>() を使用して登録します。必要なシグネチャは次のとおりです。
PrerunArgs および PostrunArgs メソッドの詳細については、Development ガイドの
ステートメントごとの状態
を参照してください。
ほとんどの拡張機能では、プリラン/ポストラン フックは必要ありません。 C++ SDK は、
型チェックや結果バッファーのサイズ設定など、一般的なケースを自動的に処理します。
STRING を返す VDF と CUSTOM を返す VDF の両方について、VDF 本体が実行される前に、
結果バッファーは解決された戻り値の型に合わせて拡張されます。プリラン/ポストランは、
行ごとに発生するべきではない、コストの高いステートメントごとのセットアップ (接続のオープンなど)
が必要な場合にのみ使用してください。プリラン/ポストランをユースケースで使用する必要がある場合は、
VillageSQL Discord でシナリオを共有してください。
チームは、C++ SDK サポートを追加して、これを自動的に処理できるようにする場合があります。
集計関数
組み込みの集計関数 COUNT(DISTINCT)、MIN、MAX、および GROUP_CONCAT は、カスタム型でもすぐに使用できます。MIN および MAX には、型に登録された比較関数が必要です。 カスタム集計 VDF もサポートされています。make_aggregate_func<State, &result_fn>("name") を使用して登録し、.returns()、.param()、.clear<>()、および .accumulate<>() をチェーンしてから、.build() を呼び出します。.clear<>() と .accumulate<>() の両方が必要です。ビルダー API とコールバックのシグネチャについては、集計 VDF を参照してください。
カスタム型を使用した組み込みの集計操作:
- 各関数呼び出しは、独自の結果バッファー (スレッドセーフ) を持つ 1 行を処理します。
prerun/postrunは、ステートメントごとのセットアップ/ティアダウンを提供します。- グローバル状態を避けてください - 関数パラメーターと戻り値を使用します。
- グローバル状態を使用する必要がある場合は、ミューテックス/ロックで保護します。
ウィンドウ関数
次のウィンドウ関数は、カスタム型で動作します。一時テーブル
カスタム型は、一時テーブルで動作します。CREATE TEMPORARY TABLE、INSERT、および ALTER TABLE は、永続テーブルと同じように動作します。
プレビュー API
一部の VEF 機能は、C++ SDK インクルードツリーのvillagesql/preview/ の下にあるオプトインヘッダーとして利用できます。ABI と API は現在も活発に開発が進められており、予告なく変更される可能性があります。
オプトインするには、拡張機能のソースにインクルードを追加します。たとえば、次のとおりです。
<villagesql/vsql.h> によって取り込まれません。オプトインする場合は、これを直接インクルードする必要があります。
vsql::preview の下の名前空間レイアウトは、機能ごとです。単一の普遍的なパターンはありません。キーリング API は vsql::preview_keyring::KeyringCapability を使用します。スレッドワーカー API は vsql::preview_thread_worker::ThreadWorkerCapability を使用します。SQL クエリ API は vsql::preview_sql_query::SqlQueryCapability を使用し、バックグラウンドワーカー スレッドハンドル (vef_thread_handle_t *) からオープン(開始)する必要があります。各ヘッダーを確認して、定義されている正確な名前空間とクラス名を確認してください。
完全なプレビュー API ドキュメントについては、プレビュー機能 を参照してください。
トリガー
トリガーは、カスタム型の列を持つテーブルで発動します。トリガー本体は、NEW および OLD からのカスタム型以外の列を参照できます。トリガー本体内でカスタム型の列の値にアクセスすることは、まだサポートされていません。

