Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 04b4092

Browse files
committed
Add code to check that IF/WHILE/EXIT test expressions are boolean,
and try to coerce the values to boolean if not. Per recent discussions.
1 parent 55d85f4 commit 04b4092

File tree

1 file changed

+74
-110
lines changed

1 file changed

+74
-110
lines changed

src/pl/plpgsql/src/pl_exec.c

Lines changed: 74 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
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
*
@@ -52,7 +52,6 @@
5252
#include "utils/array.h"
5353
#include "utils/builtins.h"
5454
#include "utils/lsyscache.h"
55-
#include "utils/syscache.h"
5655

5756

5857
static const char *const raise_skip_msg = "RAISE";
@@ -151,6 +150,9 @@ static void exec_eval_datum(PLpgSQL_execstate * estate,
151150
static 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);
154156
static 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,
164166
static 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);
167170
static 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)
11111114
static int
11121115
exec_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)
11831185
static int
11841186
exec_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)
15401542
static int
15411543
exec_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

Comments
 (0)