函数
函数类型解析
1、从系统表PG_PROC中选择所有可能被选到的函数。如果使用了一个不带模式修饰的函数名称,那么认为该函数是那些在当前搜索路径中的函数。如果给出一个带修饰的函数名,那么只考虑指定模式中的函数。如果搜索路径中找到了多个不同参数类型的函数。将从中选择一个合适的函数。
2、查找和输入参数类型完全匹配的函数。如果找到一个,则用之。如果输入的实参类型都是unknown类型,则不会找到匹配的函数。
3、如果未找到完全匹配,请查看该函数是否为一个特殊的类型转换函数。
4、寻找最优匹配。
抛弃那些输入类型不匹配并且也不能隐式转换成匹配的候选函数。unknown文本在这种情况下可以转换成任何东西。如果只剩下一个候选项,则用之,否则继续下一步。
遍历所有候选函数,保留那些输入类型匹配最准确的。此时,域被看作和它们的基本类型相同。如果没有一个函数能准确匹配,则保留所有候选。如果只剩下一个候选项,则用之,否则继续下一步。
遍历所有候选函数,保留那些需要类型转换时接受首选类型位置最多的函数。如果没有接受首选类型的函数,则保留所有候选。如果只剩下一个候选项,则用之,否则继续下一步。
如果有任何输入参数是unknown类型,检查剩余的候选函数对应参数位置的类型范畴。在每一个能够接受字符串类型范畴的位置使用string类型(这种对字符串的偏爱是合适的,因为unknown文本确实像字符串)。另外,如果所有剩下的候选函数都接受相同的类型范畴,则选择该类型范畴,否则抛出一个错误(因为在没有更多线索的条件下无法作出正确的选择)。现在抛弃不接受选定的类型范畴的候选函数,然后,如果任意候选函数在那个范畴接受一个首选类型,则抛弃那些在该参数位置接受非首选类型的候选函数。如果没有一个候选符合这些测试则保留所有候选。如果只有一个候选函数符合,则使用它;否则,继续下一步。
如果同时有unknown和已知类型的参数,并且所有已知类型的参数有相同的类型,假设unknown参数也是这种类型,检查哪个候选函数可以在unknown参数位置接受这种类型。如果正好一个候选符合,那么使用它。否则,产生一个错误。
示例
示例1:
圆整函数参数类型解析。只有一个round函数有两个参数(第一个是numeric,第二个是integer)。所以下面的查询自动把第一个类型为integer的参数转换成numeric类型。
显示小数点后的0需要执行如下语句进行设置:
set behavior_compat_options='display_leading_zero';
SELECT round(4, 4);
结果显示如下:
round
--------
4.0000
(1 row)
实际上它被分析器转换成:
SELECT round(CAST (4 AS numeric), 4);
因为带小数点的数值常量初始时被赋予numeric类型,因此下面的查询将不需要类型转换,并且可能会略微高效一些:
SELECT round(4.0, 4);
示例2:
子字符串函数类型解析。有多个substr函数,其中接受字符串声明为text、数字声明为integer类型,也接受字符串声明为text类型,数字声明为number类型等情况。如果用一个未声明类型的字符串常量调用它,系统将选择接受string类型范畴的首选类型(也就是text类型)的候选函数。
字符串声明为text、数字声明为integer类型:
SELECT substr('1234', 3);
结果显示如下:
substr -------- 34 (1 row)
字符串声明为text类型,数字声明为number类型:
SELECT substr('abcd', 3::number, 3::number);
结果显示如下:
substr -------- cd (1 row)
如果该字符串声明为varchar类型,就像从表中取出来的数据一样,分析器将试着将其转换成text类型:
SELECT substr(varchar '1234', 3);
结果显示如下:
substr -------- 34 (1 row)
被分析器转换后实际上变成:
SELECT substr(CAST (varchar '1234' AS text), 3);