CREATE OPERATOR name ( PROCEDURE = func_name [, LEFTARG = type1 ] [, RIGHTARG = type2 ] [, COMMUTATOR = com_op ] [, NEGATOR = neg_op ] [, RESTRICT = res_proc ] [, JOIN = join_proc ] [, HASHES ] [, SORT1 = left_sort_op ] [, SORT2 = right_sort_op ] )
定義する演算子。 使用できる文字については後で説明します。
この演算子の実装に使用される関数。
もしあれば、この演算子の左辺の引数の型。 左単項演算子の場合、このオプションは省略されます。
もしあれば、この演算子の右辺の引数の型。 右単項演算子の場合、このオプションは省略されます。
この演算子の交代演算子。
この演算子の否定子。
この演算子の制限選択評価関数。
この演算子の結合選択評価関数。
この演算子がハッシュ結合をサポートできることを示します。
この演算子がマージ結合をサポートできる場合、この演算子の 左辺用データ型をソートする演算子。
この演算子がマージ結合をサポートできる場合、この演算子の 右辺用データ型をソートする演算子。
CREATE OPERATOR は name という 新しい演算子を定義します。 演算子を定義したユーザがその所有者になります。
演算子 name は、NAMEDATALEN-1 (デフォルトで 31) 以下の、次の文字で名前が 付けられます。
+ - * / < > = ~ ! @ # % ^ & | ` ? $ :
"$" と ":" は、複数文字からなる演算子の名前の一部になるこ とはできますが、これらを使用した 1 文字の演算子を定義する ことができません。
"--" と "/*" は、コメントの開始とみなされますので、演算子 名の中に含めることはできません。
複数文字からなる演算子名に以下の文字を少なくとも1 文字、含 んでいない限り、その名前を "+" または "-" で終らせることは できません。
~ ! @ # % ^ & | ` ? $ :
Note: 通常、SQL 標準ではない演算子名を使用する場合、曖昧さを防ぐため に演算子の前後を空白で区切る必要があります。 例えば、"@" という名前の左単項演算子を定義した場合、 X*@Y と記述することはできません。 Postgres が 1 つではなく、確実に 2 つの演算子の名前として読みとることができるように、 X* @Y と記述しなければなりません。
"!=" 演算子は入力を "<>" にそのまま写しますので、これら 2 つの名前は常に同じ意味になります。
LEFTARG と RIGHTARG の少なくともどちらか 1 つは定義されな ければなりません。 二項演算子の場合、両方が定義されなければなりません。 右単項演算子の場合、LEFTARG のみが定義されなければならず、 また、左単項演算子の場合は、RIGHTARG のみが定義されなけれ ばなりません。
func_name プロシージャは事前に CREATE FUNCTION を使用して定義してお く必要があり、また、指定された型の引数を正確な個数 (1 つ または 2 つ)を受け付けるように定義されていなければなりま せん。
存在するのならば、Postgres が 必要に応じて演算項目の順序を反転させることができるように、 交代演算子を認識させておくべきです。 例えば、領域に対する「より小さい」を判定する、<<< 演算子はおそらく領域に対する「より大きい」を判定する、 >>>演算子を交代演算子として持つでしょう。 これにより、問い合わせオプティマイザは自由に
box '((0,0),(1,1))' >>> MYBOXES.descriptionを
MYBOXES.description <<< box '((0,0),(1,1))'に変換することができます。
これにより、実行コードが常に後者の表現を使用するようにでき、 問い合わせオプティマイザを多少単純化することができます。
同様に否定子演算子があれば、それを認識させておくべきです。 領域の「等しい」を判定する、=== 演算子と領域の「等しくな い」を判定する、!== 演算子が存在するものと仮定します。 否定子の関係により、問い合わせオプティマイザは
NOT MYBOXES.description === box '((0,0),(1,1))'を
MYBOXES.description !== box '((0,0),(1,1))'に単純化することができます。
交代演算子の名前が与えられた場合、 Postgres はカタログからそれを検索します。 検出された段階でそれ自体がまだ交代演算子を持っていなかった場合、 その交代演算子の項目は、新しく作成された演算子をその交代演算子 として持つように更新されます。 否定子に対しても同様の処理が行なわれます。 これにより、互いが交代演算子または否定子になる 2 つの演算子を 定義することができます。 最初の演算子は交代演算子または否定子 (のどちらか適切なもの) が ない状態で定義されなければなりません。 2 番目の演算子が定義される時に、最初の演算子を交代演算子または 否定子として指名します。 最初の演算子はその副作用として更新されます。 (Postgres 6.5 の時点では、互いを参照する 2 つの演算子を持つだけ でも動作します。)
問い合わせオプティマイザの結合処理を補助するために HASHES、 SORT1、SORT2 オプションが存在します。 Postgres は常に反復置換[WONG76] を使用して結合 (つまり、ブール値を返す演算子で区切られた 2 つのタプル変数を持つ句の処理) を評価できます。 更に、Postgres は [SHAP86] の方針 に従ったハッシュ結合アルゴリズムを使用することもできます。 しかし、どちらの戦略が適用できるかを認知する必要があります。 現在のハッシュ結合アルゴリズムは等価性検査が存在する演算子に 対してのみ正しく動作します。 更にいうと、データ型の等価性は、その型の表現がビット単位で等 しいことを意味していなければなりません。 (例えば、等価性検査に関係しない未使用のビットを持つデータ型は ハッシュ結合させることができません。) HASES フラグは問い合わせオプティマイザに対して、この演算子を使 用して安全にハッシュ結合ができることを示します。
同様に、2 つのソート演算子は問い合わせオプティマイザに対して、 マージソートがソート戦略において使用可能かどうか、どちらの演 算子を使用して 2 つの演算項目クラスをソートすべきかを示します。 ソート演算子は等価性演算子に対して用意されなければならず、ま た、左辺と右辺それぞれのデータ型の「より小さい」を判定する演 算子を参照しなければなりません。
他の結合戦略が実用的であることが判明した場合、 Postgres はそれを使用するように オプティマイザと実行システムを変更し、演算子が定義される時 に追加仕様を要求することになるでしょう。 好運にも、研究団体が新しい結合戦略を発明することは滅多にあ りませんし、ユーザ定義の結合戦略の追加される大部分はその複 雑性を含める価値があるとは思われていません。
RESTRICT、JOIN オプションは問い合わせオプティマイザの結果 サイズの推定を補助します。 次の形式の句がその条件にある場合、
MYBOXES.description <<< box '((0,0),(1,1))'Postgres はMYBOXES 内のこの句を 満たすインスタンスがどのくらいあるのかを評価する必要がでて きます。 res_proc 関数 は、正確なデータ型の引数を取り、浮動小数点数値を返す、(既 に CREATE FUNCTION を使用して定義された ことを意味する)登録済みの関数でなければなりません。 問い合わせオプティマイザは単にこの関数を ((0,0),(1,1)) というパラメータを渡して 呼出し、その結果にリレーションのサイズを掛け、インスタンス 数の期待値を入手します。
同様に、演算子の演算項目の両方がインスタンス変数を持つ場合、 問い合わせオプティマイザは結合の結果のサイズを評価しなけれ ばなりません。 join_proc 関数 は結果サイズの期待値を計算するために、2 つの クラスが包含する候補を掛け合わせた、別の浮動小数点数値を返 します。
関数
my_procedure_1 (MYBOXES.description, box '((0,0),(1,1))')と演算子
MYBOXES.description === box '((0,0),(1,1))'の違いは、Postgresは演算子の最 適化を図り、演算子が呼び出された時にその検索空間を狭めるた めにインデックスを使用するかどうか決定することができること です。 しかしながら関数の最適化は図られず、力任せに処理されます。 更に、関数は任意数の引数を取ることができますが、演算子は 1 つか 2 つに限られています。