CREATE OPERATOR

Name

CREATE OPERATOR  --  新しいユーザ演算子を定義する。

Synopsis

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 ] )
  

入力

name

定義する演算子。 使用できる文字については後で説明します。

func_name

この演算子の実装に使用される関数。

type1

もしあれば、この演算子の左辺の引数の型。 左単項演算子の場合、このオプションは省略されます。

type2

もしあれば、この演算子の右辺の引数の型。 右単項演算子の場合、このオプションは省略されます。

com_op

この演算子の交代演算子。

neg_op

この演算子の否定子。

res_proc

この演算子の制限選択評価関数。

join_proc

この演算子の結合選択評価関数。

HASHES

この演算子がハッシュ結合をサポートできることを示します。

left_sort_op

この演算子がマージ結合をサポートできる場合、この演算子の 左辺用データ型をソートする演算子。

right_sort_op

この演算子がマージ結合をサポートできる場合、この演算子の 右辺用データ型をソートする演算子。

出力

CREATE

演算子の作成に成功した場合に返されるメッセージ。

説明

CREATE OPERATORname という 新しい演算子を定義します。 演算子を定義したユーザがその所有者になります。

演算子 name は、NAMEDATALEN-1 (デフォルトで 31) 以下の、次の文字で名前が 付けられます。

+ - * / < > = ~ ! @ # % ^ & | ` ? $ : 
   

名前の選択に関して、以下に示す数点の制限があります。

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 つに限られています。

注意

より詳しくは、 PostgreSQL ユーザガイド の演算 子の章を参照して下さい。 ユーザ定義の演算子をデータベースから削除する場合は DROP OPERATOR を参照して下さい。

使用法

次のコマンドは BOX データ型に対する領域等価性を判定する 新しい演算子を定義します。

CREATE OPERATOR === (
   LEFTARG = box,
   RIGHTARG = box,
   PROCEDURE = area_equal_procedure,
   COMMUTATOR = ===,
   NEGATOR = !==,
   RESTRICT = area_restriction_procedure,
   JOIN = area_join_procedure,
   HASHES,
   SORT1 = <<<,
   SORT2 = <<<
);
  

互換性

SQL92

CREATE OPERATORPostgres の拡張です。 SQL92 には CREATE OPERATOR はありません。