CREATE OPERATOR name ( PROCEDURE = func_name [, LEFTARG = lefttype ] [, RIGHTARG = righttype ] [, COMMUTATOR = com_op ] [, NEGATOR = neg_op ] [, RESTRICT = res_proc ] [, JOIN = join_proc ] [, HASHES ] [, MERGES ] [, SORT1 = left_sort_op ] [, SORT2 = right_sort_op ] [, LTCMP = less_than_op ] [, GTCMP = greater_than_op ] )
定義される演算子です。使用できる文字は下記を参照してください。 この名前は、スキーマで修飾されている場合があります。例 CREATE OPERATOR myschema.+ (...)
この演算子を実装するために使われる関数です。
もしある場合は、演算子の左辺の引数の型です。このオプションは左単項演算子では省略されます。
もしある場合は、演算子の右辺の引数の型です。このオプションは右単項演算子では省略されます。
この演算子の交代演算子です。
この演算子の否定子です。
この演算子の制約選択評価関数です。
この演算子の結合選択評価関数です。
この演算子がハッシュ結合をサポートできることを示します。
この演算子がマージ結合をサポートできることを示します。
この演算子がマージ結合をサポートできる場合、この演算子の左辺データ型をソートする小なり演算子です。
この演算子がマージ結合をサポートできる場合、この演算子の右辺データ型をソートする小なり演算子です。
この演算子がマージ結合をサポートできる場合、この演算子の入力データ型を比較する小なり演算子です。
この演算子がマージ結合をサポートできる場合、この演算子の入力データ型を比較する大なり演算子です。
CREATE OPERATORは、新しい演算子 nameを定義します。演算子を定義したユーザがその所有者となります。
スキーマ名が与えられている場合、その演算子は指定されたスキーマで作成されます。 スキーマ名がなければ、演算子は現在のスキーマ (検索パスの前にあるスキーマ。CURRENT_SCHEMA() 参照) で作成されます。
異なるデータ型の演算をする場合であれば、同じスキーマ内の 2 つの演算子が、同じ名前でも構いません。 これは、オーバーロードと呼ばれるものです。 演算子名があいまいな場合、システムでは、実際の入力データ型に基づいて対象となる演算子を選択しようとします。
演算子nameは、以下に示す文字で、NAMEDATALEN-1(デフォルトでは63)文字数までの文字列です。
+ - * / < > = ~ ! @ # % ^ & | ` ? $
$は、複数文字の演算子名の一部になることはできますが、単一文字の演算子として定義することはできません。
--と/*は演算子名のどこにも使うことができません。 コメントの開始とみなれてしまうからです。
複数文字の演算子名は、下記のうちの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、MERGES、SORT1、SORT2、LTCMP、および GTCMP オプションは、結合を実行する際に問い合わせオプティマイザをサポートするために存在します。 PostgreSQL は、常に反復置換 (つまり、boolean 値を返す演算子によって分離された、2 つのタプル変数を持つ句の処理) により、結合を評価できます。 このほかに、PostgreSQL では、ハッシュ結合アルゴリズムを使用することができます。 とはいえ、どちらの戦略が適用できるかどうかを知る必要があります。 現在のハッシュ結合アルゴリズムは等価性の評価を示す演算子のみに対して有効です。さらに、データ型の等価性は、型の表現形式がビット単位で等しいことを意味していなければなりません (たとえば、等価性の評価に関係のない未使用のビットを含んでいるデータ型はハッシュ結合させることができません)。 HASHES のフラグは、問い合わせオプティマイザに対し、ハッシュ結合がこの演算子で安全に使用できることを示します。
同様に、MERGES フラグは、この演算子でマージソートが結合戦略として使用可能かどうかを示します。 マージ結合では、2 つの入力データ型が一定の順序で並んでいる必要があります。また、マージ結合演算子が、その順序に従って等価演算子のように作用する必要があります。 たとえば、integer および float 変数を、両方の入力を通常の数値順にソートすることにより、等価的にマージ結合することが可能です。 マージ結合を実行するには、マージ結合の等価演算子に関連した 4 つの演算子を、システムが識別可能であることが必要です。 4 つの演算子とは、左の入力データ型に対する小なり比較、右の入力データ型に対する小なり比較、2 つのデータ型間の小なり比較、2 つのデータ型間の大なり比較です。 これらの演算子は、それぞれ SORT1、SORT2、LTCMP、および GTCMP オプションと、名前で指定することができます。 MERGES が指定された場合にこれらの演算子名のいずれでも省略されると、それぞれ <、<、<、および > というデフォルト名が埋められます。 また、これら 4 つの演算子オプションのいずれかが存在する場合、MERGES が暗黙指定されているものとみなされます。
他の結合戦略が実用的であった場合、 PostgreSQLはその戦略を使用するようにオプティマイザと実行システムを変更し、ある演算子が定義されたときに追加仕様を求めることになります。幸運なことに、研究団体が新しい結合戦略を発明することは滅多になく、追加されるユーザ定義の結合戦略の大部分は、その複雑さほどに価値があるとは思えません。
RESTRICT と JOIN オプションは、問い合わせオプティマイザの結果サイズの推定を補助します。 たとえば、以下のような形式の句があるとします。
myboxes.description <<< box '((0,0), (1,1))'
上記のような句が条件の中に記述されている場合、PostgreSQL では、この句を満たす 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))'
上記の関数と演算子との違いは、PostgreSQL が演算子の最適化を図り、演算子が呼び出されたときに、検索空間を制限するためにインデックスを使用するかどうかを決定できることです。しかしながら、関数を最適化することはせず、力任せに処理されます。さらに、演算子は1つまたは2つまでと引数の数が制限されているのに対して、関数はどんな数の引数でも取ることができます。
以下のコマンドは、BOXデータ型に対する領域等価性を判定する新しい演算子を定義します。
CREATE OPERATOR === ( LEFTARG = box, RIGHTARG = box, PROCEDURE = area_equal_procedure, COMMUTATOR = ===, NEGATOR = !==, RESTRICT = area_restriction_procedure, JOIN = area_join_procedure, HASHES, SORT1 = <<<, SORT2 = <<< -- ソート演算子が与えられているため、MERGES が暗黙指定されています。 -- LTCMP および GTCMP は、それぞれ < および > とみなされます。 );