5.3. 関数

関数呼び出し型の解決

  1. pg_proc システムカタログ内で一致するかどうかを点検します。 (unknown を含む場合、この段階で対を見つけることは ありません。)

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

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

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

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

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

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

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

  3. もし良く合うものが見つからなければ、その関数呼び出しが些細な型強制 要求であるかどうかを見ます。これは、もし関数呼び出しが一つの引数しか持たず、 関数名が他のデータ型の(内部的な)名前と同じだった場合に起こります。 さらに、関数の引数は、unknown 型リテラルか指定されたデータ型とバイナリ互換性 がある型のどちらかでなければいけません。これらの条件が揃うと、 関数の引数は指定されたデータ型に型強制されます。

5.3.1. 例

5.3.1.1. 階乗関数

pg_proc カタログには、階乗関数が 1 つのみ定義されています。ですから 次の問い合わせは自動的に int2 引数を int4 に変換します。

tgl=> select int4fac(int2 '4');
 int4fac
---------
      24
(1 row)
そして、実際にはパーサによって次のように変換されます。
tgl=> select int4fac(int4(int2 '4'));
 int4fac
---------
      24
(1 row)

5.3.1.2. Substring 関数

pg_proc には2つの substr 関数が宣言されています。 しかし、text 型と int4 型という 2 つの型を 持つものは 1 つしかありません。

型指定の無い文字列定数を与えて呼び出した場合、その型は、1 つの候補関数の 型に直ちに適合します。

tgl=> select substr('1234', 3);
 substr
--------
     34
(1 row)

あるテーブルから文字列を得るといった場合にあり得るものとして、文字列が varchar 型として宣言されていたとすると、パーサは文字列 を text 型に強制しようとします。

tgl=> select substr(varchar '1234', 3);
 substr
--------
     34
(1 row)
は、パーサによって次のように変換されます。
tgl=> select substr(text(varchar '1234'), 3);
 substr
--------
     34
(1 row)

Note: 実際に、パーサは textvarchar が "バイナリ互換性がある" ということを分かっています。つまり、物理的変換 を行わずにもう一方を受け入れる関数に渡されることができるということです。 したがってこの場合、明示的な型変換呼び出しは実際には挿入されません。

int4 型を使って呼び出された場合、パーサは text に変換しようとします。

tgl=> select substr(1234, 3);
 substr
--------
     34
(1 row)
は、実際には次のように実行します。
tgl=> select substr(text(1234), 3);
 substr
--------
     34
(1 row)
システムカタログに text(int4) という変換関数があるので、これは 成功します。