上面解说了如何在一次操作符调用中确定所应用的到底是哪个操作符。请留神这个过程间承受被调用操作符的优先级影响。详阅 「操作符优先级」- http://www.oushu.com/docs/ch/... 。
操作符类型解析
- 从零碎表pg_operator中选出要思考的操作符。 如果应用了一个不带模式润饰的操作符名(常见的情况), 那么认为该操作符是那些在以后搜寻门路中名字和参数个数都匹配的操作符 (参阅 「模式搜寻门路」- http://www.oushu.com/docs/ch/... )。如果给出一个带润饰的操作符名, 那么只思考指定模式中的操作符。
a. 如果搜寻门路中找到了多个雷同参数类型的操作符,那么只思考最早呈现在门路中的那一个。 然而不同参数类型的操作符将被平等对待,而不论它们在门路中的地位如何。 - 查找准确承受输出参数类型的操作符。如果找到一个(在一组被思考的操作符中, 可能只存在一个准确匹配的),则用之。
a. 如果一个双目操作符调用中的一个参数是unknown类型, 则在本次查看中假如其与另一个参数类型雷同。包含两个unknown 输出的调用或一个一元带有unknown输出的操作符,将绝不会在此处找到匹配。 - 查找最佳匹配。
a. 摈弃那些输出类型不匹配并且也不能隐式转换成匹配的候选操作符。 unknown文本在这种状况下能够转换成任何货色。 如果只剩下一个候选项,则用之,否则持续下一步。
b. 遍历所有候选操作符,保留那些输出类型匹配最精确的。(此时,域被看作和他们的根本类型雷同。) 如果没有一个操作符能被保留,则保留所有候选。如果只剩下一个候选项,则用之,否则持续下一步。
c. 遍历所有候选操作符,保留那些须要类型转换时承受(属于输出数据类型的类型领域的)首选类型地位最多的操作符。如果没有承受首选类型的操作符,则保留所有候选。如果只剩下一个候选项,则用之,否则持续下一步。
d. 如果有任何输出参数是unknown类型,查看残余的候选操作符对应参数地位的类型领域。 在每一个可能承受字符串类型领域的地位应用 string类型(这种对字符串的偏爱是适合的, 因为 unknown 文本的确像字符串)。另外,如果所有剩下的候选操作符都承受雷同的类型领域, 则抉择该类型领域,否则抛出一个谬误(因为在没有更多线索的条件下无奈作出正确的抉择)。而后, 如果任意候选操作符在某个给定的参数地位承受一个首选类型, 则摈弃那些在该参数地位承受非首选类型的候选操作符。
a. 如果只有一个操作符合乎,那么应用它。否则,产生一个谬误。
上面是一些例子。
例.阶乘操作符类型解析
在零碎表中里只有一个阶乘操作符,它以double precision类型作为参数。扫描器给上面查问表达式的参数赋予integer的初始类型:
SELECT 2 ^ 3 AS "exp";exp-----8(1 row)
分析器对参数做类型转换,查问等效于:
SELECT CAST(2 AS double precision) ^ CAST(3 AS double precision) AS "exp";
例.字符串连贯操作符类型剖析
一种字符串格调的语法既能够用于字符串也能够用于简单的扩大类型。 未声明类型的字符串将被所有可能的候选操作符匹配。
有一个未声明的参数的例子:
SELECT text 'abc' || 'def' AS "text and unknown";text and unknown------------------abcdef(1 row)
本例中分析器寻找两个参数都是text的操作符, 因而第二个参数就被认为是text类型。
上面是连贯两个未声明类型的值:
SELECT 'abc' || 'def' AS "unspecified";unspecified-------------abcdef(1 row)
因为查问中没有申明任何类型,所以本例中对类型没有任何初始提醒,因而,分析器查找所有候选操作符,发现既存在承受字符串类型领域的操作符也存在承受位串类型领域的操作符。因为字符串类型领域是首选,所以抉择字符串类型领域的首选类型text 作为解析未知类型文本的申明类型。
例.绝对值和取反操作符类型剖析
OushuDB 操作符表外面有几条记录对应于前缀操作符@, 它们都用于为各种数值类型实现绝对值操作。其中之一用于float8类型, 它是数值类型领域中的首选类型。因而,在面对非数值输出的时候,OushuDB 会应用该类型:
SELECT @ '-4.5' AS "abs";abs-----4.5(1 row)
此处,零碎在利用选定的操作符之前隐式的转换text类型为float8类型。 咱们能够验证它是float8而不是其它类型:
SELECT @ '-4.5e500' AS "abs";ERROR: "-4.5e500" is out of range for type double precision
另一方面,前缀操作符~(按位取反)只为整数数据类型定义, 而不为float8定义。因而,如果咱们用~做相似的试验将失去:
SELECT ~ '20' AS "negation";ERROR: operator is not unique: ~ "unknown"HINT: Could not choose a best candidate operator. You may need to add explicit type casts.
这是因为零碎无奈决定几个可能的~操作符中到底应该应用哪一个。 咱们能够用明确地类型转换来帮它:
SELECT ~ CAST('20' AS int8) AS "negation";negation-----------21(1 row)