diff --git a/doc/src/sgml/typeconv.sgml b/doc/src/sgml/typeconv.sgml index cca45eb5698..1976dc29dd2 100644 --- a/doc/src/sgml/typeconv.sgml +++ b/doc/src/sgml/typeconv.sgml @@ -185,7 +185,9 @@ That is, if a query is well-formed and the types already match, then the query s without spending extra time in the parser and without introducing unnecessary implicit conversion calls in the query. + + Additionally, if a query usually requires an implicit conversion for a function, and if then the user defines a new function with the correct argument types, the parser @@ -209,7 +211,7 @@ should use this new function and no longer do implicit conversion to use the old The specific operator that is referenced by an operator expression is determined using the following procedure. Note that this procedure is indirectly affected - by the precedence of the involved operators, since that will determine + by the precedence of the operators involved, since that will determine which sub-expressions are taken to be the inputs of which operators. See for more information. @@ -217,7 +219,7 @@ should use this new function and no longer do implicit conversion to use the old Operator Type Resolution - + Select the operators to be considered from the pg_operator system catalog. If a non-schema-qualified @@ -240,7 +242,7 @@ search path position. - + Check for an operator accepting exactly the input argument types. If one exists (there can be only one exact match in the set of @@ -248,7 +250,7 @@ operators considered), use it. - + If one argument of a binary operator invocation is of the unknown type, then assume it is the same type as the other argument for this check. @@ -256,10 +258,17 @@ Invocations involving two unknown inputs, or a unary operator with an unknown input, will never find a match at this step. + + +If one argument of a binary operator invocation is of the unknown +type and the other is of a domain type, next check to see if there is an +operator accepting exactly the domain's base type on both sides; if so, use it. + + - + Look for the best match. @@ -275,9 +284,15 @@ candidate remains, use it; else continue to the next step. +If any input argument is of a domain type, treat it as being of the +domain's base type for all subsequent steps. This ensures that domains +act like their base types for purposes of ambiguous-operator resolution. + + + + Run through all candidates and keep those with the most exact matches -on input types. (Domains are considered the same as their base type -for this purpose.) Keep all candidates if none have exact matches. +on input types. Keep all candidates if none have exact matches. If only one candidate remains, use it; else continue to the next step. @@ -376,7 +391,7 @@ be interpreted as type text. -Here is a concatenation on unspecified types: +Here is a concatenation of two values of unspecified types: SELECT 'abc' || 'def' AS "unspecified"; @@ -394,7 +409,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, text, is used as the specific -type to resolve the unknown literals as. +type to resolve the unknown-type literals as. @@ -450,6 +465,45 @@ SELECT ~ CAST('20' AS int8) AS "negation"; + +Custom Operator on a Domain Type + + +Users sometimes try to declare operators applying just to a domain type. +This is possible but is not nearly as useful as it might seem, because the +operator resolution rules are designed to select operators applying to the +domain's base type. As an example consider + +CREATE DOMAIN mytext AS text CHECK(...); +CREATE FUNCTION mytext_eq_text (mytext, text) RETURNS boolean AS ...; +CREATE OPERATOR = (procedure=mytext_eq_text, leftarg=mytext, rightarg=text); +CREATE TABLE mytable (val mytext); + +SELECT * FROM mytable WHERE val = 'foo'; + +This query will not use the custom operator. The parser will first see if +there is a mytext = mytext operator +(), which there is not; +then it will consider the domain's base type text, and see if +there is a text = text operator +(), which there is; +so it resolves the unknown-type literal as text and +uses the text = text operator. +The only way to get the custom operator to be used is to explicitly cast +the literal: + +SELECT * FROM mytable WHERE val = text 'foo'; + +so that the mytext = text operator is found +immediately according to the exact-match rule. If the best-match rules +are reached, they actively discriminate against operators on domain types. +If they did not, such an operator would create too many ambiguous-operator +failures, because the casting rules always consider a domain as castable +to or from its base type, and so the domain operator would be considered +usable in all the same cases as a similarly-named operator on the base type. + + + @@ -565,9 +619,15 @@ candidate remains, use it; else continue to the next step. +If any input argument is of a domain type, treat it as being of the +domain's base type for all subsequent steps. This ensures that domains +act like their base types for purposes of ambiguous-function resolution. + + + + Run through all candidates and keep those with the most exact matches -on input types. (Domains are considered the same as their base type -for this purpose.) Keep all candidates if none have exact matches. +on input types. Keep all candidates if none have exact matches. If only one candidate remains, use it; else continue to the next step. @@ -858,8 +918,23 @@ and Related Constructs If all inputs are of the same type, and it is not unknown, -resolve as that type. Otherwise, replace any domain types in the list with -their underlying base types. +resolve as that type. + + + + + +If any input is of a domain type, treat it as being of the +domain's base type for all subsequent steps. + + + Somewhat like the treatment of domain inputs for operators and + functions, this behavior allows a domain type to be preserved through + a UNION or similar construct, so long as the user is + careful to ensure that all inputs are implicitly or explicitly of that + exact type. Otherwise the domain's base type will be preferred. + +