villagesql クレート API のリファレンスです。 入門チュートリアルについては、Rust で拡張機能を作成する を参照してください。 カスタム型については、Rust のカスタム型 を参照してください。
InValue
InValue は、サーバーが各関数の引数に対して渡す列挙型です。 関数は args: &[InValue] を受け取り、その値を使用する前に各引数をチェックする必要があります。
常に
Null を明示的にパターンマッチングしてください。 .unwrap() を呼び出すか、値のバリアントのみをパターンマッチングすると、バグになります。 SQL NULL はエラーではなく、通常の入力です。
VdfReturn
VdfReturn は、関数がサーバーに返す値です。 いずれかの関連関数を使用して構築します。
警告とエラー:
warning は、残りの結果セットで処理を続けることが理にかなう、ユーザー入力の検証エラーに使用します。 警告はステートメントを失敗させません。厳密モードの INSERT および UPDATE でも同様です。 error は、処理を続行することが安全でない場合に使用します。たとえば、保存されたデータが破損している場合や、内部の不変条件に違反している場合です。 致命的なエラーは、ステートメント全体を中止します。
extension! マクロ
extension! は、サーバーが VEB ファイルをロードするときに呼び出す VEF エントリポイントを生成します。 これは、クレート内に正確に 1 つ存在する必要があります。
types: と requires: はそれぞれ単独でオプションですが、funcs: は常に存在する必要があります。型のみの拡張機能では funcs: [] と記述してください。 純粋な関数拡張機能では types: を省略します。 funcs: [] を持ち型を持たない extension! ブロックは有効ですが、何も行わない拡張機能が生成されます。
requires: は、拡張機能が使用する Rustにおけるプレビュー機能 を、static な機能オブジェクトへの参照として宣言します。 これは最後に、funcs: セクションの後に記述する必要があります。拡張機能が関数を登録しない場合は funcs: [] を含めてください。
func! マクロ
func! は、SQL で呼び出すことができる関数を宣言します。 8 つの形式があります。ステートメントごとの状態を持たない 4 つの形式 (パラメータなし、buffer_size のみ、deterministic のみ、両方)、prerun 関数を通じてステートメントごとの状態を付加する 2 つの形式、そしてそれらにオプションの postrun: を加えた 2 つの形式です。以下のステートメントごとの状態を参照してください。
func! で使用する 型定数:
ステートメントごとの状態
一部の関数には、単一のステートメントのすべての行にまたがる状態 (呼び出しカウンター、アキュムレーターなど) が必要です。 状態の型をstate: で宣言し、セットアップ関数を prerun: で宣言します。 prerun 関数は最初の行の前に 1 回実行され、その後、行関数がその状態への &mut アクセスを伴って行ごとに 1 回実行されます。
prerun 関数のシグネチャは fn(PrerunArgs, PrerunResult<T>) であり、それが状態を渡す行関数は、状態を最初に受け取ります: fn(state: &mut T, args: &[InValue]) -> VdfReturn。 T は state: で指定された型であり、コンパイラーは prerun 関数と行関数がその型について一致していることをチェックします。
PrerunArgs::len() は各行が受け取る引数の数であり、PrerunArgs::is_empty() は関数が引数なしで呼び出された場合に true になります。
状態を自分で解放してはいけません。 func! は、ステートメントが終了したときに状態を破棄する postrun を常に生成するため、独自の後処理を指定した場合でも、状態の解放はあなたの責任ではありません。 この破棄のステップは、postrun が delete_state<T>() を呼び出す必要がある C++ SDK とは逆です。ステートメントごとの状態 を参照してください。
独自の後処理を先に実行するには、postrun: postrun_fn (fn(&mut StateType)) を指定します。これは最後の行の後、状態がまだ借用可能なうちに、SDK 自身の破棄の前に 1 回実行されます。Rust SDK リポジトリの examples/vsql_postrun_order/src/lib.rs を参照してください。記録されたテスト出力には prerun,postrun,drop|rows_seen=3 という行が含まれており、この順序を裏付けています。
ステートメント内での自身の呼び出しインデックスを返す関数を持つ、完全な拡張機能:
call_index() は 3 回実行され、1、2、3 を順に返します。行ごとに 1 つの値です。 SUM はこれら 3 つの値を加算し、6 になります。
2 番目の SELECT は、より大きな値ではなく、最初と同じ合計を返します。カウンターは 1 つのステートメントに対して割り当てられ、それが終了したときに破棄されるためです。
agg_func! マクロ
agg_func! は集約 SQL 関数を宣言します。SUM/COUNT のように、行ごとに 1 回ではなく、各グループの行全体に対して呼び出される関数です。2 つの形式があります。
アキュムレーターはステートメントごとに 1 回割り当てられ、ステートメントの終了時に破棄されます。
agg_func! は、それを作成する prerun と破棄する postrun の両方を生成するため、どちらも自分で書く必要はありません。グループごとの動作を実現するのが clear_fn です。GROUP BY では同じアキュムレーターがグループ間で再利用されるため、グループ間で漏れてはならないフィールドはここでリセットする必要があります。
完全な SUM 相当の集約関数 — SDK リポジトリの vsql_agg_sum の例:
accumulate が InValue::Int のみをマッチさせることで NULL がスキップされ、組み込みの SUM と一致します。seen フラグにより、すべて NULL のグループと空のグループは 0 ではなく NULL を返します。
varargs_func! マクロ
varargs_func! は、任意の数、任意の型の引数を受け入れる VDF を宣言します。パラメータリストは [..] と記述します。これは必須のリテラルであり、引数なしの func! で使用する [] とは異なります。
8 つの形式があります。3 つの形があり、それぞれに省略形と、buffer_size と deterministic を(単独ではなく必ず一緒に)追加する完全形があります。state:/prerun: の形には、さらにオプションの postrun: を追加する 2 つの形式があります。意味は func! と同じです。
ベア形式には検証がなく、引数ゼロの呼び出しも受け入れます。あらゆる入力に対して定義される関数であれば正当な選択ですが、行関数だけで、渡され得るすべての入力に対処しなければならないことを意味します。ステートメントごとの状態を割り当てて破棄するのは
state: 形式のみです。prerun のみの形式は PrerunResult<()> を使用して何も保存しないため、postrun は存在しません。そのような prerun は PrerunResult を error と request_buffer_size のためだけに使用し、set_state は決して呼び出しません。
prerun での引数型の検査
サーバーは何も検証しないため、可変長引数の prerun は最初の行が実行される前に引数の型を確認する必要があります。PrerunArgs::type_at がそのビューを提供します。あわせて、len()/is_empty() と、ステートメントごとの状態で説明されている PrerunResult のメソッドも利用できます。
is_custom() と custom_name() を組み合わせることで、特定の 1 つのカスタム型だけを受け入れられます。is_custom() だけでは、サーバー内のすべてのカスタム型を受け入れてしまいます。
SDK リポジトリの vsql_varargs の例は、形式ごとに 1 つの関数を宣言しています。prerun で検証し、ステートメントごとの呼び出しカウンターを持つ、状態付きの可変長引数関数:
str_join は行関数内で InValue をマッチさせます。prerun が見るのは宣言された型であって値ではなく、STRING 列はどの行でも NULL を保持し得るためです。
describe(引数ゼロの呼び出しと非スカラー引数を拒否し、異種の引数リストを整形する prerun のみの関数)と point_path(is_custom() と custom_name() で検証する関数)も宣言しています。完全なソースは Rust SDK リポジトリの examples/vsql_varargs/src/lib.rs を参照してください。
custom_type! マクロ
custom_type! は、新しい列型を登録します。 type_name、persisted_length、max_decode_buffer_length、encode、decode、および compare が必要です。 hash はオプションですが、推奨されます。 default と intrinsic_default_fn はどちらか一方を指定し、両方は指定しないでください。
default フィールドは、列のデフォルト値ではありません。省略された列は NULL になります。 これは、サーバーが型を初期化するときにエンコードする文字列を提供します。その初期化は、拡張機能のインストール時ではなく、ステートメントが初めてその型を名指ししたときに行われます。 default と intrinsic_default_fn のどちらも指定しない場合、サーバーは代わりに空文字列をエンコードします。 いずれの場合も、エンコードが Err を返すと、そのステートメントは失敗し、型は使用できないままになります。
default と intrinsic_default_fn の両方を指定した場合は、拡張機能のインストール時に拒否されます。初回使用時まで先送りされることはありません。
custom! マクロ
villagesql::custom!("type_name") は、func! 宣言でカスタム型を名前によって参照します。
villagesql::Type::* がパラメータリストまたは戻り値の型の位置に現れる場所であれば、どこでも使用できます。 文字列は、対応する custom_type! で宣言された type_name と一致する必要があります。
manifest.json フィールド
すべての拡張機能には、Cargo.toml の横に manifest.json が必要です。
name の検証ルール: 英字で始まり、英字または数字で終わり、最大 64 文字。 マニフェストが無効な場合、INSTALL EXTENSION は失敗します。
