1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-30 11:03:19 +03:00

Use standard casting mechanism to convert types in plpgsql, when possible.

plpgsql's historical method for converting datatypes during assignments was
to apply the source type's output function and then the destination type's
input function.  Aside from being miserably inefficient in most cases, this
method failed outright in many cases where a user might expect it to work;
an example is that "declare x int; ... x := 3.9;" would fail, not round the
value to 4.

Instead, let's convert by applying the appropriate assignment cast whenever
there is one.  To avoid breaking compatibility unnecessarily, fall back to
the I/O conversion method if there is no assignment cast.

So far as I can tell, there is just one case where this method produces a
different result than the old code in a case where the old code would not
have thrown an error.  That is assignment of a boolean value to a string
variable (type text, varchar, or bpchar); the old way gave boolean's output
representation, ie 't'/'f', while the new way follows the behavior of the
bool-to-text cast and so gives 'true' or 'false'.  This will need to be
called out as an incompatibility in the 9.5 release notes.

Aside from handling many conversion cases more sanely, this method is
often significantly faster than the old way.  In part that's because
of more effective caching of the conversion info.
This commit is contained in:
Tom Lane
2015-03-04 11:04:30 -05:00
parent b9896198cf
commit 1345cc67bb
5 changed files with 240 additions and 130 deletions

View File

@ -881,13 +881,14 @@ PREPARE <replaceable>statement_name</>(integer, integer) AS SELECT $1 &lt; $2;
<para>
If the expression's result data type doesn't match the variable's
data type, or the variable has a specific size/precision
(like <type>char(20)</type>), the result value will be implicitly
converted by the <application>PL/pgSQL</application> interpreter using
the result type's output-function and
the variable type's input-function. Note that this could potentially
result in run-time errors generated by the input function, if the
string form of the result value is not acceptable to the input function.
data type, the value will be coerced as though by an assignment cast
(see <xref linkend="typeconv-query">). If no assignment cast is known
for the pair of data types involved, the <application>PL/pgSQL</>
interpreter will attempt to convert the result value textually, that is
by applying the result type's output function followed by the variable
type's input function. Note that this could result in run-time errors
generated by the input function, if the string form of the result value
is not acceptable to the input function.
</para>
<para>

View File

@ -844,9 +844,10 @@ Check for an exact match with the target.
<step performance="required">
<para>
Otherwise, try to convert the expression to the target type. This will succeed
if there is a registered cast between the two types.
If the expression is an unknown-type literal, the contents of
Otherwise, try to convert the expression to the target type. This is possible
if an <firstterm>assignment cast</> between the two types is registered in the
<structname>pg_cast</> catalog (see <xref linkend="sql-createcast">).
Alternatively, if the expression is an unknown-type literal, the contents of
the literal string will be fed to the input conversion routine for the target
type.
</para>