10.3. 関数

関数呼び出しで使用される特定の関数は以下の手順に従って解決されます。

関数型の解決

  1. pg_procシステムカタログから、調査の対象とする関数を選択します。 修飾されていない関数名が使用される場合、調査の対象となる関数は、現行の検索パスで可視になっている、同一の名前と引数の数を持つ関数が調査対象であると見做されます。 (項5.8.3を参照してください。) 修飾された関数名が与えられている場合、指定されたスキーマの関数のみが調査対象と見做されます。

    1. 検索パスで、引数のデータ型が同じである複数の関数を検出した場合、そのパスで最初に検出された関数のみを調査対象と見做します。 ただし、引数のデータ型が異なる関数は、検索パス内の位置に関係なく、同じように調べられます。

  2. 正確に入力引数型を受け付ける関数があるかどうかチェックします。 該当する関数があれば(調査される関数の集合内で正確に一致するものは1つしか有り得ません)、それを使用します。 (unknownを含む場合は、この段階で一致するものは決して見つかりません。)

  3. 正確に一致するものが存在しなかった場合、その関数呼び出しが平凡な型変換要求であるかどうかを確認します。 これは、関数呼び出しがただ1つの引数をとり、関数名が何らかのデータ型の(内部的な)名前と同一である場合に発生します。 更に、その関数の引数は、unknown型のリテラルか指定されたデータ型とバイナリ互換でなければなりません。 これらの条件に合う場合、実際に関数を呼び出すことなく、関数の引数は指定されたデータ型に変換されます。

  4. 最もよく合うものを検索します。

    1. 関数の候補のうち、入力値のデータ型が一致せず、また、(暗黙的変換関数を使用して)一致するように変換できないものを破棄します。 unknownリテラルは、上記の目的で何にでも変換可能とみなされます。 1つの侯補しか残らない場合、それを使います。 それ以外の場合は次の段階に進みます。

    2. すべての侯補を検索し、入力型に最も正確に合うものを残します。 (この時、ドメインはその基本型と同一であると見做します。) 正確に合うものが何もなければすべての侯補を残します。 1つの侯補しか残らない場合、それを使います。 それ以外の場合は次の段階に進みます。

    3. すべての侯補を検索し、型変換が必要とされる所で(入力データ型カテゴリの)好ましい型を受け付けるものを残します。 好ましい型を受け付けるものが何もなければすべての侯補を残します。 1つの侯補しか残らない場合、それを使います。 それ以外の場合は次の段階に進みます。

    4. 入力引数でunknownのものがあった場合、それらの残った侯補に引数位置で受け入れられる型カテゴリをチェックします。 各位置で候補がstringカテゴリを受け付ける場合は、そのカテゴリを選択します。 (unknown 型のリテラルは文字列のようなものですので、この文字列への重みづけは適切です。) そうでなければ、もし残ったすべての侯補が同じ型カテゴリを受け入れる場合はそのカテゴリを選択します。 そうでもなければ失敗します。 なぜならさらに手掛りがなければ正しい選択が演繹されることができないからです。 ここで、選択された型カテゴリを受け付けない演算子候補は破棄されます。 更に、与えられた引数の位置上の好ましい型を受け付ける候補が1つでもある場合、その引数の好ましい型ではないものを受け付ける候補は破棄されます。

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

この"最善一致"規則は演算子と関数の型解決で同一であることに注意してください。 以下に例を示します。

例 10-4. 丸め関数引数の型解決

2つの引数を取るround関数は1つしかありません。 (第一引数はnumeric、第二引数はintegerです。) ですから、以下の問い合わせは自動的に、integer型の第一引数をnumericに変換します。

SELECT round(4, 4);

 round
--------
 4.0000
(1 row)

問い合わせはパーサによって実質以下のように変形されます。

SELECT round(CAST (4 AS numeric), 4);

小数点を持つ数値定数はまずnumericに割り当てられますので、以下の問い合わせでは型変換が不要です。そのためかなり効率的になる可能性があります。

SELECT round(4.0, 4);

例 10-5. 部分文字列関数の型解決

substr関数は複数存在します。 その1つはtextinteger型を取ります。 型の指定がない文字列定数で呼び出した場合、システムは好ましいカテゴリstring(すなわちtext型)の引数を受け付ける候補関数を選択します。

SELECT substr('1234', 3);

 substr
--------
     34
(1 row)

文字列がvarchar型と宣言された場合、これはテーブルから取り出した場合が考えられますが、パーサはそれをtextになるように変換しようと試みます。

SELECT substr(varchar '1234', 3);

 substr
--------
     34
(1 row)

これは以下になるようにパーサによって変換されます。

SELECT substr(CAST (varchar '1234' AS text), 3);

注意: パーサはpg_castカタログからtextvarcharがバイナリ互換、つまり、何らかの物理的な変換を行なうことなく片方を受け付ける関数にもう片方を渡すことができることを学習します。 従って、この場合実際に挿入される明示的な型変換呼び出しはありません。

また、integer型の引数でこの関数が呼び出された場合、パーサはそれをtextに変換しようと試みます。

SELECT substr(1234, 3);

 substr
--------
     34
(1 row)

これは実際は以下を実行します。

SELECT substr(CAST (1234 AS text), 3);

integerからtextへの暗黙的に呼び出し可能なキャストが存在しますので、この自動変形は成功します。