関数呼び出しの引数型は以下の手順に従って解決されます。
関数の引数型の解決
pg_proc システムカタログから、調査の対象となる関数を選択します。 修飾されていない関数名が使用される場合、調査される関数は現行の検索パスで可視になっている、名前と引数の数が正しい関数です (Section 2.8.3 参照)。 修飾された関数名が与えられている場合、指定されたスキーマの関数のみを調べることができます。
検索パスで、引数のデータ型が同じである複数の関数を検出した場合、そのパスで最初に検出された関数のみを調べることができます。 ただし、引数のデータ型が異なる関数は、検索パス内の位置に関係なく、同じように調べられます。
正確に入力引数型を受け取っている関数があるかどうかチェックしてください。 該当する関数があれば (調査される関数のセット内で正確に一致するものは 1 つしか有り得ません)、それを使用してください。 (unknown を含む場合は、この段階では一致するものが見つかることはありません。)
正確に一致するものが存在しなかった場合、その関数呼び出しが平凡な型強制要求であるかどうかを確認します。これは、関数呼び出しが 1 つの引数をとり、関数名が何らかのデータ型の(内部的な)名前と同一である場合に発生します。更に、その関数の引数は、unknown型のリテラルか指定されたデータ型とバイナリ互換でなければなりません。これらの条件に合う場合、明示的な関数を呼び出すことなく、関数の引数は指定されたデータ型に強制されます。
最もよく合うものを検索します。
関数の候補のうち、入力値のデータ型が一致せず、また、(暗黙的強制関数を使用して) 一致を強制できないものを破棄してください。 unknown リテラルは、上記の目的で何にでも強制的に変更できるとみなされます。1つの侯補しか残らない場合、それを使います。 それ以外の場合は次の段階に進みます。
すべての侯補を検索し、入力型に最も正確に合うものを残します。正確に合うものが何もなければすべての侯補を残します。1つの侯補しか残らない場合、それを使います。 それ以外の場合は次の段階に進みます。
すべての侯補を検索し、入力型に最も正確に合う、もしくはバイナリ互換性のあるものを残します。もし正確に合うものかバイナリ互換性のあるものがなければすべての侯補を残します。1つの侯補しか残らない場合、それを使います。 それ以外の場合は次の段階に進みます。
すべての侯補を検索し、型強制が要求される最も多くの引数位置で好ましい型を受け入れるものを残します。好ましい型を受け入れるものがなければすべての侯補を残します。1つの侯補しか残らない場合、それを使います。 それ以外の場合は次の段階に進みます。
入力引数でunknownのものがあった場合、それらの残った侯補に引数位置で受け入れられる型カテゴリをチェックします。もしそのカテゴリを受け入れる侯補が合った場合、それぞれのポジションで文字列カテゴリを選択します(unknown型のリテラルは確かに文字列のように見えるので、この文字列へのバイアスは適しています)。そうでなければ、もし残ったすべての侯補が同じ型カテゴリを受け入れる場合はそのカテゴリを選択します。 そうでもなければ失敗します。 なぜならさらに手掛りがなければ正しい選択が演繹されることができないからです。さらに、侯補の中で、選択されたカテゴリ内で好ましい型を受け入れるものがあるかどうか注意します。ここで選択された型カテゴリを受け入れない侯補は捨てます。 さらに、もし侯補で好ましい型を与えられた引数ポジションで受け入れるものがあれば、その引数の好ましくない型を受け入れる侯補を捨てます。
1つの侯補しか残らない場合、それを使います。もし侯補がない、もしくは1つより多い侯補が残る場合は失敗します。
Example 7-4. 階乗関数の引数型の解決
pg_proc カタログには、int4fac 関数が1つのみ定義されています。ですから、次の問い合わせは自動的にint2引数をint4に変換します。
tgl=> SELECT int4fac(int2 '4'); int4fac --------- 24 (1 row)
そして、実際にはパーサによって以下のように変換されます。
tgl=> SELECT int4fac(int4(int2 '4')); int4fac --------- 24 (1 row)
Example 7-5. 部分文字列関数の引数型の解決
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: 実際に、パーサはtextとvarcharがバイナリ互換性があるということを知っています。 つまり、物理的変換を行わずにもう一方を受け入れる関数に渡されることができるということです。したがってこの場合、明示的な型変換呼び出しは実際には挿入されません。
int4型を使って呼び出された場合、パーサはtextに変換しようとします。
tgl=> SELECT substr(1234, 3); substr -------- 34 (1 row)
上記のものは、実際には次のようになります。
tgl=> SELECT substr(text(1234), 3); substr -------- 34 (1 row)
システムカタログにtext(int4)という変換関数があるので、これは成功します。