diff --git a/doc/src/sgml/typeconv.sgml b/doc/src/sgml/typeconv.sgml index 55ce51b2c10..567f184e943 100644 --- a/doc/src/sgml/typeconv.sgml +++ b/doc/src/sgml/typeconv.sgml @@ -23,7 +23,7 @@ using explicit type coercion. This chapter introduces the PostgreSQL type conversion mechanisms and conventions. -Refer to the relevant sections in the and +Refer to the relevant sections in and for more information on specific data types and allowed functions and operators. @@ -43,8 +43,8 @@ has an associated data type which determines its behavior and allowed usage. PostgreSQL has an extensible type system that is much more general and flexible than other RDBMS implementations. Hence, most type conversion behavior in PostgreSQL -should be governed by general rules rather than by ad-hoc heuristics to allow -mixed-type expressions to be meaningful, even with user-defined types. +should be governed by general rules rather than by ad-hoc heuristics, to allow +mixed-type expressions to be meaningful even with user-defined types. @@ -64,8 +64,8 @@ tgl=> SELECT text 'Origin' AS "Label", point '(0,0)' AS "Value"; (1 row) -has two strings, of type text and point. -If a type is not specified for a string, then the placeholder type +has two literal constants, of type text and point. +If a type is not specified for a string literal, then the placeholder type unknown is assigned initially, to be resolved in later stages as described below. @@ -218,7 +218,7 @@ should use this new function and will no longer do the implicit conversion using The operand types of an operator invocation are resolved following - to the procedure below. Note that this procedure is indirectly affected + the procedure below. Note that this procedure is indirectly affected by the precedence of the involved operators. See for more information. @@ -283,7 +283,7 @@ If only one candidate remains, use it; else continue to the next step. If any input arguments are unknown, check the type categories accepted at those argument positions by the remaining -candidates. At each position, try the "string" category if any +candidates. At each position, select the "string" category if any candidate accepts that category (this bias towards string is appropriate since an unknown-type literal does look like a string). Otherwise, if all the remaining candidates accept the same type category, select that @@ -366,7 +366,7 @@ Strings with unspecified type are matched with likely operator candidates. -One unspecified argument: +An example with one unspecified argument: tgl=> SELECT text 'abc' || 'def' AS "Text and Unknown"; Text and Unknown @@ -405,34 +405,50 @@ type to resolve the unknown literals to. -Factorial Operator Type Resolution +Absolute-Value and Factorial Operator Type Resolution -This example illustrates an interesting result. Traditionally, the -factorial operator is defined for integers only. The PostgreSQL -operator catalog has only one entry for factorial, taking an integer operand. -If given a non-integer numeric argument, PostgreSQL -will try to convert that argument to an integer for evaluation of the -factorial. - +The PostgreSQL operator catalog has several +entries for the prefix operator @, all of which implement +absolute-value operations for various numeric datatypes. One of these +entries is for type float8, which is the preferred type in +the numeric category. Therefore, PostgreSQL +will use that entry when faced with a non-numeric input: -tgl=> SELECT (4.3 !); - ?column? ----------- - 24 +tgl=> select @ text '-4.5' as "abs"; + abs +----- + 4.5 (1 row) - - - -Of course, this leads to a mathematically suspect result, -since in principle the factorial of a non-integer is not defined. -However, the role of a database is not to teach mathematics, but -to be a tool for data manipulation. If a user chooses to take the -factorial of a floating point number, PostgreSQL -will try to oblige. +Here the system has performed an implicit text-to-float8 conversion +before applying the chosen operator. We can verify that float8 and +not some other type was used: + +tgl=> select @ text '-4.5e500' as "abs"; +ERROR: Input '-4.5e500' is out of range for float8 + - + + +On the other hand, the postfix operator ! (factorial) +is defined only for integer datatypes, not for float8. So, if we +try a similar case with !, we get: + +tgl=> select text '44' ! as "factorial"; +ERROR: Unable to identify a postfix operator '!' for type 'text' + You may need to add parentheses or an explicit cast + +This happens because the system can't decide which of the several +possible ! operators should be preferred. We can help +it out with an explicit cast: + +tgl=> select cast(text '44' as int8) ! as "factorial"; + factorial +--------------------- + 2673996885588443136 +(1 row) + @@ -507,13 +523,14 @@ If only one candidate remains, use it; else continue to the next step. If any input arguments are unknown, check the type categories accepted at those argument positions by the remaining candidates. At each position, -try the string category if any candidate accepts that category (this bias towards string +select the string category if any candidate accepts that category +(this bias towards string is appropriate since an unknown-type literal does look like a string). Otherwise, if all the remaining candidates accept the same type category, select that category; otherwise fail because the correct choice cannot be deduced without more clues. Also note whether any of the candidates accept a preferred data type within the selected category. -Now discard operator candidates that do not accept the selected type category; +Now discard candidates that do not accept the selected type category; furthermore, if any candidate accepts a preferred type at a given argument position, discard candidates that accept non-preferred types for that argument. @@ -536,7 +553,8 @@ then fail. Factorial Function Argument Type Resolution -There is only one factorial function defined in the pg_proc catalog. +There is only one int4fac function defined in the +pg_proc catalog. So the following query automatically converts the int2 argument to int4: @@ -619,7 +637,7 @@ tgl=> SELECT substr(1234, 3); 34 (1 row) -actually executes as +which actually executes as tgl=> SELECT substr(text(1234), 3); substr @@ -637,6 +655,12 @@ system catalog. Query Targets + + Values to be inserted into a table are coerced to the destination + column's datatype according to the + following steps. + + Query Target Type Resolution @@ -666,33 +690,36 @@ passing the column's declared length as the second parameter. -<type>varchar</type> Storage Type Conversion +<type>character</type> Storage Type Conversion -For a target column declared as varchar(4) the following query +For a target column declared as character(20) the following query ensures that the target is sized correctly: -tgl=> CREATE TABLE vv (v varchar(4)); +tgl=> CREATE TABLE vv (v character(20)); CREATE tgl=> INSERT INTO vv SELECT 'abc' || 'def'; INSERT 392905 1 -tgl=> SELECT * FROM vv; - v ------- - abcd +tgl=> SELECT v, length(v) FROM vv; + v | length +----------------------+-------- + abcdef | 20 (1 row) What has really happened here is that the two unknown literals are resolved -to text by default, allowing the || operator to be -resolved as text concatenation. Then the text result of the operator -is coerced to varchar to match the target column type. (But, since the -parser knows that text and varchar are binary-compatible, this coercion -is implicit and does not insert any real function call.) Finally, the -sizing function varchar(varchar, integer) is found in the system -catalogs and applied to the operator's result and the stored column length. -This type-specific function performs the desired truncation. +to text by default, allowing the || operator +to be resolved as text concatenation. Then the text +result of the operator is coerced to bpchar (blank-padded +char, the internal name of the character datatype) to match the target +column type. (Since the parser knows that text and +bpchar are binary-compatible, this coercion is implicit and does +not insert any real function call.) Finally, the sizing function +bpchar(bpchar, integer) is found in the system catalogs +and applied to the operator's result and the stored column length. This +type-specific function performs the required length check and addition of +padding spaces. @@ -701,10 +728,13 @@ This type-specific function performs the desired truncation. <literal>UNION</> and <literal>CASE</> Constructs -The UNION and CASE constructs must match up possibly dissimilar types to -become a single result set. The resolution algorithm is applied separately to -each output column of a union. CASE uses the identical algorithm to match -up its result expressions. +SQL UNION constructs must match up possibly dissimilar types to +become a single result set. The resolution algorithm is applied separately +to each output column of a union query. The INTERSECT and +EXCEPT constructs resolve dissimilar types in the same way as +UNION. +A CASE construct also uses the identical algorithm to match up its +component expressions and select a result datatype. <literal>UNION</> and <literal>CASE</> Type Resolution @@ -768,6 +798,8 @@ tgl=> SELECT 1.2 AS "Double" UNION SELECT 1; 1.2 (2 rows) +The literal 1.2 is of type double precision, +the preferred type in the numeric category, so that type is used. @@ -776,7 +808,7 @@ tgl=> SELECT 1.2 AS "Double" UNION SELECT 1; Here the output type of the union is forced to match the type of -the first/top clause in the union: +the first clause in the union: tgl=> SELECT 1 AS "All integers"