pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
函数调用类型解析
在 pg_proc 系统目录中检查精确匹配。 (涉及 unknown 的情况在这一步 永远找不到匹配。)
寻找最佳匹配。
列出所有同名、参数个数相同且输入类型 匹配或可以强制转换成匹配的 函数。(为此目的,假定 unknown 字面量 可以转换成任何类型。)如果只有一个, 就使用它;否则继续下一步。
遍历所有候选,保留输入类型精确匹配 最多的。如果没有任何精确匹配,则保留全部 候选。如果只剩一个候选,就使用它;否则继续下一步。
遍历所有候选,保留输入类型精确匹配或二进制 兼容匹配最多的。如果没有任何精确或二进制 兼容匹配,则保留全部候选。 如果只剩一个候选,就使用它;否则继续下一步。
遍历所有候选,保留在需要类型强制转换的最多个 位置上接受首选类型的。 如果没有任何候选接受首选类型,则保留全部候选。 如果只剩一个候选,就使用它;否则继续下一步。
如果有输入参数是"unknown",检查其余候选在这些参数 位置上接受的类型类别。在每个位置上,如果有候选接受 "string" 类别就选择该类别(这种偏向字符串的做法 是恰当的,因为未知类型的字面量看起来确实像字符串)。 否则,如果所有剩余候选接受相同的类型类别, 就选择该类别;否则失败,因为没有更多线索 就无法推断出正确的选择。还要注意 是否有候选接受所选类别中的首选数据类型。 现在丢弃不接受所选类型类别的操作符候选; 此外,如果某个候选在给定的参数 位置上接受首选类型,就丢弃在该参数上 接受非首选类型的候选。
如果只剩一个候选操作符,就使用它。如果没有候选操作符或者不止一个候选操作符剩余,则失败。
如果找不到最佳匹配,看看这个函数调用是否 是一个平凡的类型强制转换请求。当函数调用 只有一个参数且函数名与某个数据类型的(内部) 名相同时就是这种情况。此外,函数参数必须是 未知类型的字面量或与该数据类型二进制 兼容的类型。满足这些条件时,函数参数被强制 转换为该数据类型。
pg_proc 目录中只定义了一个阶乘函数。 因此下面的查询自动把 int2 参数 转换为 int4:
tgl=> select int4fac(int2 '4');
int4fac
---------
24
(1 row)
并且实际上被解析器变换为
tgl=> select int4fac(int4(int2 '4'));
int4fac
---------
24
(1 row)
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 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。