CREATE OPERATOR name ( PROCEDURE = func_name [, LEFTARG = lefttype ] [, RIGHTARG = righttype ] [, 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と書くことはできません。 PostgreSQLが1つではなく確実に2つの演算子として解釈するためにはX* @Yと書かなければなりません。
演算子!=は入力では<>に写像されるので、これらの2つの名前は常に等価です。
少なくともLEFTARGとRIGHTARGのどちらかは定義されなければなりません。二項演算子では両方が定義されなければなりません。右単項演算子ではLEFTARGのみが定義されなければならず、左単項演算子ではRIGHTARGのみが定義されなければなりません。
func_nameプロシージャは、CREATE FUNCTIONを使って事前に定義されていなければならず、指定された型の正しい数の引数(1つか2つ)を受け付けるように定義されていなければなりません。
存在する場合、交代演算子は、PostgreSQLが必要に応じて演算項目の順序を反転できるように認識させておくべきです。たとえば、領域に対する「より小さい」を判定する演算子「<<<」はおそらく、領域に対する「より大きい」を判定する演算子「>>>」を交代演算子として持つでしょう。これにより、問い合わせオプティマイザは自由に以下の文を、その次の文に置き換えることができます。
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))'
交代演算子名が与えられた場合、PostgreSQL はカタログの中からそれを探します。検出された交代演算子名の交代演算子がまだ存在しない場合、交代演算子のエントリは新しく作られた演算子をその交代演算子として持つように更新されます。これは否定子にも適用されます。互いの交代演算子または否定子である2つの演算子の定義を許可するためです。最初の演算子は交代演算子や否定子(のどちらか適切なもの)なしで定義されなければなりません。2番目の演算子が定義されるときに、最初の演算子を交代演算子または否定子として指定します。副作用として最初の演算子は更新されます( PostgreSQL 6.5以降では、両方の演算子がお互いを参照するようにすることもできます)。
オプションHASHES、SORT1、SORT2は結合の実行で問い合わせオプティマイザをサポートするために存在します。 PostgreSQLは常に反復置換[WONG76](つまり、boolean値を返す演算子によって分離された2つのタプル変数を持つ句の処理)により結合を評価できます。このほかに、PostgreSQLは[SHAP86]に従ったハッシュ結合アルゴリズムを使用することができます。とはいえ、どちらの戦略が適用できるかどうかを知る必要があります。現在のハッシュ結合アルゴリズムは等価性の評価を示す演算子のみに対して有効です。さらに、データ型の等価性は、型の表現形式がビット単位で等しいことを意味していなければなりません(たとえば、等価性の評価に関係のない未使用のビットを含んでいるデータ型はハッシュ結合させることができません)。HASHESのフラグは問い合わせオプティマイザに対し、ハッシュ結合がこの演算子で安全に使用できることを示します。
同様にして、2つのソート演算子は問い合わせオプティマイザに対し、マージソートが結合戦略で有効かどうか、そしてどちらの演算子が2つの演算項目クラスに対して使用されるのかを示します。ソート演算子は等価演算子に対してのみ提供されなければならず、それぞれが右辺と左辺のデータ型に対する「より小さい」を評価する演算子を参照しなければなりません。
他の結合戦略が実用的であった場合、 PostgreSQLはその戦略を使用するようにオプティマイザと実行システムを変更し、ある演算子が定義されたときに追加仕様を求めることになります。幸運なことに、研究団体が新しい結合戦略を発明することは滅多になく、追加されるユーザ定義の結合戦略の大部分は、その複雑さほどに価値があるとは思えません。
RESTRICTとJOINオプションは問い合わせオプティマイザの結果サイズの推定を補助します。もし、下記のような形式の句が条件の中にある場合、 PostgreSQLはこの句を満たすMYBOXESにあるインスタンスの割合を推測する必要があります。
MYBOXES.description <<< box '((0,0), (1,1))'
res_proc関数は、正確なデータ型の引数をとり、浮動小数点数値を返す、登録された(すでに CREATE FUNCTIONを使って定義された)関数でなければなりません。問い合わせオプティマイザは単にこの関数を ((0,0), (1,1))というパラメータを渡して呼び出し、その結果にリレーションのサイズを掛け、インスタンス数の期待値を入手します。
同様に、演算子の演算項目が2つともインスタンス変数を持っている場合、問い合わせオプティマイザは結合の結果のサイズを推測しなければなりません。関数join_procは結果サイズの期待値を計算するために、関係する2つのテーブルの要素数によって乗算された別の浮動小数点数値を返します。
以下のような関数があるとします。
my_procedure_1 (MYBOXES.description, box '((0,0), (1,1))')
上記の関数と、以下の演算子との違いは PostgreSQLが演算子の最適化を図り、演算子が呼び出されたときに、検索空間を制限するためにインデックスを使用するかどうかを決定できることです。
MYBOXES.description === box '((0,0), (1,1))'
しかしながら、関数を最適化することはせず、力任せに処理されます。さらに、演算子は1つまたは2つまでと引数の数が制限されているのに対して、関数はどんな数の引数でも取ることができます。