関数呼び出しの引数型は以下の手順に従って解決されます。
関数の引数型の解決
pg_proc システムカタログ内で一致するかどうかを点検します(unknownを含む場合、この段階で対を見つけることはありません)。
カタログ内で正確に一致するものが存在しなかった場合、その関数呼び出しが平凡な型強制要求としてのものかを確認します。これは、関数呼び出しが 1 つの引数をとり、関数名が何らかのデータ型の(内部的な)名前と同一である場合に発生します。更に、その関数の引数は、unknown型のリテラルか指定されたデータ型とバイナリ互換でなければなりません。これらの条件に合う場合、明示的な関数を呼び出すことなく、関数の引数は指定されたデータ型に強制されます。
最もよく合うものを検索します。
入力型が合う、もしくは合うように型強制ができる、同じ名前かつ引数の数が同じ関数のすべての一覧を作成します(unknownリテラルはこの目的では何にでも型強制できるとみなされます)。もし1つしかなければそれを使います。そうでなければ次の段階に進みます。
すべての侯補を検索し、入力型に最も正確に合うものを残します。正確に合うものが何もなければすべての侯補を残します。1つだけ侯補が残った場合はそれを使います。それ以外の場合は次の段階に進みます。
すべての侯補を検索し、入力型に最も正確に合う、もしくはバイナリ互換性のあるものを残します。もし正確に合うものかバイナリ互換性のあるものがなければすべての侯補を残します。1つの侯補しか残らない場合、それを使います。それ以外の場合は次の段階に進みます。
すべての侯補を検索し、型強制が要求される最も多くの引数位置で好ましい型を受け入れるものを残します。好ましい型を受け入れるものがなければすべての侯補を残します。1つの侯補しか残らない場合、それを使います。それ以外の場合は次の段階に進みます。
入力引数でunknownのものがあった場合、それらの残った侯補に引数位置で受け入れられる型カテゴリをチェックします。もしそのカテゴリを受け入れる侯補が合った場合、それぞれのポジションで文字列カテゴリを選択します(unknown型のリテラルは確かに文字列のように見えるので、この文字列へのバイアスは適しています)。そうでなければ、もし残ったすべての侯補が同じ型カテゴリを受け入れる場合はそのカテゴリを選択します。そうでもなければ失敗します。なぜならさらに手掛りがなければ正しい選択が演繹されることができないからです。さらに、侯補の中で、選択されたカテゴリ内で好ましい型を受け入れるものがあるかどうか注意します。ここで選択された型カテゴリを受け入れない侯補は捨てます。さらに、もし侯補で好ましい型を与えられた引数ポジションで受け入れるものがあれば、その引数の好ましくない型を受け入れる侯補を捨てます。
1つの侯補しか残らない場合、それを使います。もし侯補がない、もしくは1つより多い侯補が残る場合は失敗します。
Example 5-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 5-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)という変換関数があるので、これは成功します。