概要
VillageSQLの拡張フレームワーク(VEF)を使用すると、データベースサーバーにカスタム機能を追加できます。このガイドでは、C++ SDKと拡張テンプレートを使用して、C++で拡張機能を構築する手順を説明します。 VDFの実装の詳細(引数と結果の型、集約、システム変数、パラメータ化された型)については、開発ガイドを参照してください。Rustを使用する場合は、Rustでの拡張機能の作成を参照してください。
VillageSQL拡張機能とは?
VillageSQL拡張機能は、VEBファイル(VillageSQL拡張バンドル)としてパッケージ化され、次のものが含まれます。- マニフェスト - 拡張機能に関するメタデータ(名前、バージョン、説明)
- 共有ライブラリ - 機能の実装であるコンパイルされたC++コード
- オプションのメタデータ - 追加のリソースまたは構成
- 型と関数を定義するためのC++ API
- SQLスクリプトなしでの自動登録
- 型セーフな引数と結果の型
- 拡張機能の定義のためのビルダーパターン
VDFと従来のUDF: VEFを通じて登録された関数は、VDF(VillageSQL定義関数)と呼ばれます。VillageSQLは、
CREATE FUNCTION ... SONAMEを通じて登録された従来のMySQL UDFもサポートしていますが、新しい拡張機能にはVDFをお勧めします。SQLでのVDFの呼び出し
VDFは、拡張機能プレフィックスの有無にかかわらず呼び出すことができます。- システム関数(組み込みのMySQL関数(
NOW()、CONCAT()など)) - UDF(従来のMySQLユーザー定義関数)
- VDF(拡張機能の関数)- 同じ名前の関数が1つだけ存在する場合
- ストアド関数(
CREATE FUNCTIONで作成)
- 複数の拡張機能が同じ名前の関数を提供する場合、
extension.function_nameを使用します。 - 曖昧さがない場合は、コードをシンプルにするために非修飾名を使用します。
- その関数名を提供する拡張機能が1つだけの場合、修飾名は必要ありません。
- カスタム関数(VDF) - 自動型チェックと検証を備えたSQL関数
- カスタムデータ型 -
ORDER BYおよびインデックスで機能するCOMPLEX、UUID、またはVECTORなどの新しい列タイプ - 型操作 - カスタム型のエンコード、デコード、比較、およびハッシュ関数
前提条件
開始する前に、VillageSQLをソースからビルドします。拡張機能は、サーバーのSDKヘッダーとビルドツリーに対してリンクされます。最初にソースからのビルドガイドに従ってください。 また、次のものも必要です。- Git - クローニングとバージョン管理用
- CMake 3.18以降 - ビルドシステム
- C++コンパイラ - GCC 8+、Clang 8+、またはC++17サポートを備えたMSVC 2019+
- 基本的なC++の知識 - C++と関数ポインタの理解
ステップ1:拡張テンプレートを取得する
拡張テンプレートを次の2つの方法で開始できます。オプションA:VillageSQLソースからテンプレートを使用する
VillageSQLソースコードがある場合は、テンプレートが含まれています。オプションB:GitHubからフォークする
VillageSQL拡張テンプレートリポジトリをフォークすることから始めます。-
GitHubのテンプレートリポジトリにアクセスします。
- **「フォーク」**ボタンをクリックして、独自のコピーを作成します。
-
ローカルにフォークをクローンします。
ステップ2:マニフェストを更新する
manifest.jsonを編集して、拡張機能のメタデータを定義します。
$schemaフィールドはオプションですが、すべてのマニフェストフィールドのIDEのオートコンプリートとインライン検証を有効にします。
manifest.jsonスキーマ
検証ルール:
name: 文字で始まり、文字または数字で終わる必要があります。小文字、数字、アンダースコア、ハイフンを含めることができます。最大64文字。アンダースコアを使用します - ハイフンはSQLでバッククォートで囲む必要があります。version: セマンティックバージョンに従う必要があります(例:1.0.0、0.2.1)- 無効なマニフェストは、
INSTALL EXTENSIONの失敗を引き起こします。
ステップ3:C++ SDKを使用して拡張機能を実装する
C++ SDKは、フルーエントなビルダーパターンを使用して拡張機能を定義するためのC++ APIを提供します。- コンパイル時のチェックを備えた型セーフな関数定義
- 引数の自動検証と型変換
- 比較/ハッシュ関数を備えたカスタム型のサポート(
ORDER BYおよびインデックスを有効にします)
VillageSQLヘッダーを含める
メインの拡張ファイル(例:src/extension.cc)を作成し、C++ SDKヘッダーを含めます。
<villagesql/vsql.h>ヘッダーは、型ビルダー、関数ビルダー、および拡張ビルダーをプルインし、一般的に使用されるシンボルをvsql名前空間に再エクスポートします。
拡張機能を定義する
VEF_GENERATE_ENTRY_POINTS()マクロを使用して、拡張機能を定義します。
make_func<&impl>("name")- 実装ポインタを持つ関数を作成します。.returns(type)- 戻り値の型を設定します(STRING、INT、REAL、またはカスタム型名)。.param(type)- パラメータを追加します(最大8つのパラメータ)。.buffer_size(size_t)-STRING/CUSTOM戻りの特定の出力バッファサイズを要求します。.max_result_length(size_t)-STRING戻りの結果列のサイズを設定し、マテリアライズされた結果が引数の幅で切り捨てられないようにします。VEF_MAX_RESULT_LENGTH(16 MiB)を超える値は、サーバーによって上限が設定されます。STRINGのみ。最初に.returns(STRING)を呼び出します。プロトコル4(開発ABI)が必要です。.deterministic(bool = true)- この関数は常に同じ入力に対して同じ出力を返し、副作用がないことを宣言します。デフォルトは非決定性です。.prerun<func>()- ステートメントごとのセットアップ関数を設定します(オプション)。.postrun<func>()- ステートメントごとのクリーンアップ関数を設定します(オプション)。.build()- 関数の登録を完了します。
パラメータ制限: 関数は最大8つのパラメータ(
kMaxParamsで定義)をサポートします。それ以上のパラメータが必要な場合は、構造化型または複数の関数を検討してください。カスタム型引数と戻り値を持つVDF
VDFは、.param(TYPE_NAME)および.returns(TYPE_NAME)をビルダーで使用して、カスタム型の値を受け取り、返すことができます。実装では、入力にCustomArg、出力にCustomResultを使用します。これは、型操作で使用されるのと同じ引数と結果の型です。
.param(COMPLEX)および.returns(COMPLEX)で登録します。
CustomArg/CustomResultAPIについては、開発ガイドを参照してください。これには、パラメータ化された型用のCustomArgWith<P>およびCustomResultWith<P>が含まれます。
決定性関数
デフォルトでは、VDFは非決定性として登録されます。非決定性関数は、次の3つのSQLコンテキストでブロックされます。生成された列、CHECK制約、および式デフォルト値(列のDEFAULT (expr))。これらの機能のいずれかを使用すると、非決定性VDFがエラーを返します。関数が常に同じ入力に対して同じ出力を生成し、副作用がない場合は、ビルダーチェーンに.deterministic()を追加して、決定性として宣言できます。
オプティマイザは、この情報を使用して、関数を1つのステートメントに対して1回評価し、行ごとに呼び出すのではなく、行間で値を再利用する場合があります。非決定性関数を誤って決定性としてマークすると、サーバーが異なる出力を生成する必要がある入力に対して同じ結果を返す可能性があります。関数が外部状態、ランダム性、または時間に依存しない場合にのみ、.deterministic()を追加してください。
ビルダーのシグネチャ: .deterministic(bool d = true) - 引数なしの形式は、デフォルトでtrueになります。
例:
complex_addは決定性として宣言されているため、生成された列の定義で使用できます。
カスタムバッファサイズ
可変長のデータを返す関数の場合は、特定のバッファサイズを要求します。buffer()とset_length()を使用して値を自分で構築する場合、バッファはbuffer().size()バイトに固定されます。それを超えて書き込むとメモリオーバーフローが発生するため、超過しないようにガードしてください。
STRING結果の場合、out.set(sv)はsnprintfスタイルのオーバーフロー契約に従います。収まる分だけバイトをコピーし、set_lengthを介して値の完全なサイズを報告します。報告されたサイズがバッファを超えると、サーバーは結果バッファを拡張して関数を再呼び出しするため、要求されたバッファより大きいSTRING値は切り捨てられなくなります。
その契約は行の評価時に適用されます。マテリアライズされたSTRING結果(GROUP BY/DISTINCTの一時テーブル、CREATE TABLE ... SELECT、またはUNION内)は、関数が.max_result_length(n)を宣言しない限り、引数の幅で切り捨てられます。これは結果列のサイズを設定します(文字数単位で、VEF_MAX_RESULT_LENGTH(16 MiB)が上限です)。
関数の最大出力サイズに基づいて、
.buffer_size()を使用して十分なバッファサイズを要求します。バッファサイズを正しく設定すると、バッファの拡張と再実行のラウンドトリップのコストを回避できます。関数を実装する前に、C++ APIリファレンスを確認して、完全なVDF契約を確認してください。これには、nullチェック、結果の型、バッファのサイズ設定、およびエラー処理が含まれます。
ステップ4:カスタム型を作成する
カスタム型を使用すると、ORDER BY、インデックス、および集約関数で機能するCOMPLEX、UUID、またはVECTORなどの新しい列タイプを定義できます。拡張機能にのみ関数を登録する場合は、ステップ5に進みます。
完全な実装のウォークスルーについては、C++でのカスタム型を参照してください。型にパラメータがある場合(例:VECTOR(1536))、パラメータ化された型を参照してください。
ステップ5:ビルド構成を更新する
CMakeLists.txtを編集して、拡張機能をVEBファイルとしてビルドします。
VillageSQLExtensionFrameworkは、拡張機能をビルドするためのCMakeヘルパーを提供します。VEF_CREATE_VEB()は、ライブラリ、マニフェスト、およびメタデータを.vebアーカイブにパッケージ化します。- フレームワークは、MySQL/VillageSQLビルドフラグを自動的に検出します。
- ライブラリターゲット名は通常
extensionです(任意の名前を使用できます)。 - VEB名は、
manifest.jsonの名前と一致する必要があります。 - デフォルトでは、拡張機能は安定したABIヘッダーに対してビルドされます。不安定な開発ヘッダーに対してビルドするには、
-DVSQL_USE_DEV_ABI=ONを設定します。
ステップ6:ビルドディレクトリを作成する
別のビルドディレクトリを作成します。ステップ7:CMakeとMakeでビルドする
拡張機能を構成してビルドします。- コンパイルされた共有ライブラリ(
.soファイル) - VEBパッケージ(
.vebファイル)- マニフェストとライブラリを含むtarアーカイブ
ビルドを確認する
VEBファイルの内容を確認します。ステップ8:インストールしてテストする
オプションA:VillageSQL拡張ディレクトリにインストールする
インストールターゲットを使用して、VEBをVillageSQLインストールにコピーします。.vebファイルが、VillageSQL_VEB_INSTALL_DIRで構成されたディレクトリにコピーされます。
オプションB:手動インストール
VEBファイルを手動でコピーします。拡張機能をテストする
-
VillageSQLに接続します。
-
拡張機能をインストールします。
-
インストールを確認します。
-
関数をテストします。
テストの作成
拡張機能が正しく機能することを確認するために、テストファイルを追加します。-
mysql-test/t/にテストファイルを作成します。 -
期待される結果を生成します。
-
テストを実行します。
トラブルシューティング
拡張機能がロードされない
エラーログを確認し、VEBの内容を確認します。関数が見つからない
インストールと登録を確認します。ビルドエラー
拡張機能の例
既存のVillageSQL拡張機能から学習します。vsql_complex
複素数データ型の実装
vsql_extension_template
拡張機能を作成するための最小限のテンプレート
次のステップ
拡張機能の使用
拡張機能をインストールおよび管理する方法を学びます。
開発ガイド
引数と結果の型、集約、システム変数、およびテスト
拡張機能のアーキテクチャ
ライフサイクル、キャッシュ、パフォーマンス、およびセキュリティモデル
ソースからのビルド
VillageSQLをソースコードからビルドします。

