What is the rule for `unknown` and type inference?

删除回忆录丶 提交于 2019-12-13 00:14:53

问题


I'm looking for an explanation of the following, If I run something like this I get an unknown type,

SELECT pg_typeof(a)
FROM ( SELECT null ) AS t(a);
 pg_typeof 
-----------
 unknown
(1 row)

However, with more complexity it becomes text magically,

SELECT pg_typeof(a)
FROM (
  SELECT null
  UNION SELECT null
) AS t(a);
 pg_typeof 
-----------
 text
(1 row)

Explicit casting doesn't change that, this also returns text,

SELECT pg_typeof(a)
FROM (
  SELECT null::unknown
  UNION SELECT null::unknown               
) AS t(a);

It follows amusingly that this works,

SELECT pg_typeof(a)
FROM (
  SELECT null
  UNION SELECT 42                  
) AS t(a);

But this doesn't,

SELECT pg_typeof(a)
FROM (
  SELECT null
  UNION SELECT null
  UNION SELECT 42
) AS t(a);

What purpose does the unknown type have at all if it's assumed to be text in the above circumstance?


回答1:


There are actually three questions in there that I will try to answer.

  1. What is the purpose of unknown?

    This is the data type initially assigned to NULLs and string literals in SQL statements. If such literals were assigned type text immediately, it would be difficult to infer the correct type.

    For example, you want myfunc('hello') to invoke myfunc(character varying), but there is no implicit type cast from text to character varying (and it would cause ambiguity if you created one).

  2. Why does SELECT null return a column of type unknown?

    The traditional answer is: Because the user didn't specify the type.

    However, this behaviour has been problematic. For example, if you create a table like this:

    CREATE TABLE test
       AS SELECT 'hello';
    

    you would end up with a column of type unknown, which is undesireable and will cause problems further on. The type unknown really should not be user visible, but rather an implementation detail.

    Consequently, this commit has changed the behaviour from PostgreSQL v10 on: Now any unknowns left in a SELECT or RETURNING list are forced to text, and tables cannot be created with columns of type unknown.

  3. Why does SELECT NULL UNION SELECT 42 work, but not SELECT NULL UNION SELECT NULL UNION SELECT 42?

    This is owed to the type conversion rules. UNION is left associative, so the latter query is interpreted as

    (SELECT NULL UNION SELECT NULL) UNION SELECT 42;
    

    Now the first UNION resolves to data type text because of rule 3:

    If all inputs are of type unknown, resolve as type text (the preferred type of the string category).

    This causes an error when trying to resolve the type for the second UNION because of rule 4:

    If the non-unknown inputs are not all of the same type category, fail.

    On the other hand, in the query

    SELECT NULL UNION SELECT 42;
    

    “NULL” has type unknown, and “42” has type integer (the type chosen for numeric literals without decimal point).

    Rule 5

    Choose the first non-unknown input type which is a preferred type in that category, if there is one.

    does not apply here, because integer is not a preferred type in its category (that would be oid and double precision), so rule 6 is used:

    Otherwise, choose the last non-unknown input type that allows all the preceding non-unknown inputs to be implicitly converted to it.

    This results in a type of integer.



来源:https://stackoverflow.com/questions/43624354/what-is-the-rule-for-unknown-and-type-inference

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!