Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit1345cc6

Browse files
committed
Use standard casting mechanism to convert types in plpgsql, when possible.
plpgsql's historical method for converting datatypes during assignments wasto apply the source type's output function and then the destination type'sinput function. Aside from being miserably inefficient in most cases, thismethod 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 thevalue to 4.Instead, let's convert by applying the appropriate assignment cast wheneverthere is one. To avoid breaking compatibility unnecessarily, fall back tothe 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 adifferent result than the old code in a case where the old code would nothave thrown an error. That is assignment of a boolean value to a stringvariable (type text, varchar, or bpchar); the old way gave boolean's outputrepresentation, ie 't'/'f', while the new way follows the behavior of thebool-to-text cast and so gives 'true' or 'false'. This will need to becalled out as an incompatibility in the 9.5 release notes.Aside from handling many conversion cases more sanely, this method isoften significantly faster than the old way. In part that's becauseof more effective caching of the conversion info.
1 parentb989619 commit1345cc6

File tree

5 files changed

+241
-131
lines changed

5 files changed

+241
-131
lines changed

‎doc/src/sgml/plpgsql.sgml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -881,13 +881,14 @@ PREPARE <replaceable>statement_name</>(integer, integer) AS SELECT $1 &lt; $2;
881881

882882
<para>
883883
If the expression's result data type doesn't match the variable's
884-
data type, or the variable has a specific size/precision
885-
(like <type>char(20)</type>), the result value will be implicitly
886-
converted by the <application>PL/pgSQL</application> interpreter using
887-
the result type's output-function and
888-
the variable type's input-function. Note that this could potentially
889-
result in run-time errors generated by the input function, if the
890-
string form of the result value is not acceptable to the input function.
884+
data type, the value will be coerced as though by an assignment cast
885+
(see <xref linkend="typeconv-query">). If no assignment cast is known
886+
for the pair of data types involved, the <application>PL/pgSQL</>
887+
interpreter will attempt to convert the result value textually, that is
888+
by applying the result type's output function followed by the variable
889+
type's input function. Note that this could result in run-time errors
890+
generated by the input function, if the string form of the result value
891+
is not acceptable to the input function.
891892
</para>
892893

893894
<para>

‎doc/src/sgml/typeconv.sgml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -844,9 +844,10 @@ Check for an exact match with the target.
844844

845845
<step performance="required">
846846
<para>
847-
Otherwise, try to convert the expression to the target type. This will succeed
848-
if there is a registered cast between the two types.
849-
If the expression is an unknown-type literal, the contents of
847+
Otherwise, try to convert the expression to the target type. This is possible
848+
if an <firstterm>assignment cast</> between the two types is registered in the
849+
<structname>pg_cast</> catalog (see <xref linkend="sql-createcast">).
850+
Alternatively, if the expression is an unknown-type literal, the contents of
850851
the literal string will be fed to the input conversion routine for the target
851852
type.
852853
</para>

‎src/pl/plpgsql/src/pl_comp.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -559,8 +559,6 @@ do_compile(FunctionCallInfo fcinfo,
559559
{
560560
function->fn_retbyval=typeStruct->typbyval;
561561
function->fn_rettyplen=typeStruct->typlen;
562-
function->fn_rettypioparam=getTypeIOParam(typeTup);
563-
fmgr_info(typeStruct->typinput,&(function->fn_retinput));
564562

565563
/*
566564
* install $0 reference, but only for polymorphic return
@@ -803,7 +801,6 @@ plpgsql_compile_inline(char *proc_source)
803801
char*func_name="inline_code_block";
804802
PLpgSQL_function*function;
805803
ErrorContextCallbackplerrcontext;
806-
Oidtypinput;
807804
PLpgSQL_variable*var;
808805
intparse_rc;
809806
MemoryContextfunc_cxt;
@@ -876,8 +873,6 @@ plpgsql_compile_inline(char *proc_source)
876873
/* a bit of hardwired knowledge about type VOID here */
877874
function->fn_retbyval= true;
878875
function->fn_rettyplen=sizeof(int32);
879-
getTypeInputInfo(VOIDOID,&typinput,&function->fn_rettypioparam);
880-
fmgr_info(typinput,&(function->fn_retinput));
881876

882877
/*
883878
* Remember if function is STABLE/IMMUTABLE. XXX would it be better to
@@ -2200,12 +2195,11 @@ build_datatype(HeapTuple typeTup, int32 typmod, Oid collation)
22002195
}
22012196
typ->typlen=typeStruct->typlen;
22022197
typ->typbyval=typeStruct->typbyval;
2198+
typ->typtype=typeStruct->typtype;
22032199
typ->typrelid=typeStruct->typrelid;
2204-
typ->typioparam=getTypeIOParam(typeTup);
22052200
typ->collation=typeStruct->typcollation;
22062201
if (OidIsValid(collation)&&OidIsValid(typ->collation))
22072202
typ->collation=collation;
2208-
fmgr_info(typeStruct->typinput,&(typ->typinput));
22092203
typ->atttypmod=typmod;
22102204

22112205
returntyp;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp