表 37.9で示すように、btreeでは一つの必須サポート関数と、4つの省略可能なサポート関数を定義します。 5つのユーザ定義メソッドは以下の通りです。
order
btreeの演算子族が比較演算子を提供する各データ型の組み合わせに対して、比較サポート関数を提供しなければなりません。それらはサポート関数1番でpg_amproc
に、また、比較での左右のデータ型と等しいamproclefttype
/amprocrighttype
に、登録されます(すなわち、pg_amop
に登録されている演算子が対応するものと同じデータ型です)。
比較関数は2つの非NULL値A
とB
を取り、
A
<
B
、A
=
B
、または、A
>
B
であるときにそれぞれ、<
0
、0
、または、>
0
であるint32
の値を返さなければなりません。
NULLの結果は許されず、データ型の全ての値は比較可能でなければなりません。
例としてsrc/backend/access/nbtree/nbtcompare.c
を参照してください。
比較される値が照合順序が適用可能なデータ型のものである場合、比較サポート関数に適切な照合順序のOIDが渡され、標準のPG_GET_COLLATION()
機構が使用されます。
sortsupport
任意で、btree演算子族はソートサポート関数を提供してもよいです。これはサポート関数2番で登録されます。
この関数は、素朴に比較サポート関数を呼び出すよりも、ソート目的により効果的な方法での比較の実装を可能にします。
これに関するAPIはsrc/include/utils/sortsupport.h
で定義されています。
in_range
任意で、btree演算子族はin_rangeサポート関数を提供してもよいです。これはサポート関数3番に登録されます。
これはbtreeインデックス操作中には使われません。そうではなく、演算子族のセマンティクスをRANGE
offset
PRECEDING
とRANGE
offset
FOLLOWING
フレーム境界タイプ(4.2.8を参照)を含むWINDOW句に対応できるように拡張します。
基本的には、提供される拡張情報はどのように演算子族のデータ並び順と互換性のある方法でoffset
値を足すか引くかです。
in_range
関数は以下のシグネチャを持たなければなりません。
in_range(val
type1,base
type1,offset
type2,sub
bool,less
bool) returns bool
val
とbase
は同じ型でなければならず、これは演算子族でサポートされる型の一つ(すなわち、並び順を提供する対象の型)です。
しかしながら、offset
は異なる型のものでも可能です。それは演算子族でサポートされないものでもよいです。
例としては、組み込みのtime_ops
族がinterval
型のoffset
を持つin_range
関数を提供しています。
演算子族は、任意のサポートされる型と一つまたは複数のoffset
型に対するin_range
関数を提供できます。
各in_range
関数は、pg_amproc
にtype1
と等しいamproclefttype
とtype2
に等しいamproclefttype
で登録されるべきです。
in_range
関数の本質的なセマンティクスは2つのBooleanフラグパラメータに依存します。
これは以下のように、base
にoffset
を加算または減算して、それからval
を結果と比較すべきです。
!
sub
かつ
!
less
であるなら、
val
>=
(base
+
offset
)を返します
!
sub
かつ
less
であるなら、
val
<=
(base
+
offset
)を返します
sub
かつ
!
less
であるなら、
val
>=
(base
-
offset
)を返します
sub
かつ
less
であるなら、
val
<=
(base
-
offset
)を返します
このように実行する前に、本関数は、offset
の符号を検査すべきです。
すなわち、負であったなら、エラーERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE
(22013)、エラー文面としては「invalid preceding or following size in window function(ウィンドウ関数で先行または後続のサイズが不正です)」などを出すことです。
(意味上の必要性が乏しいと見られることから非標準の演算子族はこの制限を無視することを選ぶかもしれませんが、これはSQL標準で必要とされています。)
中核コードが特定のデータ型における「ゼロより小さい」ことの意味を理解しなくても良いように、この要件はin_range
関数に委託されます。
さらに期待されることは、in_range
関数は、実用的には、base
+
offset
やbase
-
offset
がオーバーフローする場合にエラーを投げるのを避けるべきです。
たとえ値がデータ型の範囲を超えたとしても正しい比較結果は決定できます。
データ型が「infinity」や「NaN」などの概念を含む場合には、in_range
の結果が演算子族の通常のソート順序と一致するように特別な対応が必要となることに注意してください。
in_range
関数の結果は、演算子族で規定されるソート順序と整合していなければなりません。
正確には、与えらえれた任意のoffset
とsub
の修正値は以下のようになります。
less
= trueのin_range
がいくつかのval1
とbase
に対して真であるなら、同じbase
の全てのval2
<=
val1
に対して真でなければなりません。
less
= trueのin_range
が、いくつかのval1
とbase
に対して偽であるなら、同じbase
の全てのval2
>=
val1
に対して偽でなければなりません。
less
= trueのin_range
がいくつかのval
とbase1
に対して真であるなら、同じval
の全てのbase2
>=
base1
に対して真でなければなりません。
less
= trueのin_range
が一部のval
とbase1
に対して偽であるなら、同じval
の全てのbase2
<=
base1
に対して偽でなければなりません。
less
= falseのときには、逆条件の類似した命題が適用できます。
整列しようとしている型(type1
)が照合可能であるなら、標準のPG_GET_COLLATION()機構を使って、in_range
関数に適切な照合順序のOIDが渡されます。
in_range
関数は、通例STRICTと印付けされ、NULL入力を処理する必要がありません。
equalimage
省略可能ですが、btree演算子族はequalimage
(「イメージ等価を意味する等価」)サポート関数を提供してもよいです。これはサポート関数4番で登録されます。
この関数は、中核コードがbtree重複排除の最適化を適用するのが安全かを決定できるようにします。
今のところ、equalimage
関数はインデックスの構築または再構築時にのみ呼び出されます。
equalimage
関数は以下のシグネチャを持たなければなりません。
equalimage(opcintype
oid
) returns bool
戻り値は演算子クラスと照合順序についての静的な情報です。
true
を返すことは、A
およびB
引数が何らセマンティック情報を損失すること無しに交換可能でもあるとき、演算子クラスに対するorder
関数が0
(「引数が等しい」)だけを返すことが保証されていることを示します。
equalimage
関数が登録されていなかったり、false
を返すことは、この条件は守られないであろうことを示します。
opcintype
引数は演算子クラスタがインデックスを作るデータ型の
です。
これは同じ基となるpg_type
.oidequalimage
関数を演算子クラスを横断して再利用できるようになる利便性があります。
opcintype
が照合可能なデータ型である場合には、適切な照合順序のOIDが、標準のPG_GET_COLLATION()
機構を使って、equalimage
関数に渡されます。
演算子クラスに関する限り、true
を返すことは、重複排除が安全(あるいはequalimage
関数に渡されたOIDの照合順序について安全)であることを示します。
しかしながら、コアコードは、全てのインデックス列がequalimage
関数を登録する演算子クラスを使っていて、各関数が呼ばれたとき実際にtrue
を返すときに、そのインデックスに対して重複排除を安全と見做すだけです。
イメージ等価は単純にビット毎に等しいこととほとんど同じ条件です。
一点微妙な違いがあります。varlenaデータ型にインデックス作成するとき、入力時の一貫性のないTOAST圧縮の適用のために、同じdatumの二つのイメージのディスク上の表現はビット毎には等しくないかもしれません。
これまでは、演算子クラスのequalimage
関数がtrue
を返すときには、datum_image_eq()
C関数が常に演算子クラスのorder
関数と一致すると想定して安全でした(同じ照合順序のOIDがequalimage
とorder
の両関数に渡されるとして)。
コアコードは基本的に、複数データ型の族の中の演算子クラスの「等価性がイメージ等価性を含む」状態について、同族の他の演算子クラスの詳細に基づいた、いかなる推測もできません。
また、ある演算子族が型にまたがってequalimage
関数を登録していることを認識できず、そのような試みはエラーになります。
これは「等価性がイメージ等価性を含む」状態は、演算子族の階層でおおむね定義されている、ソートと等価性のセマンティクスに依存しているだけでは無いためです。
一般に、ある特定データ型の実装によるセマンティクスは別個に考慮されなければなりません。
コアPostgreSQL配布物に含まれる演算子クラスが従う慣習は、標準品、すなわち、一般的なequalimage
関数を登録することです。
大部分の演算子クラスタはbtequalimage()
を登録しています。これは重複排除が無条件に安全であることを示しています。
text
などの照合可能なデータ型に対する演算子クラスはbtvarstrequalimage()
を登録します。これは決定的な照合順序では重複排除が安全であることを示します。
サードパーティ拡張におけるベストプラクティスは制御を保つためにそれら自身のカスタム関数を登録することです。
options
省略可能ですが、B-treeの演算子族はoptions
(「演算子クラス固有オプション」)サポート関数を提供してもよいです。これはサポート関数5番に登録されます。
この関数はユーザに見える演算子クラスの振る舞いを制御するパラメータの集合を定義します。
options
サポート関数は以下のシグネチャを持たなければなりません。
options(relopts
local_relopts *
) returns void
関数にはlocal_relopts
構造体へのポインタが渡されます。ここには演算子クラス固有のオプションの集合が書かれている必要があります。
このオプションにはPG_HAS_OPCLASS_OPTIONS()
およびPG_GET_OPCLASS_OPTIONS()
マクロを使って他のサポート関数からアクセスが可能です。
今のところ、options
サポート関数を持ったB-Treeの演算子クラスはありません。
B-treeはGiST、SP-GiST、GINおよびBRINで行われてるような柔軟なキーの表現を許していません。
そのため、おそらくはoptions
が現在のB-treeインデックスアクセスメソッドで多数適用されることはありません。
それでも、統一性のためにサポート関数がB-treeに追加されました。おそらくPostgreSQLでのB-treeの更なる進化の過程で使用法を見つけ出すでしょう。