pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
函数调用的参数类型按 下列步骤解析。
函数参数类型解析
从 pg_proc 系统 目录中选择要考虑的函数。如果使用的是未限定的 函数名,所考虑的函数 是当前搜索路径中可见的名称和参数个数都 合适的函数(见 第 2.8.3 节)。 如果给出的是限定的函数名,则只考虑指定 模式中的函数。
如果搜索路径中找到多个参数类型完全相同的函数,只考虑路径中最早出现的那一个。参数类型不同的函数则不受搜索路径位置影响,处于同等地位。
检查是否存在一个恰好接受输入参数类型的函数。如果存在(在被考虑的函数集合中至多只有一个精确匹配),就使用它。(涉及unknown的情况在这一步永远找不到匹配。)
如果找不到精确匹配,看看这个函数调用是否 是一个平凡的类型强制转换请求。当函数调用 只有一个参数且函数名与某个数据类型的(内部) 名相同时就是这种情况。此外,函数参数必须是 未知类型的字面量或与该数据类型二进制 兼容的类型。满足这些条件时,函数参数被强制 转换为该数据类型,不会有任何显式的函数调用。
寻找最佳匹配。
丢弃输入类型不匹配且不能(用隐式强制转换函数) 转换成匹配的候选函数。 为此目的,假定 unknown 字面量 可以转换成任何类型。如果只剩一个 候选,就使用它;否则继续下一步。
遍历所有候选,保留输入类型精确匹配 最多的。如果没有任何精确匹配,则保留全部 候选。如果只剩一个候选,就使用它;否则继续下一步。
遍历所有候选,保留输入类型精确匹配或二进制 兼容匹配最多的。如果没有任何精确或二进制 兼容匹配,则保留全部候选。 如果只剩一个候选,就使用它;否则继续下一步。
遍历所有候选,保留在需要类型强制转换的最多个 位置上接受首选类型的。 如果没有任何候选接受首选类型,则保留全部候选。 如果只剩一个候选,就使用它;否则继续下一步。
如果有输入参数是 unknown,检查其余 候选在这些参数位置上接受的类型 类别。在每个位置上,如果有候选接受 string 类别就选择该类别(这种偏向字符串的 做法是恰当的,因为未知类型的字面量看起来 确实像字符串)。 否则,如果所有剩余候选接受相同的类型类别, 就选择该类别;否则失败,因为 没有更多线索就无法推断出正确的选择。还要注意 是否有候选接受所选类别中的首选数据类型。 现在丢弃不接受所选类型类别的候选; 此外,如果某个候选在给定的参数 位置上接受首选类型,就丢弃在该参数上 接受非首选类型的候选。
如果只剩一个候选操作符,就使用它。如果没有候选操作符或者不止一个候选操作符剩余,则失败。
例 7.4. 阶乘函数参数类型解析
pg_proc 目录中只定义了一个 int4fac 函数。 因此下面的查询自动把 int2 参数 转换为 int4:
tgl=> SELECT int4fac(int2 '4');
int4fac
---------
24
(1 row)
并且实际上被解析器变换为
tgl=> SELECT int4fac(int4(int2 '4'));
int4fac
---------
24
(1 row)
例 7.5. substr 函数类型解析
pg_proc 中声明了两个 substr 函数。但 只有一个接受两个参数,类型是 text 和 int4。
如果用未指定类型的字符串常量调用,该类型会直接 与唯一的候选函数类型匹配:
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)
实际上,解析器知道 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)。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。