3
3
* procedural language
4
4
*
5
5
* 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 $
7
7
*
8
8
* This software is copyrighted by Jan Wieck - Hamburg.
9
9
*
52
52
#include "utils/array.h"
53
53
#include "utils/builtins.h"
54
54
#include "utils/lsyscache.h"
55
- #include "utils/syscache.h"
56
55
57
56
58
57
static const char * const raise_skip_msg = "RAISE" ;
@@ -151,6 +150,9 @@ static void exec_eval_datum(PLpgSQL_execstate * estate,
151
150
static int exec_eval_integer (PLpgSQL_execstate * estate ,
152
151
PLpgSQL_expr * expr ,
153
152
bool * isNull );
153
+ static bool exec_eval_boolean (PLpgSQL_execstate * estate ,
154
+ PLpgSQL_expr * expr ,
155
+ bool * isNull );
154
156
static Datum exec_eval_expr (PLpgSQL_execstate * estate ,
155
157
PLpgSQL_expr * expr ,
156
158
bool * isNull ,
@@ -164,6 +166,7 @@ static void exec_move_row(PLpgSQL_execstate * estate,
164
166
static HeapTuple make_tuple_from_row (PLpgSQL_execstate * estate ,
165
167
PLpgSQL_row * row ,
166
168
TupleDesc tupdesc );
169
+ static char * convert_value_to_string (Datum value , Oid valtype );
167
170
static Datum exec_cast_value (Datum value , Oid valtype ,
168
171
Oid reqtype ,
169
172
FmgrInfo * reqinput ,
@@ -1111,14 +1114,13 @@ exec_stmt_getdiag(PLpgSQL_execstate * estate, PLpgSQL_stmt_getdiag * stmt)
1111
1114
static int
1112
1115
exec_stmt_if (PLpgSQL_execstate * estate , PLpgSQL_stmt_if * stmt )
1113
1116
{
1114
- Datum value ;
1115
- Oid valtype ;
1117
+ bool value ;
1116
1118
bool isnull = false;
1117
1119
1118
- value = exec_eval_expr (estate , stmt -> cond , & isnull , & valtype );
1120
+ value = exec_eval_boolean (estate , stmt -> cond , & isnull );
1119
1121
exec_eval_cleanup (estate );
1120
1122
1121
- if (!isnull && DatumGetBool ( value ) )
1123
+ if (!isnull && value )
1122
1124
{
1123
1125
if (stmt -> true_body != NULL )
1124
1126
return exec_stmts (estate , stmt -> true_body );
@@ -1183,16 +1185,16 @@ exec_stmt_loop(PLpgSQL_execstate * estate, PLpgSQL_stmt_loop * stmt)
1183
1185
static int
1184
1186
exec_stmt_while (PLpgSQL_execstate * estate , PLpgSQL_stmt_while * stmt )
1185
1187
{
1186
- Datum value ;
1187
- Oid valtype ;
1188
+ bool value ;
1188
1189
bool isnull = false;
1189
1190
int rc ;
1190
1191
1191
1192
for (;;)
1192
1193
{
1193
- value = exec_eval_expr (estate , stmt -> cond , & isnull , & valtype );
1194
+ value = exec_eval_boolean (estate , stmt -> cond , & isnull );
1194
1195
exec_eval_cleanup (estate );
1195
- if (isnull || !DatumGetBool (value ))
1196
+
1197
+ if (isnull || !value )
1196
1198
break ;
1197
1199
1198
1200
rc = exec_stmts (estate , stmt -> body );
@@ -1540,18 +1542,17 @@ exec_stmt_select(PLpgSQL_execstate * estate, PLpgSQL_stmt_select * stmt)
1540
1542
static int
1541
1543
exec_stmt_exit (PLpgSQL_execstate * estate , PLpgSQL_stmt_exit * stmt )
1542
1544
{
1543
- Datum value ;
1544
- Oid valtype ;
1545
- bool isnull = false;
1546
-
1547
1545
/*
1548
1546
* If the exit has a condition, check that it's true
1549
1547
*/
1550
1548
if (stmt -> cond != NULL )
1551
1549
{
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 );
1553
1554
exec_eval_cleanup (estate );
1554
- if (isnull || !DatumGetBool ( value ) )
1555
+ if (isnull || !value )
1555
1556
return PLPGSQL_RC_OK ;
1556
1557
}
1557
1558
@@ -1785,9 +1786,6 @@ exec_stmt_raise(PLpgSQL_execstate * estate, PLpgSQL_stmt_raise * stmt)
1785
1786
Oid paramtypeid ;
1786
1787
Datum paramvalue ;
1787
1788
bool paramisnull ;
1788
- HeapTuple typetup ;
1789
- Form_pg_type typeStruct ;
1790
- FmgrInfo finfo_output ;
1791
1789
char * extval ;
1792
1790
int pidx = 0 ;
1793
1791
char c [2 ] = {0 , 0 };
@@ -1822,22 +1820,7 @@ exec_stmt_raise(PLpgSQL_execstate * estate, PLpgSQL_stmt_raise * stmt)
1822
1820
if (paramisnull )
1823
1821
extval = "<NULL>" ;
1824
1822
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 );
1841
1824
plpgsql_dstring_append (& ds , extval );
1842
1825
pidx ++ ;
1843
1826
continue ;
@@ -2091,9 +2074,6 @@ exec_stmt_dynexecute(PLpgSQL_execstate * estate,
2091
2074
bool isnull = false;
2092
2075
Oid restype ;
2093
2076
char * querystr ;
2094
- HeapTuple typetup ;
2095
- Form_pg_type typeStruct ;
2096
- FmgrInfo finfo_output ;
2097
2077
int exec_res ;
2098
2078
2099
2079
/*
@@ -2106,23 +2086,9 @@ exec_stmt_dynexecute(PLpgSQL_execstate * estate,
2106
2086
(errcode (ERRCODE_NULL_VALUE_NOT_ALLOWED ),
2107
2087
errmsg ("cannot EXECUTE a null querystring" )));
2108
2088
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 );
2118
2091
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 );
2126
2092
exec_eval_cleanup (estate );
2127
2093
2128
2094
/*
@@ -2211,9 +2177,6 @@ exec_stmt_dynfors(PLpgSQL_execstate * estate, PLpgSQL_stmt_dynfors * stmt)
2211
2177
int rc = PLPGSQL_RC_OK ;
2212
2178
int i ;
2213
2179
int n ;
2214
- HeapTuple typetup ;
2215
- Form_pg_type typeStruct ;
2216
- FmgrInfo finfo_output ;
2217
2180
void * plan ;
2218
2181
Portal portal ;
2219
2182
bool found = false;
@@ -2238,23 +2201,9 @@ exec_stmt_dynfors(PLpgSQL_execstate * estate, PLpgSQL_stmt_dynfors * stmt)
2238
2201
(errcode (ERRCODE_NULL_VALUE_NOT_ALLOWED ),
2239
2202
errmsg ("cannot EXECUTE a null querystring" )));
2240
2203
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 );
2256
2206
2257
- ReleaseSysCache (typetup );
2258
2207
exec_eval_cleanup (estate );
2259
2208
2260
2209
/*
@@ -2428,9 +2377,6 @@ exec_stmt_open(PLpgSQL_execstate * estate, PLpgSQL_stmt_open * stmt)
2428
2377
Datum queryD ;
2429
2378
Oid restype ;
2430
2379
char * querystr ;
2431
- HeapTuple typetup ;
2432
- Form_pg_type typeStruct ;
2433
- FmgrInfo finfo_output ;
2434
2380
void * curplan ;
2435
2381
2436
2382
/* ----------
@@ -2445,24 +2391,9 @@ exec_stmt_open(PLpgSQL_execstate * estate, PLpgSQL_stmt_open * stmt)
2445
2391
(errcode (ERRCODE_NULL_VALUE_NOT_ALLOWED ),
2446
2392
errmsg ("cannot EXECUTE a null querystring" )));
2447
2393
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
+
2466
2397
exec_eval_cleanup (estate );
2467
2398
2468
2399
/* ----------
@@ -3131,6 +3062,28 @@ exec_eval_integer(PLpgSQL_execstate * estate,
3131
3062
return DatumGetInt32 (exprdatum );
3132
3063
}
3133
3064
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
+
3134
3087
/* ----------
3135
3088
* exec_eval_expr Evaluate an expression and return
3136
3089
* the result Datum.
@@ -3560,6 +3513,31 @@ make_tuple_from_row(PLpgSQL_execstate * estate,
3560
3513
return tuple ;
3561
3514
}
3562
3515
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
+
3563
3541
/* ----------
3564
3542
* exec_cast_value Cast a value if required
3565
3543
* ----------
@@ -3580,29 +3558,14 @@ exec_cast_value(Datum value, Oid valtype,
3580
3558
*/
3581
3559
if (valtype != reqtype || reqtypmod != -1 )
3582
3560
{
3583
- HeapTuple typetup ;
3584
- Form_pg_type typeStruct ;
3585
- FmgrInfo finfo_output ;
3586
3561
char * extval ;
3587
3562
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 );
3600
3564
value = FunctionCall3 (reqinput ,
3601
3565
CStringGetDatum (extval ),
3602
3566
ObjectIdGetDatum (reqtypelem ),
3603
3567
Int32GetDatum (reqtypmod ));
3604
3568
pfree (extval );
3605
- ReleaseSysCache (typetup );
3606
3569
}
3607
3570
}
3608
3571
@@ -3631,6 +3594,7 @@ exec_simple_cast_value(Datum value, Oid valtype,
3631
3594
FmgrInfo finfo_input ;
3632
3595
3633
3596
getTypeInputInfo (reqtype , & typInput , & typElem );
3597
+
3634
3598
fmgr_info (typInput , & finfo_input );
3635
3599
3636
3600
value = exec_cast_value (value ,
0 commit comments