33 * procedural language
44 *
55 * IDENTIFICATION
6- * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.92 2003/09/28 23:37:45 tgl Exp $
6+ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.93 2003/10/01 21:47:42 tgl Exp $
77 *
88 * This software is copyrighted by Jan Wieck - Hamburg.
99 *
5252#include "utils/array.h"
5353#include "utils/builtins.h"
5454#include "utils/lsyscache.h"
55- #include "utils/syscache.h"
5655
5756
5857static const char * const raise_skip_msg = "RAISE" ;
@@ -151,6 +150,9 @@ static void exec_eval_datum(PLpgSQL_execstate * estate,
151150static int exec_eval_integer (PLpgSQL_execstate * estate ,
152151 PLpgSQL_expr * expr ,
153152 bool * isNull );
153+ static bool exec_eval_boolean (PLpgSQL_execstate * estate ,
154+ PLpgSQL_expr * expr ,
155+ bool * isNull );
154156static Datum exec_eval_expr (PLpgSQL_execstate * estate ,
155157 PLpgSQL_expr * expr ,
156158 bool * isNull ,
@@ -164,6 +166,7 @@ static void exec_move_row(PLpgSQL_execstate * estate,
164166static HeapTuple make_tuple_from_row (PLpgSQL_execstate * estate ,
165167 PLpgSQL_row * row ,
166168 TupleDesc tupdesc );
169+ static char * convert_value_to_string (Datum value , Oid valtype );
167170static Datum exec_cast_value (Datum value , Oid valtype ,
168171 Oid reqtype ,
169172 FmgrInfo * reqinput ,
@@ -1111,14 +1114,13 @@ exec_stmt_getdiag(PLpgSQL_execstate * estate, PLpgSQL_stmt_getdiag * stmt)
11111114static int
11121115exec_stmt_if (PLpgSQL_execstate * estate , PLpgSQL_stmt_if * stmt )
11131116{
1114- Datum value ;
1115- Oid valtype ;
1117+ bool value ;
11161118 bool isnull = false;
11171119
1118- value = exec_eval_expr (estate , stmt -> cond , & isnull , & valtype );
1120+ value = exec_eval_boolean (estate , stmt -> cond , & isnull );
11191121 exec_eval_cleanup (estate );
11201122
1121- if (!isnull && DatumGetBool ( value ) )
1123+ if (!isnull && value )
11221124 {
11231125 if (stmt -> true_body != NULL )
11241126 return exec_stmts (estate , stmt -> true_body );
@@ -1183,16 +1185,16 @@ exec_stmt_loop(PLpgSQL_execstate * estate, PLpgSQL_stmt_loop * stmt)
11831185static int
11841186exec_stmt_while (PLpgSQL_execstate * estate , PLpgSQL_stmt_while * stmt )
11851187{
1186- Datum value ;
1187- Oid valtype ;
1188+ bool value ;
11881189 bool isnull = false;
11891190 int rc ;
11901191
11911192 for (;;)
11921193 {
1193- value = exec_eval_expr (estate , stmt -> cond , & isnull , & valtype );
1194+ value = exec_eval_boolean (estate , stmt -> cond , & isnull );
11941195 exec_eval_cleanup (estate );
1195- if (isnull || !DatumGetBool (value ))
1196+
1197+ if (isnull || !value )
11961198 break ;
11971199
11981200 rc = exec_stmts (estate , stmt -> body );
@@ -1540,18 +1542,17 @@ exec_stmt_select(PLpgSQL_execstate * estate, PLpgSQL_stmt_select * stmt)
15401542static int
15411543exec_stmt_exit (PLpgSQL_execstate * estate , PLpgSQL_stmt_exit * stmt )
15421544{
1543- Datum value ;
1544- Oid valtype ;
1545- bool isnull = false;
1546-
15471545 /*
15481546 * If the exit has a condition, check that it's true
15491547 */
15501548 if (stmt -> cond != NULL )
15511549 {
1552- value = exec_eval_expr (estate , stmt -> cond , & isnull , & valtype );
1550+ bool value ;
1551+ bool isnull = false;
1552+
1553+ value = exec_eval_boolean (estate , stmt -> cond , & isnull );
15531554 exec_eval_cleanup (estate );
1554- if (isnull || !DatumGetBool ( value ) )
1555+ if (isnull || !value )
15551556 return PLPGSQL_RC_OK ;
15561557 }
15571558
@@ -1785,9 +1786,6 @@ exec_stmt_raise(PLpgSQL_execstate * estate, PLpgSQL_stmt_raise * stmt)
17851786 Oid paramtypeid ;
17861787 Datum paramvalue ;
17871788 bool paramisnull ;
1788- HeapTuple typetup ;
1789- Form_pg_type typeStruct ;
1790- FmgrInfo finfo_output ;
17911789 char * extval ;
17921790 int pidx = 0 ;
17931791 char c [2 ] = {0 , 0 };
@@ -1822,22 +1820,7 @@ exec_stmt_raise(PLpgSQL_execstate * estate, PLpgSQL_stmt_raise * stmt)
18221820 if (paramisnull )
18231821 extval = "<NULL>" ;
18241822 else
1825- {
1826- typetup = SearchSysCache (TYPEOID ,
1827- ObjectIdGetDatum (paramtypeid ),
1828- 0 , 0 , 0 );
1829- if (!HeapTupleIsValid (typetup ))
1830- elog (ERROR , "cache lookup failed for type %u" ,
1831- paramtypeid );
1832- typeStruct = (Form_pg_type ) GETSTRUCT (typetup );
1833-
1834- fmgr_info (typeStruct -> typoutput , & finfo_output );
1835- extval = DatumGetCString (FunctionCall3 (& finfo_output ,
1836- paramvalue ,
1837- ObjectIdGetDatum (typeStruct -> typelem ),
1838- Int32GetDatum (-1 )));
1839- ReleaseSysCache (typetup );
1840- }
1823+ extval = convert_value_to_string (paramvalue , paramtypeid );
18411824 plpgsql_dstring_append (& ds , extval );
18421825 pidx ++ ;
18431826 continue ;
@@ -2091,9 +2074,6 @@ exec_stmt_dynexecute(PLpgSQL_execstate * estate,
20912074 bool isnull = false;
20922075 Oid restype ;
20932076 char * querystr ;
2094- HeapTuple typetup ;
2095- Form_pg_type typeStruct ;
2096- FmgrInfo finfo_output ;
20972077 int exec_res ;
20982078
20992079 /*
@@ -2106,23 +2086,9 @@ exec_stmt_dynexecute(PLpgSQL_execstate * estate,
21062086 (errcode (ERRCODE_NULL_VALUE_NOT_ALLOWED ),
21072087 errmsg ("cannot EXECUTE a null querystring" )));
21082088
2109- /*
2110- * Get the C-String representation.
2111- */
2112- typetup = SearchSysCache (TYPEOID ,
2113- ObjectIdGetDatum (restype ),
2114- 0 , 0 , 0 );
2115- if (!HeapTupleIsValid (typetup ))
2116- elog (ERROR , "cache lookup failed for type %u" , restype );
2117- typeStruct = (Form_pg_type ) GETSTRUCT (typetup );
2089+ /* Get the C-String representation */
2090+ querystr = convert_value_to_string (query , restype );
21182091
2119- fmgr_info (typeStruct -> typoutput , & finfo_output );
2120- querystr = DatumGetCString (FunctionCall3 (& finfo_output ,
2121- query ,
2122- ObjectIdGetDatum (typeStruct -> typelem ),
2123- Int32GetDatum (-1 )));
2124-
2125- ReleaseSysCache (typetup );
21262092 exec_eval_cleanup (estate );
21272093
21282094 /*
@@ -2211,9 +2177,6 @@ exec_stmt_dynfors(PLpgSQL_execstate * estate, PLpgSQL_stmt_dynfors * stmt)
22112177 int rc = PLPGSQL_RC_OK ;
22122178 int i ;
22132179 int n ;
2214- HeapTuple typetup ;
2215- Form_pg_type typeStruct ;
2216- FmgrInfo finfo_output ;
22172180 void * plan ;
22182181 Portal portal ;
22192182 bool found = false;
@@ -2238,23 +2201,9 @@ exec_stmt_dynfors(PLpgSQL_execstate * estate, PLpgSQL_stmt_dynfors * stmt)
22382201 (errcode (ERRCODE_NULL_VALUE_NOT_ALLOWED ),
22392202 errmsg ("cannot EXECUTE a null querystring" )));
22402203
2241- /*
2242- * Get the C-String representation.
2243- */
2244- typetup = SearchSysCache (TYPEOID ,
2245- ObjectIdGetDatum (restype ),
2246- 0 , 0 , 0 );
2247- if (!HeapTupleIsValid (typetup ))
2248- elog (ERROR , "cache lookup failed for type %u" , restype );
2249- typeStruct = (Form_pg_type ) GETSTRUCT (typetup );
2250-
2251- fmgr_info (typeStruct -> typoutput , & finfo_output );
2252- querystr = DatumGetCString (FunctionCall3 (& finfo_output ,
2253- query ,
2254- ObjectIdGetDatum (typeStruct -> typelem ),
2255- Int32GetDatum (-1 )));
2204+ /* Get the C-String representation */
2205+ querystr = convert_value_to_string (query , restype );
22562206
2257- ReleaseSysCache (typetup );
22582207 exec_eval_cleanup (estate );
22592208
22602209 /*
@@ -2428,9 +2377,6 @@ exec_stmt_open(PLpgSQL_execstate * estate, PLpgSQL_stmt_open * stmt)
24282377 Datum queryD ;
24292378 Oid restype ;
24302379 char * querystr ;
2431- HeapTuple typetup ;
2432- Form_pg_type typeStruct ;
2433- FmgrInfo finfo_output ;
24342380 void * curplan ;
24352381
24362382 /* ----------
@@ -2445,24 +2391,9 @@ exec_stmt_open(PLpgSQL_execstate * estate, PLpgSQL_stmt_open * stmt)
24452391 (errcode (ERRCODE_NULL_VALUE_NOT_ALLOWED ),
24462392 errmsg ("cannot EXECUTE a null querystring" )));
24472393
2448- /* ----------
2449- * Get the C-String representation.
2450- * ----------
2451- */
2452- typetup = SearchSysCache (TYPEOID ,
2453- ObjectIdGetDatum (restype ),
2454- 0 , 0 , 0 );
2455- if (!HeapTupleIsValid (typetup ))
2456- elog (ERROR , "cache lookup failed for type %u" , restype );
2457- typeStruct = (Form_pg_type ) GETSTRUCT (typetup );
2458-
2459- fmgr_info (typeStruct -> typoutput , & finfo_output );
2460- querystr = DatumGetCString (FunctionCall3 (& finfo_output ,
2461- queryD ,
2462- ObjectIdGetDatum (typeStruct -> typelem ),
2463- Int32GetDatum (-1 )));
2464-
2465- ReleaseSysCache (typetup );
2394+ /* Get the C-String representation */
2395+ querystr = convert_value_to_string (queryD , restype );
2396+
24662397 exec_eval_cleanup (estate );
24672398
24682399 /* ----------
@@ -3131,6 +3062,28 @@ exec_eval_integer(PLpgSQL_execstate * estate,
31313062 return DatumGetInt32 (exprdatum );
31323063}
31333064
3065+ /* ----------
3066+ * exec_eval_boolean Evaluate an expression, coerce result to bool
3067+ *
3068+ * Note we do not do exec_eval_cleanup here; the caller must do it at
3069+ * some later point.
3070+ * ----------
3071+ */
3072+ static bool
3073+ exec_eval_boolean (PLpgSQL_execstate * estate ,
3074+ PLpgSQL_expr * expr ,
3075+ bool * isNull )
3076+ {
3077+ Datum exprdatum ;
3078+ Oid exprtypeid ;
3079+
3080+ exprdatum = exec_eval_expr (estate , expr , isNull , & exprtypeid );
3081+ exprdatum = exec_simple_cast_value (exprdatum , exprtypeid ,
3082+ BOOLOID , -1 ,
3083+ isNull );
3084+ return DatumGetBool (exprdatum );
3085+ }
3086+
31343087/* ----------
31353088 * exec_eval_expr Evaluate an expression and return
31363089 * the result Datum.
@@ -3560,6 +3513,31 @@ make_tuple_from_row(PLpgSQL_execstate * estate,
35603513 return tuple ;
35613514}
35623515
3516+ /* ----------
3517+ * convert_value_to_string Convert a non-null Datum to C string
3518+ *
3519+ * Note: callers generally assume that the result is a palloc'd string and
3520+ * should be pfree'd. This is not all that safe an assumption ...
3521+ * ----------
3522+ */
3523+ static char *
3524+ convert_value_to_string (Datum value , Oid valtype )
3525+ {
3526+ Oid typOutput ;
3527+ Oid typElem ;
3528+ bool typIsVarlena ;
3529+ FmgrInfo finfo_output ;
3530+
3531+ getTypeOutputInfo (valtype , & typOutput , & typElem , & typIsVarlena );
3532+
3533+ fmgr_info (typOutput , & finfo_output );
3534+
3535+ return DatumGetCString (FunctionCall3 (& finfo_output ,
3536+ value ,
3537+ ObjectIdGetDatum (typElem ),
3538+ Int32GetDatum (-1 )));
3539+ }
3540+
35633541/* ----------
35643542 * exec_cast_value Cast a value if required
35653543 * ----------
@@ -3580,29 +3558,14 @@ exec_cast_value(Datum value, Oid valtype,
35803558 */
35813559 if (valtype != reqtype || reqtypmod != -1 )
35823560 {
3583- HeapTuple typetup ;
3584- Form_pg_type typeStruct ;
3585- FmgrInfo finfo_output ;
35863561 char * extval ;
35873562
3588- typetup = SearchSysCache (TYPEOID ,
3589- ObjectIdGetDatum (valtype ),
3590- 0 , 0 , 0 );
3591- if (!HeapTupleIsValid (typetup ))
3592- elog (ERROR , "cache lookup failed for type %u" , valtype );
3593- typeStruct = (Form_pg_type ) GETSTRUCT (typetup );
3594-
3595- fmgr_info (typeStruct -> typoutput , & finfo_output );
3596- extval = DatumGetCString (FunctionCall3 (& finfo_output ,
3597- value ,
3598- ObjectIdGetDatum (typeStruct -> typelem ),
3599- Int32GetDatum (-1 )));
3563+ extval = convert_value_to_string (value , valtype );
36003564 value = FunctionCall3 (reqinput ,
36013565 CStringGetDatum (extval ),
36023566 ObjectIdGetDatum (reqtypelem ),
36033567 Int32GetDatum (reqtypmod ));
36043568 pfree (extval );
3605- ReleaseSysCache (typetup );
36063569 }
36073570 }
36083571
@@ -3631,6 +3594,7 @@ exec_simple_cast_value(Datum value, Oid valtype,
36313594 FmgrInfo finfo_input ;
36323595
36333596 getTypeInputInfo (reqtype , & typInput , & typElem );
3597+
36343598 fmgr_info (typInput , & finfo_input );
36353599
36363600 value = exec_cast_value (value ,
0 commit comments