拡張性

PostgreSQL 9.1.1文書
前のページ | 巻戻し | 第 54章GINインデックス | 早送り | 次のページ

# 54.2. 拡張性

GINインタフェースは高度に抽象化されています。 アクセスメソッド実装者に要求されることは、アクセスするデータ型の意味を実装することだけです。 GIN層自体が同時実行性、ログ処理、ツリー構造の検索処理に関する注意を行います。

GINアクセスメソッドを動作させるために取ることは、4つ（または5つ）のユーザ定義関数を実装することだけです。 これは、ツリー内のキーの動作とキーとインデックス付けされる項目、インデックス可能な問い合わせ間の関係を定義します。 すなわち、GINは、一般化、コード再利用、整理されたインタフェースによる拡張性を組み合わせます。

GIN用の演算子クラスが提供しなければならない4つのメソッドを示します。

`int compare(Datum a, Datum b)`

  キー（インデックス付けされる項目ではありません）を比較し、0より小さい、0、または0より大きい整数を返します。 それぞれ、最初のキーが2番目のキーより、小さい、等しい、または大きいことを示します。 NULLキーがこの関数に渡されることはありません。

`Datum *extractValue(Datum itemValue, int32 *nkeys, bool **nullFlags)`

  インデックス対象値に与えられる、pallocで割り当てられたキーの配列を返します。 返されるキーの数は`*nkeys`に格納しなければなりません。 キーのいずれかがNULLになるかもしれない場合、`*nkeys`論理値配列をpallocで割り当てそのアドレスを`*nullFlags`に格納し、必要に応じてNULLフラグを設定してください。 すべてのキーが非NULLであれば、`*nullFlags`をNULL（初期値）のままにすることができます。 項目がキーを含まない場合、戻り値はNULLになるかもしれません。

`Datum *extractQuery(Datum query, int32 *nkeys, StrategyNumber n, bool **pmatch, Pointer **extra_data, bool **nullFlags, int32 *searchMode)`

  問い合わせ対象の値に与えられる、pallocで割り当てられたキーの配列を返します。 つまり、`query`はインデックス可能な演算子の右辺の値です。 この左辺はインデックス対象の列です。 `n`は演算子クラス内の演算子の戦略番号です（項35.14.2を参照）。 `extractQuery`はしばしば、`query`のデータ型とキー値を抽出するために使用しなければならないメソッドを決定するために、`n`を調べなければなりません。 返されるキーの数を`*nkeys`に格納しなければなりません。 キーのいずれかがNULLとなる可能性がある場合はまた、`*nkeys`個の論理値の配列をpallocで割り当て、`*nullFlags`にそのアドレスを格納し、必要に応じてNULLフラグを設定してください。 すべてのキーが非NULLならば`*nullFlags`はヌル（初期値）のままにしておくことができます。 `query`がキーを含まない場合、戻り値をNULLにすることができます。

  `searchMode`は出力引数です。 これにより`extractQuery`は検索がどのように行われるかの詳細を指定することができます。 `*searchMode`が`GIN_SEARCH_MODE_DEFAULT`（呼び出し前にこの値に初期化されます。）に設定された場合、返されるキーの少なくとも１つに一致する項目が合致候補とみなされます。 `*searchMode`が`GIN_SEARCH_MODE_INCLUDE_EMPTY`に設定された場合、少なくとも１つの一致するキーを含む項目に加え、キーをまったく含まない項目が合致候補とみなされます。 （このモードは例えば何のサブセットかを求める演算子を実装する際に有用です。） `*searchMode`が`GIN_SEARCH_MODE_ALL`に設定された場合、返されるキーのいずれかに一致するかどうかは関係なく、インデックス内の非NULLの項目すべてが合致候とみなされます。 （このモードは、基本的にインデックス全体のスキャン処理が必要ですので、他の２つの選択肢と比べてかなり低速になります。 しかし境界条件を正確に実装するためにこれが必要になるかもしれません。 おそらく、このモードを必要とする演算子はほとんどの場合、GIN演算子クラス向けに優れた候補ではありません。） このモードを設定するために使用する記号は`access/gin.h`で定義されています。

  `pmatch`は部分一致が提供されている場合に使用する出力引数です。 使用するには、`extractQuery`が`*nkeys`論理値の配列を割り当て、そのアドレスを`*pmatch`に格納しなければなりません。 関連するキーが部分一致を必要とするとき、それぞれの配列要素は真に、そうでなければ偽に設定されなければなりません。 `*pmatch`がNULLに設定されている場合、GINは部分一致が必要ないと想定します。 呼び出し前に変数はNULLに初期化されますので、この引数は部分一致が提供されていない演算子クラスでは、単に無視できます。

  `extra_data`は、`extractQuery`が`consistent`と`comparePartial`メソッドに追加データを渡すことができるようにする出力引数です。 使用するには、`extractQuery`が`*nkeys`ポインタの配列を割り当て、そのアドレスを`*extra_data`に格納し、そして望まれるものは何でも個別のポインタに格納しなければなりません。 変数は呼び出し前にNULLに初期化されますので、追加データを必要としない演算子クラスでこの引数は単に無視できます。 もし`*extra_data`が設定されれば、配列全部が`consistent`メソッドに、適切な要素が`comparePartial`メソッドに渡されます。

`bool consistent(bool check[], StrategyNumber n, Datum query, int32 nkeys, Pointer extra_data[], bool *recheck, Datum queryKeys[], bool nullFlags[])`

  インデックス付けられた項目が戦略番号`n`を持つ問い合わせ演算子を満たす（または、recheck印が返されたときはたぶん満たすかもしれない）場合に真を返します。 GINは項目を明示的に格納しませんので、この関数はインデックス付けされた項目の値に直接アクセスすることができません。 どちらかというと、この問い合わせから取り出される指定された問い合わせで現れるキー値に関する知識が利用できるものです。 `check`配列は長さ`nkeys`であり、この`query`データに対して事前に行われた`extractQuery`が返したキーの数と同じです。 インデックス対象の項目が対応する問い合わせキーを持つ場合、`check`配列の各要素は真です。 つまり、(check[i] == TRUE)の場合、`extractQuery`の結果配列のi番目のキーがインデックス対象項目内に存在します。 元の`query`データは、`consistent`メソッドがそれを調査する必要がある場合に、渡されます。 このため`queryKeys[]`および`nullFlags[]`は事前に`extractQuery`によって返されます。 `extra_data`は`extractQuery`により返された追加データ配列で、ない場合はNULLです。

  `extractQuery`が`queryKeys[]`内でNULLキーを返す時、インデックス対象項目がNULLキーを含む場合は対応する`check[]`要素は真です、 つまり、`check[]`の意味は`IS NOT DISTINCT FROM`のようなものです。 `consistent`関数は、通常の値の合致とNULL合致との違いを通知する必要がある場合、対応する`nullFlags[]`要素を検査することができます。

  成功の場合、`*recheck`はヒープタプルが問い合わせ演算子に対し再検査を必要とすれば真で、インデックス検査が的確であれば偽です。 つまり、FALSEという戻り値はヒープタプルが問い合わせに合わないことを保証し、`*recheck`が付いたTRUEという戻り値はヒープタプルが問い合わせに一致する可能性があるため、それを取り出し、元のインデックス付けされた項目を直接問い合わせ演算子で評価することで再検査する必要があることを意味します。

省略可能ですが、GINに対する演算子クラスは第5のメソッドを提供します。

`int comparePartial(Datum partial_key, Datum key, StrategyNumber n, Pointer extra_data)`

  問い合わせキーとインデックスキーの部分一致を比較します。 符号が結果を示す整数が返ります。 ゼロ未満はインデックスキーは問い合わせに一致しないが、インデックススキャンを続けるべきであることを示します。 ゼロはインデックスキーが問い合わせに一致することを示します。 ゼロより大きな値はこれ以上の一致はありえないためインデックススキャンを停止すべきであることを示します。 スキャンをいつ停止するかを決めるためにセマンテックスが必要とされる場合、部分一致問い合わせを生成した演算子の戦略番号`n`が提供されます。 また`extra_data`は`extractQuery`で作成される追加データ配列の対応する要素、もしなければNULLです。 NULLキーがこの関数に渡されることはありません。

"部分一致"問い合わせをサポートするためには、演算子クラスは`comparePartial`メソッドを提供しなければなりません。 またその`extractQuery`は、部分一致問い合わせであった時に`pmatch`パラメータを設定しなければなりません。 詳細については項54.3.2を参照してください。

上記の各種`Datum`値の実データ型は、演算子クラスに依存して変動します。 `extractValue`に渡される項目値は常に演算子クラスの入力型であり、キー値はすべてそのクラスの`STORAGE`型でなければなりません。 `extractQuery`および`consistent`に渡される`query`引数は、戦略番号によって識別されるクラスのメンバ演算子の右辺入力型として指定されたものになります。 正しい型のキー値がそこから抽出できる限り、これは項目の型と同じである必要はありません。

前のページ | ホーム | 次のページ
はじめに | 上に戻る | 実装