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つ以上を含まない限り "+" または "-" で終ることができません。
~ ! @ # % ^ & | ` ? $
Note: 非 SQL 標準の演算子名を使って作業する場合、通常はあいまいさを 避けるために隣接する演算子をスペースで区切る必要があります。 例えば、"@" という名前の左単項演算子を定義した場合、 X*@Y と書くことはできません。 Postgres が1つではなく確実に2つの 演算子として読むためには X* @Y と書かなければなりません。
演算子 "!=" は入力では "<>" に写像されるので、これらの 2つの名前は常に等価です。
少なくとも LEFTARG と RIGHTARG のどちらかは定義されなければ なりません。二項演算子では両方が定義されなければなりません。 右単項演算子では 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 以降では、両方の演算子がお互いを参照する ようにすることもできます。)
オプション HASHES、SORT1、SORT2 は結合の実行で問い合わせオプティマイザ をサポートするために存在します。Postgres は常に反復置換 [WONG76] (つまり、ブール値を返す演算子によって分離 された二つのタプル変数を持つ句の処理)により結合を評価できます。 このほかに、Postgres は[SHAP86] にした がったハッシュ結合アルゴリズムを使用することができます。 とはいっても、 どちらの戦略が適用できるかどうかを知る必要があります。 現在のハッシュ 結合アルゴリズムは等価性の評価を示す演算子のみに対して有効です。さらに、 データ型の等価性は、型の表現形式がビット単位で等しいことを意味 していなければなりません。(例えば、等価性の評価に関係のない未使用の ビットを含んでいるデータ型はハッシュ結合させることができません。) HASHES のフラグは問合せオプティマイザに対し、ハッシュ結合がこの演算子 で安全に使用できることを示します。
同様にして、2つのソート演算子は問合せオプティマイザに対し、マージ ソートが結合戦略で有効かどうか、そしてどちらの演算子が2つの 演算項目クラスに対して使用されるのかを示します。 ソート演算子は 等価演算子に対してのみ提供されなければならず、それぞれが右辺と左辺の データ型に対する「より小さい」を評価する演算子を参照しなければ なりません。
他の結合戦略が実用的であった場合、 Postgres はその戦略を使用するようにオプティマイザと実行システムを変更し、 ある演算子 が定義されたときに追加仕様を求めることになります。 幸運なこと に、研究団体が新しい結合戦略を発明することは滅多になく、追加される ユーザ定義の結合戦略の大部分は、 内包する複雑性ほどに価値があるとは 思えません。
RESTRICT と JOIN オプションは問い合わせオプティマイザの結果サイズ の推定を補助します。もし、下記のような形式の句
MYBOXES.description <<< box '((0,0), (1,1))'が条件の中にある場合、Postgres は この句を満たす MYBOXES にあるインスタンスの割合を推測する必要 があります。res_proc 関数は、正確なデータ型の引数をとり、浮動小数点数値を返す、登録 された(既に CREATE FUNCTION を使って定義 された)関数でなければなりません。問い合わせオプティマイザは 単にこの関数を ((0,0), (1,1)) というパラメータ を渡して呼び出し、その結果にリレーションのサイズを掛け、 インスタンス数の期待値を入手します。
同様に、演算子の演算項目が2つともインスタンス変数を持っている場合、 問合せオプティマイザは結合の結果のサイズを推測しなければなりません。 関数 join_proc は結果サイズの期待値を計算するために、関係する 2つのテーブルの要素数によって乗算された別の浮動小数点数値を返します。
関数
my_procedure_1 (MYBOXES.description, box '((0,0), (1,1))')と、演算子
MYBOXES.description === box '((0,0), (1,1))'との違いは Postgres が演算子の最適化を図り、 演算子が呼び出されたときに、検索空間を制限するためにインデックスを 使用するかどうかを決定できることです。しかしながら、関数を最適化する ことはせず、力任せに処理されます。 更に、演算子は1つまたは2つまでと引数の数が制限されているにも 関わらず、関数はどんな数の引数でも取ることが出来ます。