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 ,
152151PLpgSQL_expr * expr ,
153152bool * 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 ,
155157PLpgSQL_expr * expr ,
156158bool * isNull ,
@@ -164,6 +166,7 @@ static void exec_move_row(PLpgSQL_execstate * estate,
164166static HeapTuple make_tuple_from_row (PLpgSQL_execstate * estate ,
165167PLpgSQL_row * row ,
166168TupleDesc tupdesc );
169+ static char * convert_value_to_string (Datum value ,Oid valtype );
167170static Datum exec_cast_value (Datum value ,Oid valtype ,
168171Oid reqtype ,
169172FmgrInfo * 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 ;
11161118bool isnull = false;
11171119
1118- value = exec_eval_expr (estate ,stmt -> cond ,& isnull , & valtype );
1120+ value = exec_eval_boolean (estate ,stmt -> cond ,& isnull );
11191121exec_eval_cleanup (estate );
11201122
1121- if (!isnull && DatumGetBool ( value ) )
1123+ if (!isnull && value )
11221124{
11231125if (stmt -> true_body != NULL )
11241126return 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 ;
11881189bool isnull = false;
11891190int rc ;
11901191
11911192for (;;)
11921193{
1193- value = exec_eval_expr (estate ,stmt -> cond ,& isnull , & valtype );
1194+ value = exec_eval_boolean (estate ,stmt -> cond ,& isnull );
11941195exec_eval_cleanup (estate );
1195- if (isnull || !DatumGetBool (value ))
1196+
1197+ if (isnull || !value )
11961198break ;
11971199
11981200rc = 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 */
15501548if (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 );
15531554exec_eval_cleanup (estate );
1554- if (isnull || !DatumGetBool ( value ) )
1555+ if (isnull || !value )
15551556return PLPGSQL_RC_OK ;
15561557}
15571558
@@ -1785,9 +1786,6 @@ exec_stmt_raise(PLpgSQL_execstate * estate, PLpgSQL_stmt_raise * stmt)
17851786Oid paramtypeid ;
17861787Datum paramvalue ;
17871788bool paramisnull ;
1788- HeapTuple typetup ;
1789- Form_pg_type typeStruct ;
1790- FmgrInfo finfo_output ;
17911789char * extval ;
17921790int pidx = 0 ;
17931791char c [2 ]= {0 ,0 };
@@ -1822,22 +1820,7 @@ exec_stmt_raise(PLpgSQL_execstate * estate, PLpgSQL_stmt_raise * stmt)
18221820if (paramisnull )
18231821extval = "<NULL>" ;
18241822else
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 );
18411824plpgsql_dstring_append (& ds ,extval );
18421825pidx ++ ;
18431826continue ;
@@ -2091,9 +2074,6 @@ exec_stmt_dynexecute(PLpgSQL_execstate * estate,
20912074bool isnull = false;
20922075Oid restype ;
20932076char * querystr ;
2094- HeapTuple typetup ;
2095- Form_pg_type typeStruct ;
2096- FmgrInfo finfo_output ;
20972077int exec_res ;
20982078
20992079/*
@@ -2106,23 +2086,9 @@ exec_stmt_dynexecute(PLpgSQL_execstate * estate,
21062086(errcode (ERRCODE_NULL_VALUE_NOT_ALLOWED ),
21072087errmsg ("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 );
21262092exec_eval_cleanup (estate );
21272093
21282094/*
@@ -2211,9 +2177,6 @@ exec_stmt_dynfors(PLpgSQL_execstate * estate, PLpgSQL_stmt_dynfors * stmt)
22112177int rc = PLPGSQL_RC_OK ;
22122178int i ;
22132179int n ;
2214- HeapTuple typetup ;
2215- Form_pg_type typeStruct ;
2216- FmgrInfo finfo_output ;
22172180void * plan ;
22182181Portal portal ;
22192182bool found = false;
@@ -2238,23 +2201,9 @@ exec_stmt_dynfors(PLpgSQL_execstate * estate, PLpgSQL_stmt_dynfors * stmt)
22382201(errcode (ERRCODE_NULL_VALUE_NOT_ALLOWED ),
22392202errmsg ("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 );
22582207exec_eval_cleanup (estate );
22592208
22602209/*
@@ -2428,9 +2377,6 @@ exec_stmt_open(PLpgSQL_execstate * estate, PLpgSQL_stmt_open * stmt)
24282377Datum queryD ;
24292378Oid restype ;
24302379char * querystr ;
2431- HeapTuple typetup ;
2432- Form_pg_type typeStruct ;
2433- FmgrInfo finfo_output ;
24342380void * curplan ;
24352381
24362382/* ----------
@@ -2445,24 +2391,9 @@ exec_stmt_open(PLpgSQL_execstate * estate, PLpgSQL_stmt_open * stmt)
24452391(errcode (ERRCODE_NULL_VALUE_NOT_ALLOWED ),
24462392errmsg ("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+
24662397exec_eval_cleanup (estate );
24672398
24682399/* ----------
@@ -3131,6 +3062,28 @@ exec_eval_integer(PLpgSQL_execstate * estate,
31313062return DatumGetInt32 (exprdatum );
31323063}
31333064
3065+ /* ----------
3066+ * exec_eval_booleanEvaluate 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_exprEvaluate an expression and return
31363089 *the result Datum.
@@ -3560,6 +3513,31 @@ make_tuple_from_row(PLpgSQL_execstate * estate,
35603513return tuple ;
35613514}
35623515
3516+ /* ----------
3517+ * convert_value_to_stringConvert 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_valueCast a value if required
35653543 * ----------
@@ -3580,29 +3558,14 @@ exec_cast_value(Datum value, Oid valtype,
35803558 */
35813559if (valtype != reqtype || reqtypmod != -1 )
35823560{
3583- HeapTuple typetup ;
3584- Form_pg_type typeStruct ;
3585- FmgrInfo finfo_output ;
35863561char * 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 );
36003564value = FunctionCall3 (reqinput ,
36013565CStringGetDatum (extval ),
36023566ObjectIdGetDatum (reqtypelem ),
36033567Int32GetDatum (reqtypmod ));
36043568pfree (extval );
3605- ReleaseSysCache (typetup );
36063569}
36073570}
36083571
@@ -3631,6 +3594,7 @@ exec_simple_cast_value(Datum value, Oid valtype,
36313594FmgrInfo finfo_input ;
36323595
36333596getTypeInputInfo (reqtype ,& typInput ,& typElem );
3597+
36343598fmgr_info (typInput ,& finfo_input );
36353599
36363600value = exec_cast_value (value ,