mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
Extend the unknowns-are-same-as-known-inputs type resolution heuristic.
For a very long time, one of the parser's heuristics for resolving ambiguous operator calls has been to assume that unknown-type literals are of the same type as the other input (if it's known). However, this was only used in the first step of quickly checking for an exact-types match, and thus did not help in resolving matches that require coercion, such as matches to polymorphic operators. As we add more polymorphic operators, this becomes more of a problem. This patch adds another use of the same heuristic as a last-ditch check before failing to resolve an ambiguous operator or function call. In particular this will let us define the range inclusion operator in a less limited way (to come in a follow-on patch).
This commit is contained in:
@ -304,13 +304,18 @@ without more clues. Now discard
|
||||
candidates that do not accept the selected type category. Furthermore,
|
||||
if any candidate accepts a preferred type in that category,
|
||||
discard candidates that accept non-preferred types for that argument.
|
||||
Keep all candidates if none survive these tests.
|
||||
If only one candidate remains, use it; else continue to the next step.
|
||||
</para>
|
||||
</step>
|
||||
<step performance="required">
|
||||
<para>
|
||||
If only one candidate remains, use it. If no candidate or more than one
|
||||
candidate remains,
|
||||
then fail.
|
||||
If there are both <type>unknown</type> and known-type arguments, and all
|
||||
the known-type arguments have the same type, assume that the
|
||||
<type>unknown</type> arguments are also of that type, and check which
|
||||
candidates can accept that type at the <type>unknown</type>-argument
|
||||
positions. If exactly one candidate passes this test, use it.
|
||||
Otherwise, fail.
|
||||
</para>
|
||||
</step>
|
||||
</substeps>
|
||||
@ -376,7 +381,7 @@ be interpreted as type <type>text</type>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Here is a concatenation on unspecified types:
|
||||
Here is a concatenation of two values of unspecified types:
|
||||
<screen>
|
||||
SELECT 'abc' || 'def' AS "unspecified";
|
||||
|
||||
@ -394,7 +399,7 @@ and finds that there are candidates accepting both string-category and
|
||||
bit-string-category inputs. Since string category is preferred when available,
|
||||
that category is selected, and then the
|
||||
preferred type for strings, <type>text</type>, is used as the specific
|
||||
type to resolve the unknown literals as.
|
||||
type to resolve the unknown-type literals as.
|
||||
</para>
|
||||
</example>
|
||||
|
||||
@ -450,6 +455,36 @@ SELECT ~ CAST('20' AS int8) AS "negation";
|
||||
</para>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
<title>Array Inclusion Operator Type Resolution</title>
|
||||
|
||||
<para>
|
||||
Here is another example of resolving an operator with one known and one
|
||||
unknown input:
|
||||
<screen>
|
||||
SELECT array[1,2] <@ '{1,2,3}' as "is subset";
|
||||
|
||||
is subset
|
||||
-----------
|
||||
t
|
||||
(1 row)
|
||||
</screen>
|
||||
The <productname>PostgreSQL</productname> operator catalog has several
|
||||
entries for the infix operator <literal><@</>, but the only two that
|
||||
could possibly accept an integer array on the left-hand side are
|
||||
array inclusion (<type>anyarray</> <literal><@</> <type>anyarray</>)
|
||||
and range inclusion (<type>anyelement</> <literal><@</> <type>anyrange</>).
|
||||
Since none of these polymorphic pseudo-types (see <xref
|
||||
linkend="datatype-pseudo">) are considered preferred, the parser cannot
|
||||
resolve the ambiguity on that basis. However, the last resolution rule tells
|
||||
it to assume that the unknown-type literal is of the same type as the other
|
||||
input, that is, integer array. Now only one of the two operators can match,
|
||||
so array inclusion is selected. (Had range inclusion been selected, we would
|
||||
have gotten an error, because the string does not have the right format to be
|
||||
a range literal.)
|
||||
</para>
|
||||
</example>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="typeconv-func">
|
||||
@ -594,13 +629,18 @@ the correct choice cannot be deduced without more clues.
|
||||
Now discard candidates that do not accept the selected type category.
|
||||
Furthermore, if any candidate accepts a preferred type in that category,
|
||||
discard candidates that accept non-preferred types for that argument.
|
||||
Keep all candidates if none survive these tests.
|
||||
If only one candidate remains, use it; else continue to the next step.
|
||||
</para>
|
||||
</step>
|
||||
<step performance="required">
|
||||
<para>
|
||||
If only one candidate remains, use it. If no candidate or more than one
|
||||
candidate remains,
|
||||
then fail.
|
||||
If there are both <type>unknown</type> and known-type arguments, and all
|
||||
the known-type arguments have the same type, assume that the
|
||||
<type>unknown</type> arguments are also of that type, and check which
|
||||
candidates can accept that type at the <type>unknown</type>-argument
|
||||
positions. If exactly one candidate passes this test, use it.
|
||||
Otherwise, fail.
|
||||
</para>
|
||||
</step>
|
||||
</substeps>
|
||||
|
Reference in New Issue
Block a user