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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy