5.2. 演算子

演算子型の解決

  1. pg_operator システムカタログ内で正確に一致するかどうかを点検します。

    1. 二項演算子の 1 つの引数が unknown 型であった場合、このチェックの もう片方の引数と同一の型であると仮定します。 他の unknown を含む場合は、この段階では対を見つける ことはありません。

  2. 最も合うものを検索します。

    1. 入力型が合う、もしくは合うように型強制することができる、 同じ名前を持つ全演算子の一覧を作成します。(unknown リテラルはこの目的では何にでも型強制できるとみなされます。) もし一つしかない場合はそれを使います。それ以外の場合は 次の段階に進みます。

    2. 全ての侯補を検索し、入力型に最も正確に合うものを残します。 もし正確に合うものがなければ全ての侯補を残します。 一つの侯補しか残らない場合、それを使います。それ以外の場合は 次の段階に進みます。

    3. 全ての侯補を検索し、入力型に最も正確に合う、もしくはバイナリ互換性のある ものを残します。もし正確に合うものかバイナリ互換性のあるもの がなければ全ての侯補を残します。一つの侯補しか残らない場合、それを使います。 それ以外の場合は次の段階に進みます。

    4. 全ての侯補を検索し、型強制が要求される最も多くのポジションの 好ましい型を受け入れるものを残します。好ましい型を受け入れる ものがなければ全ての侯補を残します。一つの侯補しか残らない場合、 それを使います。それ以外の場合は次の段階に進みます。

    5. もし入力引数で "unknown" のものがあれば、残った侯補からそれらの 引数の位置において受け入れられる型カテゴリをチェックします。 もしそのカテゴリを受け入れる侯補があれば、それぞれのポジションで "string" カテゴリを選択します( unknown 型のリテラルは確かに文字列のように 見えるので、この string へのバイアスは適しています)。 そうでなければ、もし残った全ての侯補が同じ型カテゴリを受け入れる場合は そのカテゴリを選択します。そうでもなければ失敗します。なぜなら さらに手掛りがなければ正しい選択が演繹されることができないからです。 さらに、侯補の中で、選択されたカテゴリ内で好ましい型を受け入れるものが あるかどうか注意して下さい。ここで選択された型カテゴリを受け入れない 演算子侯補は捨てます。さらに、もし侯補で好ましい型を与えられた 引数位置で受け入れるものがあれば、その引数の好ましい型ではない 侯補を捨てます。

    6. もし一つの侯補しか残らない場合、それを使います。もし一つの侯補も残らない 場合、もしくは一つより多い侯補が残る場合は失敗します。

5.2.1. 例

5.2.1.1. 指数演算子

カタログ内に定義された指数演算子は 1 つだけ存在し、 double precision 型の引数をとります。スキャナは、次の問い合わせ の式の両方の引数に int4 という初期段階での型を割り当てます。

tgl=> select 2 ^ 3 AS "Exp";
 Exp
-----
   8
(1 row)
ですので、パーサは両引数に型変換を行ない、上の問い合わせは
tgl=> select CAST(2 AS double precision) ^ CAST(3 AS double precision) AS "Exp";
 Exp
-----
   8
(1 row)
または、
tgl=> select 2.0 ^ 3.0 AS "Exp";
 Exp
-----
   8
(1 row)
と同じものになります。

Note: 暗黙的な型変換を行なう関数を呼び出すことがありませんので、最後の形式が 最もオーバヘッドの少ないものになります。これは小さな問い合わせでは問題には なりませんが、大きなテーブルを伴う問い合わせの性能に影響を与える可能性 があります。

5.2.1.2. 文字列の結合

文字列のようなシンタックスは、文字列型だけではなく、複雑な拡張された 型の処理にも使われます。型指定のない文字列は演算子候補と同様の一致が なされます。

1 つの引数の型が指定されていない場合

tgl=> SELECT text 'abc' || 'def' AS "Text and Unknown";
 Text and Unknown
------------------
 abcdef
(1 row)

この場合、パーサは、text を両引数にとる演算子が存在す るかどうかを検索します。これは存在しますので、パーサは 2 番目の引数 は text 型として解釈すべきであると仮定をします。

型指定の無い結合の場合

tgl=> SELECT 'abc' || 'def' AS "Unspecified";
 Unspecified
-------------
 abcdef
(1 row)

この場合、問い合わせに型が何も指定されていませんので使用すべき型についての ヒントが初期段階において存在しません。ですので、パーサは全ての侯補となる 演算子を検索し、文字列カテゴリとビット文字列カテゴリの両方の入力 を受け入れる侯補があることを発見します。有効である場合は文字列カテゴリ のほうが好ましいので、そのカテゴリが選択されます。そして文字列の "好ましい型" である text が unknown のリテラルを解決 する特定の型として使われます。

5.2.1.3. 階乗

この例は興味深い結果を示しています。歴史的に、階乗演算子は整数型についてのみ 定義されています。Postgres 演算子カタログは、 階乗用に整数を引数としてとる 1 つのエントリしか持ちません。 もし非整数の数字を引数として渡した場合、 Postgres は、その引数を整数に変換して階乗計算を行なうようになります。

tgl=> select (4.3 !);
 ?column?
----------
       24
(1 row)

Note: 非整数の階乗の原理が定義されていませんので、もちろん、これは数学的 に疑わしい結果を導き出します。しかしデータベースの役割は数学を教え るものでは無く、データを操作する道具です。ユーザが浮動小数点数値の 階乗を計算することを選択したならば、Postgres はその要求に応えようとします。