@ -158,7 +158,8 @@ static bool exec_eval_simple_expr(PLpgSQL_execstate *estate,
PLpgSQL_expr * expr ,
PLpgSQL_expr * expr ,
Datum * result ,
Datum * result ,
bool * isNull ,
bool * isNull ,
Oid * rettype ) ;
Oid * rettype ,
int32 * rettypmod ) ;
static void exec_assign_expr ( PLpgSQL_execstate * estate ,
static void exec_assign_expr ( PLpgSQL_execstate * estate ,
PLpgSQL_datum * target ,
PLpgSQL_datum * target ,
@ -168,7 +169,8 @@ static void exec_assign_c_string(PLpgSQL_execstate *estate,
const char * str ) ;
const char * str ) ;
static void exec_assign_value ( PLpgSQL_execstate * estate ,
static void exec_assign_value ( PLpgSQL_execstate * estate ,
PLpgSQL_datum * target ,
PLpgSQL_datum * target ,
Datum value , Oid valtype , bool * isNull ) ;
Datum value , bool isNull ,
Oid valtype , int32 valtypmod ) ;
static void exec_eval_datum ( PLpgSQL_execstate * estate ,
static void exec_eval_datum ( PLpgSQL_execstate * estate ,
PLpgSQL_datum * datum ,
PLpgSQL_datum * datum ,
Oid * typeid ,
Oid * typeid ,
@ -184,7 +186,8 @@ static bool exec_eval_boolean(PLpgSQL_execstate *estate,
static Datum exec_eval_expr ( PLpgSQL_execstate * estate ,
static Datum exec_eval_expr ( PLpgSQL_execstate * estate ,
PLpgSQL_expr * expr ,
PLpgSQL_expr * expr ,
bool * isNull ,
bool * isNull ,
Oid * rettype ) ;
Oid * rettype ,
int32 * rettypmod ) ;
static int exec_run_select ( PLpgSQL_execstate * estate ,
static int exec_run_select ( PLpgSQL_execstate * estate ,
PLpgSQL_expr * expr , long maxtuples , Portal * portalP ) ;
PLpgSQL_expr * expr , long maxtuples , Portal * portalP ) ;
static int exec_for_query ( PLpgSQL_execstate * estate , PLpgSQL_stmt_forq * stmt ,
static int exec_for_query ( PLpgSQL_execstate * estate , PLpgSQL_stmt_forq * stmt ,
@ -208,16 +211,15 @@ static void exec_move_row_from_datum(PLpgSQL_execstate *estate,
static char * convert_value_to_string ( PLpgSQL_execstate * estate ,
static char * convert_value_to_string ( PLpgSQL_execstate * estate ,
Datum value , Oid valtype ) ;
Datum value , Oid valtype ) ;
static Datum exec_cast_value ( PLpgSQL_execstate * estate ,
static Datum exec_cast_value ( PLpgSQL_execstate * estate ,
Datum value , Oid valtype ,
Datum value , bool isnull ,
Oid reqtype ,
Oid valtype , int32 valtypmod ,
Oid reqtype , int32 reqtypmod ,
FmgrInfo * reqinput ,
FmgrInfo * reqinput ,
Oid reqtypioparam ,
Oid reqtypioparam ) ;
int32 reqtypmod ,
bool isnull ) ;
static Datum exec_simple_cast_value ( PLpgSQL_execstate * estate ,
static Datum exec_simple_cast_value ( PLpgSQL_execstate * estate ,
Datum value , Oid valtype ,
Datum value , bool isnull ,
Oid reqtype , int32 req typmod,
Oid valtype , int32 val typmod,
bool isnull ) ;
Oid reqtype , int32 reqtypmod ) ;
static void exec_init_tuple_store ( PLpgSQL_execstate * estate ) ;
static void exec_init_tuple_store ( PLpgSQL_execstate * estate ) ;
static void exec_set_found ( PLpgSQL_execstate * estate , bool state ) ;
static void exec_set_found ( PLpgSQL_execstate * estate , bool state ) ;
static void plpgsql_create_econtext ( PLpgSQL_execstate * estate ) ;
static void plpgsql_create_econtext ( PLpgSQL_execstate * estate ) ;
@ -452,12 +454,13 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo,
/* Cast value to proper type */
/* Cast value to proper type */
estate . retval = exec_cast_value ( & estate ,
estate . retval = exec_cast_value ( & estate ,
estate . retval ,
estate . retval ,
fcinfo - > isnull ,
estate . rettype ,
estate . rettype ,
- 1 ,
func - > fn_rettype ,
func - > fn_rettype ,
& ( func - > fn_retinput ) ,
func - > fn_rettypioparam ,
- 1 ,
- 1 ,
fcinfo - > isnull ) ;
& ( func - > fn_retinput ) ,
func - > fn_rettypioparam ) ;
/*
/*
* If the function ' s return type isn ' t by value , copy the value
* If the function ' s return type isn ' t by value , copy the value
@ -1077,15 +1080,13 @@ exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
* exec_assign_value . )
* exec_assign_value . )
*/
*/
if ( ! var - > datatype - > typinput . fn_strict )
if ( ! var - > datatype - > typinput . fn_strict )
{
bool valIsNull = true ;
exec_assign_value ( estate ,
exec_assign_value ( estate ,
( PLpgSQL_datum * ) var ,
( PLpgSQL_datum * ) var ,
( Datum ) 0 ,
( Datum ) 0 ,
true ,
UNKNOWNOID ,
UNKNOWNOID ,
& valIsNull ) ;
- 1 ) ;
}
if ( var - > notnull )
if ( var - > notnull )
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_NULL_VALUE_NOT_ALLOWED ) ,
( errcode ( ERRCODE_NULL_VALUE_NOT_ALLOWED ) ,
@ -1556,20 +1557,19 @@ exec_stmt_getdiag(PLpgSQL_execstate *estate, PLpgSQL_stmt_getdiag *stmt)
{
{
PLpgSQL_diag_item * diag_item = ( PLpgSQL_diag_item * ) lfirst ( lc ) ;
PLpgSQL_diag_item * diag_item = ( PLpgSQL_diag_item * ) lfirst ( lc ) ;
PLpgSQL_datum * var = estate - > datums [ diag_item - > target ] ;
PLpgSQL_datum * var = estate - > datums [ diag_item - > target ] ;
bool isnull = false ;
switch ( diag_item - > kind )
switch ( diag_item - > kind )
{
{
case PLPGSQL_GETDIAG_ROW_COUNT :
case PLPGSQL_GETDIAG_ROW_COUNT :
exec_assign_value ( estate , var ,
exec_assign_value ( estate , var ,
UInt32GetDatum ( estate - > eval_processed ) ,
UInt32GetDatum ( estate - > eval_processed ) ,
INT4OID , & isnull ) ;
false , INT4OID , - 1 ) ;
break ;
break ;
case PLPGSQL_GETDIAG_RESULT_OID :
case PLPGSQL_GETDIAG_RESULT_OID :
exec_assign_value ( estate , var ,
exec_assign_value ( estate , var ,
ObjectIdGetDatum ( estate - > eval_lastoid ) ,
ObjectIdGetDatum ( estate - > eval_lastoid ) ,
OIDOID , & isnull ) ;
false , OIDOID , - 1 ) ;
break ;
break ;
case PLPGSQL_GETDIAG_ERROR_CONTEXT :
case PLPGSQL_GETDIAG_ERROR_CONTEXT :
@ -1688,9 +1688,11 @@ exec_stmt_case(PLpgSQL_execstate *estate, PLpgSQL_stmt_case *stmt)
{
{
/* simple case */
/* simple case */
Datum t_val ;
Datum t_val ;
Oid t_oid ;
Oid t_typoid ;
int32 t_typmod ;
t_val = exec_eval_expr ( estate , stmt - > t_expr , & isnull , & t_oid ) ;
t_val = exec_eval_expr ( estate , stmt - > t_expr ,
& isnull , & t_typoid , & t_typmod ) ;
t_var = ( PLpgSQL_var * ) estate - > datums [ stmt - > t_varno ] ;
t_var = ( PLpgSQL_var * ) estate - > datums [ stmt - > t_varno ] ;
@ -1699,17 +1701,19 @@ exec_stmt_case(PLpgSQL_execstate *estate, PLpgSQL_stmt_case *stmt)
* what we ' re modifying here is an execution copy of the datum , so
* what we ' re modifying here is an execution copy of the datum , so
* this doesn ' t affect the originally stored function parse tree .
* this doesn ' t affect the originally stored function parse tree .
*/
*/
if ( t_var - > datatype - > typoid ! = t_oid )
if ( t_var - > datatype - > typoid ! = t_typoid | |
t_var - > datatype = plpgsql_build_datatype ( t_oid ,
t_var - > datatype - > atttypmod ! = t_typmod )
- 1 ,
t_var - > datatype = plpgsql_build_datatype ( t_typoid ,
t_typmod ,
estate - > func - > fn_input_collation ) ;
estate - > func - > fn_input_collation ) ;
/* now we can assign to the variable */
/* now we can assign to the variable */
exec_assign_value ( estate ,
exec_assign_value ( estate ,
( PLpgSQL_datum * ) t_var ,
( PLpgSQL_datum * ) t_var ,
t_val ,
t_val ,
t_oid ,
isnull ,
& isnull ) ;
t_typoid ,
t_typmod ) ;
exec_eval_cleanup ( estate ) ;
exec_eval_cleanup ( estate ) ;
}
}
@ -1885,6 +1889,7 @@ exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt)
Datum value ;
Datum value ;
bool isnull ;
bool isnull ;
Oid valtype ;
Oid valtype ;
int32 valtypmod ;
int32 loop_value ;
int32 loop_value ;
int32 end_value ;
int32 end_value ;
int32 step_value ;
int32 step_value ;
@ -1896,11 +1901,14 @@ exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt)
/*
/*
* Get the value of the lower bound
* Get the value of the lower bound
*/
*/
value = exec_eval_expr ( estate , stmt - > lower , & isnull , & valtype ) ;
value = exec_eval_expr ( estate , stmt - > lower ,
value = exec_cast_value ( estate , value , valtype , var - > datatype - > typoid ,
& isnull , & valtype , & valtypmod ) ;
value = exec_cast_value ( estate , value , isnull ,
valtype , valtypmod ,
var - > datatype - > typoid ,
var - > datatype - > atttypmod ,
& ( var - > datatype - > typinput ) ,
& ( var - > datatype - > typinput ) ,
var - > datatype - > typioparam ,
var - > datatype - > typioparam ) ;
var - > datatype - > atttypmod , isnull ) ;
if ( isnull )
if ( isnull )
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_NULL_VALUE_NOT_ALLOWED ) ,
( errcode ( ERRCODE_NULL_VALUE_NOT_ALLOWED ) ,
@ -1911,11 +1919,14 @@ exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt)
/*
/*
* Get the value of the upper bound
* Get the value of the upper bound
*/
*/
value = exec_eval_expr ( estate , stmt - > upper , & isnull , & valtype ) ;
value = exec_eval_expr ( estate , stmt - > upper ,
value = exec_cast_value ( estate , value , valtype , var - > datatype - > typoid ,
& isnull , & valtype , & valtypmod ) ;
value = exec_cast_value ( estate , value , isnull ,
valtype , valtypmod ,
var - > datatype - > typoid ,
var - > datatype - > atttypmod ,
& ( var - > datatype - > typinput ) ,
& ( var - > datatype - > typinput ) ,
var - > datatype - > typioparam ,
var - > datatype - > typioparam ) ;
var - > datatype - > atttypmod , isnull ) ;
if ( isnull )
if ( isnull )
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_NULL_VALUE_NOT_ALLOWED ) ,
( errcode ( ERRCODE_NULL_VALUE_NOT_ALLOWED ) ,
@ -1928,11 +1939,14 @@ exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt)
*/
*/
if ( stmt - > step )
if ( stmt - > step )
{
{
value = exec_eval_expr ( estate , stmt - > step , & isnull , & valtype ) ;
value = exec_eval_expr ( estate , stmt - > step ,
value = exec_cast_value ( estate , value , valtype , var - > datatype - > typoid ,
& isnull , & valtype , & valtypmod ) ;
value = exec_cast_value ( estate , value , isnull ,
valtype , valtypmod ,
var - > datatype - > typoid ,
var - > datatype - > atttypmod ,
& ( var - > datatype - > typinput ) ,
& ( var - > datatype - > typinput ) ,
var - > datatype - > typioparam ,
var - > datatype - > typioparam ) ;
var - > datatype - > atttypmod , isnull ) ;
if ( isnull )
if ( isnull )
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_NULL_VALUE_NOT_ALLOWED ) ,
( errcode ( ERRCODE_NULL_VALUE_NOT_ALLOWED ) ,
@ -2227,17 +2241,19 @@ exec_stmt_foreach_a(PLpgSQL_execstate *estate, PLpgSQL_stmt_foreach_a *stmt)
{
{
ArrayType * arr ;
ArrayType * arr ;
Oid arrtype ;
Oid arrtype ;
int32 arrtypmod ;
PLpgSQL_datum * loop_var ;
PLpgSQL_datum * loop_var ;
Oid loop_var_elem_type ;
Oid loop_var_elem_type ;
bool found = false ;
bool found = false ;
int rc = PLPGSQL_RC_OK ;
int rc = PLPGSQL_RC_OK ;
ArrayIterator array_iterator ;
ArrayIterator array_iterator ;
Oid iterator_result_type ;
Oid iterator_result_type ;
int32 iterator_result_typmod ;
Datum value ;
Datum value ;
bool isnull ;
bool isnull ;
/* get the value of the array expression */
/* get the value of the array expression */
value = exec_eval_expr ( estate , stmt - > expr , & isnull , & arrtype ) ;
value = exec_eval_expr ( estate , stmt - > expr , & isnull , & arrtype , & arrtypmod ) ;
if ( isnull )
if ( isnull )
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_NULL_VALUE_NOT_ALLOWED ) ,
( errcode ( ERRCODE_NULL_VALUE_NOT_ALLOWED ) ,
@ -2305,11 +2321,13 @@ exec_stmt_foreach_a(PLpgSQL_execstate *estate, PLpgSQL_stmt_foreach_a *stmt)
{
{
/* When slicing, nominal type of result is same as array type */
/* When slicing, nominal type of result is same as array type */
iterator_result_type = arrtype ;
iterator_result_type = arrtype ;
iterator_result_typmod = arrtypmod ;
}
}
else
else
{
{
/* Without slicing, results are individual array elements */
/* Without slicing, results are individual array elements */
iterator_result_type = ARR_ELEMTYPE ( arr ) ;
iterator_result_type = ARR_ELEMTYPE ( arr ) ;
iterator_result_typmod = arrtypmod ;
}
}
/* Iterate over the array elements or slices */
/* Iterate over the array elements or slices */
@ -2318,8 +2336,8 @@ exec_stmt_foreach_a(PLpgSQL_execstate *estate, PLpgSQL_stmt_foreach_a *stmt)
found = true ; /* looped at least once */
found = true ; /* looped at least once */
/* Assign current element/slice to the loop variable */
/* Assign current element/slice to the loop variable */
exec_assign_value ( estate , loop_var , value , iterator_result_type ,
exec_assign_value ( estate , loop_var , value , isnull ,
& isnull ) ;
iterator_result_type , iterator_result_typmod ) ;
/* In slice case, value is temporary; must free it to avoid leakage */
/* In slice case, value is temporary; must free it to avoid leakage */
if ( stmt - > slice > 0 )
if ( stmt - > slice > 0 )
@ -2503,9 +2521,12 @@ exec_stmt_return(PLpgSQL_execstate *estate, PLpgSQL_stmt_return *stmt)
if ( stmt - > expr ! = NULL )
if ( stmt - > expr ! = NULL )
{
{
int32 rettypmod ;
estate - > retval = exec_eval_expr ( estate , stmt - > expr ,
estate - > retval = exec_eval_expr ( estate , stmt - > expr ,
& ( estate - > retisnull ) ,
& ( estate - > retisnull ) ,
& ( estate - > rettype ) ) ;
& ( estate - > rettype ) ,
& rettypmod ) ;
if ( estate - > retistuple & & ! estate - > retisnull )
if ( estate - > retistuple & & ! estate - > retisnull )
{
{
@ -2595,10 +2616,11 @@ exec_stmt_return_next(PLpgSQL_execstate *estate,
/* coerce type if needed */
/* coerce type if needed */
retval = exec_simple_cast_value ( estate ,
retval = exec_simple_cast_value ( estate ,
retval ,
retval ,
isNull ,
var - > datatype - > typoid ,
var - > datatype - > typoid ,
var - > datatype - > atttypmod ,
tupdesc - > attrs [ 0 ] - > atttypid ,
tupdesc - > attrs [ 0 ] - > atttypid ,
tupdesc - > attrs [ 0 ] - > atttypmod ,
tupdesc - > attrs [ 0 ] - > atttypmod ) ;
isNull ) ;
tuplestore_putvalues ( estate - > tuple_store , tupdesc ,
tuplestore_putvalues ( estate - > tuple_store , tupdesc ,
& retval , & isNull ) ;
& retval , & isNull ) ;
@ -2654,11 +2676,13 @@ exec_stmt_return_next(PLpgSQL_execstate *estate,
Datum retval ;
Datum retval ;
bool isNull ;
bool isNull ;
Oid rettype ;
Oid rettype ;
int32 rettypmod ;
retval = exec_eval_expr ( estate ,
retval = exec_eval_expr ( estate ,
stmt - > expr ,
stmt - > expr ,
& isNull ,
& isNull ,
& rettype ) ;
& rettype ,
& rettypmod ) ;
if ( estate - > retistuple )
if ( estate - > retistuple )
{
{
@ -2718,10 +2742,11 @@ exec_stmt_return_next(PLpgSQL_execstate *estate,
/* coerce type if needed */
/* coerce type if needed */
retval = exec_simple_cast_value ( estate ,
retval = exec_simple_cast_value ( estate ,
retval ,
retval ,
isNull ,
rettype ,
rettype ,
rettypmod ,
tupdesc - > attrs [ 0 ] - > atttypid ,
tupdesc - > attrs [ 0 ] - > atttypid ,
tupdesc - > attrs [ 0 ] - > atttypmod ,
tupdesc - > attrs [ 0 ] - > atttypmod ) ;
isNull ) ;
tuplestore_putvalues ( estate - > tuple_store , tupdesc ,
tuplestore_putvalues ( estate - > tuple_store , tupdesc ,
& retval , & isNull ) ;
& retval , & isNull ) ;
@ -2924,6 +2949,7 @@ exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
if ( cp [ 0 ] = = ' % ' )
if ( cp [ 0 ] = = ' % ' )
{
{
Oid paramtypeid ;
Oid paramtypeid ;
int32 paramtypmod ;
Datum paramvalue ;
Datum paramvalue ;
bool paramisnull ;
bool paramisnull ;
char * extval ;
char * extval ;
@ -2942,7 +2968,8 @@ exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
paramvalue = exec_eval_expr ( estate ,
paramvalue = exec_eval_expr ( estate ,
( PLpgSQL_expr * ) lfirst ( current_param ) ,
( PLpgSQL_expr * ) lfirst ( current_param ) ,
& paramisnull ,
& paramisnull ,
& paramtypeid ) ;
& paramtypeid ,
& paramtypmod ) ;
if ( paramisnull )
if ( paramisnull )
extval = " <NULL> " ;
extval = " <NULL> " ;
@ -2972,11 +2999,13 @@ exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
Datum optionvalue ;
Datum optionvalue ;
bool optionisnull ;
bool optionisnull ;
Oid optiontypeid ;
Oid optiontypeid ;
int32 optiontypmod ;
char * extval ;
char * extval ;
optionvalue = exec_eval_expr ( estate , opt - > expr ,
optionvalue = exec_eval_expr ( estate , opt - > expr ,
& optionisnull ,
& optionisnull ,
& optiontypeid ) ;
& optiontypeid ,
& optiontypmod ) ;
if ( optionisnull )
if ( optionisnull )
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_NULL_VALUE_NOT_ALLOWED ) ,
( errcode ( ERRCODE_NULL_VALUE_NOT_ALLOWED ) ,
@ -3478,8 +3507,9 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate,
PLpgSQL_stmt_dynexecute * stmt )
PLpgSQL_stmt_dynexecute * stmt )
{
{
Datum query ;
Datum query ;
bool isnull = false ;
bool isnull ;
Oid restype ;
Oid restype ;
int32 restypmod ;
char * querystr ;
char * querystr ;
int exec_res ;
int exec_res ;
PreparedParamsData * ppd = NULL ;
PreparedParamsData * ppd = NULL ;
@ -3488,7 +3518,7 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate,
* First we evaluate the string expression after the EXECUTE keyword . Its
* First we evaluate the string expression after the EXECUTE keyword . Its
* result is the querystring we have to execute .
* result is the querystring we have to execute .
*/
*/
query = exec_eval_expr ( estate , stmt - > query , & isnull , & restype ) ;
query = exec_eval_expr ( estate , stmt - > query , & isnull , & restype , & restypmod ) ;
if ( isnull )
if ( isnull )
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_NULL_VALUE_NOT_ALLOWED ) ,
( errcode ( ERRCODE_NULL_VALUE_NOT_ALLOWED ) ,
@ -3982,11 +4012,12 @@ exec_assign_expr(PLpgSQL_execstate *estate, PLpgSQL_datum *target,
PLpgSQL_expr * expr )
PLpgSQL_expr * expr )
{
{
Datum value ;
Datum value ;
bool isnull ;
Oid valtype ;
Oid valtype ;
bool isnull = false ;
int32 valtypmod ;
value = exec_eval_expr ( estate , expr , & isnull , & valtype ) ;
value = exec_eval_expr ( estate , expr , & isnull , & valtype , & valtypmod ) ;
exec_assign_value ( estate , target , value , valtype , & isnull ) ;
exec_assign_value ( estate , target , value , isnull , valtype , valtypmod ) ;
exec_eval_cleanup ( estate ) ;
exec_eval_cleanup ( estate ) ;
}
}
@ -4002,14 +4033,13 @@ exec_assign_c_string(PLpgSQL_execstate *estate, PLpgSQL_datum *target,
const char * str )
const char * str )
{
{
text * value ;
text * value ;
bool isnull = false ;
if ( str ! = NULL )
if ( str ! = NULL )
value = cstring_to_text ( str ) ;
value = cstring_to_text ( str ) ;
else
else
value = cstring_to_text ( " " ) ;
value = cstring_to_text ( " " ) ;
exec_assign_value ( estate , target , PointerGetDatum ( value ) ,
exec_assign_value ( estate , target , PointerGetDatum ( value ) , false ,
TEXTOID , & isnull ) ;
TEXTOID , - 1 ) ;
pfree ( value ) ;
pfree ( value ) ;
}
}
@ -4025,7 +4055,8 @@ exec_assign_c_string(PLpgSQL_execstate *estate, PLpgSQL_datum *target,
static void
static void
exec_assign_value ( PLpgSQL_execstate * estate ,
exec_assign_value ( PLpgSQL_execstate * estate ,
PLpgSQL_datum * target ,
PLpgSQL_datum * target ,
Datum value , Oid valtype , bool * isNull )
Datum value , bool isNull ,
Oid valtype , int32 valtypmod )
{
{
switch ( target - > dtype )
switch ( target - > dtype )
{
{
@ -4039,14 +4070,15 @@ exec_assign_value(PLpgSQL_execstate *estate,
newvalue = exec_cast_value ( estate ,
newvalue = exec_cast_value ( estate ,
value ,
value ,
isNull ,
valtype ,
valtype ,
valtypmod ,
var - > datatype - > typoid ,
var - > datatype - > typoid ,
& ( var - > datatype - > typinput ) ,
var - > datatype - > typioparam ,
var - > datatype - > atttypmod ,
var - > datatype - > atttypmod ,
* isNull ) ;
& ( var - > datatype - > typinput ) ,
var - > datatype - > typioparam ) ;
if ( * isNull & & var - > notnull )
if ( isNull & & var - > notnull )
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_NULL_VALUE_NOT_ALLOWED ) ,
( errcode ( ERRCODE_NULL_VALUE_NOT_ALLOWED ) ,
errmsg ( " null value cannot be assigned to variable \" %s \" declared NOT NULL " ,
errmsg ( " null value cannot be assigned to variable \" %s \" declared NOT NULL " ,
@ -4057,7 +4089,7 @@ exec_assign_value(PLpgSQL_execstate *estate,
* probably in the eval_econtext ) into the procedure ' s memory
* probably in the eval_econtext ) into the procedure ' s memory
* context .
* context .
*/
*/
if ( ! var - > datatype - > typbyval & & ! * isNull )
if ( ! var - > datatype - > typbyval & & ! isNull )
newvalue = datumCopy ( newvalue ,
newvalue = datumCopy ( newvalue ,
false ,
false ,
var - > datatype - > typlen ) ;
var - > datatype - > typlen ) ;
@ -4072,8 +4104,8 @@ exec_assign_value(PLpgSQL_execstate *estate,
free_var ( var ) ;
free_var ( var ) ;
var - > value = newvalue ;
var - > value = newvalue ;
var - > isnull = * isNull ;
var - > isnull = isNull ;
if ( ! var - > datatype - > typbyval & & ! * isNull )
if ( ! var - > datatype - > typbyval & & ! isNull )
var - > freeval = true ;
var - > freeval = true ;
break ;
break ;
}
}
@ -4085,7 +4117,7 @@ exec_assign_value(PLpgSQL_execstate *estate,
*/
*/
PLpgSQL_row * row = ( PLpgSQL_row * ) target ;
PLpgSQL_row * row = ( PLpgSQL_row * ) target ;
if ( * isNull )
if ( isNull )
{
{
/* If source is null, just assign nulls to the row */
/* If source is null, just assign nulls to the row */
exec_move_row ( estate , NULL , row , NULL , NULL ) ;
exec_move_row ( estate , NULL , row , NULL , NULL ) ;
@ -4109,7 +4141,7 @@ exec_assign_value(PLpgSQL_execstate *estate,
*/
*/
PLpgSQL_rec * rec = ( PLpgSQL_rec * ) target ;
PLpgSQL_rec * rec = ( PLpgSQL_rec * ) target ;
if ( * isNull )
if ( isNull )
{
{
/* If source is null, just assign nulls to the record */
/* If source is null, just assign nulls to the record */
exec_move_row ( estate , rec , NULL , NULL , NULL ) ;
exec_move_row ( estate , rec , NULL , NULL , NULL ) ;
@ -4139,7 +4171,6 @@ exec_assign_value(PLpgSQL_execstate *estate,
Datum * values ;
Datum * values ;
bool * nulls ;
bool * nulls ;
bool * replaces ;
bool * replaces ;
bool attisnull ;
Oid atttype ;
Oid atttype ;
int32 atttypmod ;
int32 atttypmod ;
@ -4187,16 +4218,16 @@ exec_assign_value(PLpgSQL_execstate *estate,
* Now insert the new value , being careful to cast it to the
* Now insert the new value , being careful to cast it to the
* right type .
* right type .
*/
*/
atttype = SPI_gettypeid ( rec - > tupdesc , fno + 1 ) ;
atttype = rec - > tupdesc - > attrs [ fno ] - > atttypid ;
atttypmod = rec - > tupdesc - > attrs [ fno ] - > atttypmod ;
atttypmod = rec - > tupdesc - > attrs [ fno ] - > atttypmod ;
attisnull = * isNull ;
values [ fno ] = exec_simple_cast_value ( estate ,
values [ fno ] = exec_simple_cast_value ( estate ,
value ,
value ,
isNull ,
valtype ,
valtype ,
valtypmod ,
atttype ,
atttype ,
atttypmod ,
atttypmod ) ;
attisnull ) ;
nulls [ fno ] = isNull ;
nulls [ fno ] = attisnull ;
/*
/*
* Now call heap_modify_tuple ( ) to create a new tuple that
* Now call heap_modify_tuple ( ) to create a new tuple that
@ -4354,10 +4385,11 @@ exec_assign_value(PLpgSQL_execstate *estate,
/* Coerce source value to match array element type. */
/* Coerce source value to match array element type. */
coerced_value = exec_simple_cast_value ( estate ,
coerced_value = exec_simple_cast_value ( estate ,
value ,
value ,
isNull ,
valtype ,
valtype ,
valtypmod ,
arrayelem - > elemtypoid ,
arrayelem - > elemtypoid ,
arrayelem - > arraytypmod ,
arrayelem - > arraytypmod ) ;
* isNull ) ;
/*
/*
* If the original array is null , cons up an empty array so
* If the original array is null , cons up an empty array so
@ -4370,7 +4402,7 @@ exec_assign_value(PLpgSQL_execstate *estate,
* corresponds to the current behavior of ExecEvalArrayRef ( ) .
* corresponds to the current behavior of ExecEvalArrayRef ( ) .
*/
*/
if ( arrayelem - > arraytyplen > 0 & & /* fixed-length array? */
if ( arrayelem - > arraytyplen > 0 & & /* fixed-length array? */
( oldarrayisnull | | * isNull ) )
( oldarrayisnull | | isNull ) )
return ;
return ;
/* empty array, if any, and newarraydatum are short-lived */
/* empty array, if any, and newarraydatum are short-lived */
@ -4386,7 +4418,7 @@ exec_assign_value(PLpgSQL_execstate *estate,
nsubscripts ,
nsubscripts ,
subscriptvals ,
subscriptvals ,
coerced_value ,
coerced_value ,
* isNull ,
isNull ,
arrayelem - > arraytyplen ,
arrayelem - > arraytyplen ,
arrayelem - > elemtyplen ,
arrayelem - > elemtyplen ,
arrayelem - > elemtypbyval ,
arrayelem - > elemtypbyval ,
@ -4400,10 +4432,11 @@ exec_assign_value(PLpgSQL_execstate *estate,
* coercing the base array type back up to the domain will
* coercing the base array type back up to the domain will
* happen within exec_assign_value .
* happen within exec_assign_value .
*/
*/
* isNull = false ;
exec_assign_value ( estate , target ,
exec_assign_value ( estate , target ,
newarraydatum ,
newarraydatum ,
arrayelem - > arraytypoid , isNull ) ;
false ,
arrayelem - > arraytypoid ,
arrayelem - > arraytypmod ) ;
break ;
break ;
}
}
@ -4724,11 +4757,12 @@ exec_eval_integer(PLpgSQL_execstate *estate,
{
{
Datum exprdatum ;
Datum exprdatum ;
Oid exprtypeid ;
Oid exprtypeid ;
int32 exprtypmod ;
exprdatum = exec_eval_expr ( estate , expr , isNull , & exprtypeid ) ;
exprdatum = exec_eval_expr ( estate , expr , isNull , & exprtypeid , & exprtypmod ) ;
exprdatum = exec_simple_cast_value ( estate , exprdatum , exprtypeid ,
exprdatum = exec_simple_cast_value ( estate , exprdatum , * isNull ,
INT4OID , - 1 ,
exprtypeid , exprtypmod ,
* isNull ) ;
INT4OID , - 1 ) ;
return DatumGetInt32 ( exprdatum ) ;
return DatumGetInt32 ( exprdatum ) ;
}
}
@ -4746,17 +4780,18 @@ exec_eval_boolean(PLpgSQL_execstate *estate,
{
{
Datum exprdatum ;
Datum exprdatum ;
Oid exprtypeid ;
Oid exprtypeid ;
int32 exprtypmod ;
exprdatum = exec_eval_expr ( estate , expr , isNull , & exprtypeid ) ;
exprdatum = exec_eval_expr ( estate , expr , isNull , & exprtypeid , & exprtypmod ) ;
exprdatum = exec_simple_cast_value ( estate , exprdatum , exprtypeid ,
exprdatum = exec_simple_cast_value ( estate , exprdatum , * isNull ,
BOOLOID , - 1 ,
exprtypeid , exprtypmod ,
* isNull ) ;
BOOLOID , - 1 ) ;
return DatumGetBool ( exprdatum ) ;
return DatumGetBool ( exprdatum ) ;
}
}
/* ----------
/* ----------
* exec_eval_expr Evaluate an expression and return
* exec_eval_expr Evaluate an expression and return
* the result Datum .
* the result Datum , along with data type / typmod .
*
*
* NOTE : caller must do exec_eval_cleanup when done with the Datum .
* NOTE : caller must do exec_eval_cleanup when done with the Datum .
* - - - - - - - - - -
* - - - - - - - - - -
@ -4765,7 +4800,8 @@ static Datum
exec_eval_expr ( PLpgSQL_execstate * estate ,
exec_eval_expr ( PLpgSQL_execstate * estate ,
PLpgSQL_expr * expr ,
PLpgSQL_expr * expr ,
bool * isNull ,
bool * isNull ,
Oid * rettype )
Oid * rettype ,
int32 * rettypmod )
{
{
Datum result = 0 ;
Datum result = 0 ;
int rc ;
int rc ;
@ -4780,7 +4816,8 @@ exec_eval_expr(PLpgSQL_execstate *estate,
* If this is a simple expression , bypass SPI and use the executor
* If this is a simple expression , bypass SPI and use the executor
* directly
* directly
*/
*/
if ( exec_eval_simple_expr ( estate , expr , & result , isNull , rettype ) )
if ( exec_eval_simple_expr ( estate , expr ,
& result , isNull , rettype , rettypmod ) )
return result ;
return result ;
/*
/*
@ -4807,7 +4844,8 @@ exec_eval_expr(PLpgSQL_execstate *estate,
/*
/*
* . . . and get the column ' s datatype .
* . . . and get the column ' s datatype .
*/
*/
* rettype = SPI_gettypeid ( estate - > eval_tuptable - > tupdesc , 1 ) ;
* rettype = estate - > eval_tuptable - > tupdesc - > attrs [ 0 ] - > atttypid ;
* rettypmod = estate - > eval_tuptable - > tupdesc - > attrs [ 0 ] - > atttypmod ;
/*
/*
* If there are no rows selected , the result is a NULL of that type .
* If there are no rows selected , the result is a NULL of that type .
@ -5060,8 +5098,8 @@ loop_exit:
* exec_eval_simple_expr - Evaluate a simple expression returning
* exec_eval_simple_expr - Evaluate a simple expression returning
* a Datum by directly calling ExecEvalExpr ( ) .
* a Datum by directly calling ExecEvalExpr ( ) .
*
*
* If successful , store results into * result , * isNull , * rettype and return
* If successful , store results into * result , * isNull , * rettype , * rettypmod
* TRUE . If the expression cannot be handled by simple evaluation ,
* and return TRUE . If the expression cannot be handled by simple evaluation ,
* return FALSE .
* return FALSE .
*
*
* Because we only store one execution tree for a simple expression , we
* Because we only store one execution tree for a simple expression , we
@ -5092,7 +5130,8 @@ exec_eval_simple_expr(PLpgSQL_execstate *estate,
PLpgSQL_expr * expr ,
PLpgSQL_expr * expr ,
Datum * result ,
Datum * result ,
bool * isNull ,
bool * isNull ,
Oid * rettype )
Oid * rettype ,
int32 * rettypmod )
{
{
ExprContext * econtext = estate - > eval_econtext ;
ExprContext * econtext = estate - > eval_econtext ;
LocalTransactionId curlxid = MyProc - > lxid ;
LocalTransactionId curlxid = MyProc - > lxid ;
@ -5142,6 +5181,7 @@ exec_eval_simple_expr(PLpgSQL_execstate *estate,
* Pass back previously - determined result type .
* Pass back previously - determined result type .
*/
*/
* rettype = expr - > expr_simple_type ;
* rettype = expr - > expr_simple_type ;
* rettypmod = expr - > expr_simple_typmod ;
/*
/*
* Prepare the expression for execution , if it ' s not been done already in
* Prepare the expression for execution , if it ' s not been done already in
@ -5457,6 +5497,7 @@ exec_move_row(PLpgSQL_execstate *estate,
Datum value ;
Datum value ;
bool isnull ;
bool isnull ;
Oid valtype ;
Oid valtype ;
int32 valtypmod ;
if ( row - > varnos [ fnum ] < 0 )
if ( row - > varnos [ fnum ] < 0 )
continue ; /* skip dropped column in row struct */
continue ; /* skip dropped column in row struct */
@ -5475,23 +5516,20 @@ exec_move_row(PLpgSQL_execstate *estate,
value = ( Datum ) 0 ;
value = ( Datum ) 0 ;
isnull = true ;
isnull = true ;
}
}
valtype = SPI_gettypeid ( tupdesc , anum + 1 ) ;
valtype = tupdesc - > attrs [ anum ] - > atttypid ;
valtypmod = tupdesc - > attrs [ anum ] - > atttypmod ;
anum + + ;
anum + + ;
}
}
else
else
{
{
value = ( Datum ) 0 ;
value = ( Datum ) 0 ;
isnull = true ;
isnull = true ;
valtype = UNKNOWNOID ;
/*
valtypmod = - 1 ;
* InvalidOid is OK because exec_assign_value doesn ' t care
* about the type of a source NULL
*/
valtype = InvalidOid ;
}
}
exec_assign_value ( estate , ( PLpgSQL_datum * ) var ,
exec_assign_value ( estate , ( PLpgSQL_datum * ) var ,
value , valtype , & isnull ) ;
value , isnull , valtype , valtypmod ) ;
}
}
return ;
return ;
@ -5675,17 +5713,17 @@ convert_value_to_string(PLpgSQL_execstate *estate, Datum value, Oid valtype)
*/
*/
static Datum
static Datum
exec_cast_value ( PLpgSQL_execstate * estate ,
exec_cast_value ( PLpgSQL_execstate * estate ,
Datum value , Oid valtype ,
Datum value , bool isnull ,
Oid reqtype ,
Oid valtype , int32 valtypmod ,
Oid reqtype , int32 reqtypmod ,
FmgrInfo * reqinput ,
FmgrInfo * reqinput ,
Oid reqtypioparam ,
Oid reqtypioparam )
int32 reqtypmod ,
bool isnull )
{
{
/*
/*
* If the type of the given value isn ' t what ' s requested , convert it .
* If the type of the given value isn ' t what ' s requested , convert it .
*/
*/
if ( valtype ! = reqtype | | reqtypmod ! = - 1 )
if ( valtype ! = reqtype | |
( valtypmod ! = reqtypmod & & reqtypmod ! = - 1 ) )
{
{
MemoryContext oldcontext ;
MemoryContext oldcontext ;
@ -5719,11 +5757,12 @@ exec_cast_value(PLpgSQL_execstate *estate,
*/
*/
static Datum
static Datum
exec_simple_cast_value ( PLpgSQL_execstate * estate ,
exec_simple_cast_value ( PLpgSQL_execstate * estate ,
Datum value , Oid valtype ,
Datum value , bool isnull ,
Oid reqtype , int32 req typmod,
Oid valtype , int32 val typmod,
bool isnull )
Oid reqtype , int32 reqtypmod )
{
{
if ( valtype ! = reqtype | | reqtypmod ! = - 1 )
if ( valtype ! = reqtype | |
( valtypmod ! = reqtypmod & & reqtypmod ! = - 1 ) )
{
{
Oid typinput ;
Oid typinput ;
Oid typioparam ;
Oid typioparam ;
@ -5735,12 +5774,13 @@ exec_simple_cast_value(PLpgSQL_execstate *estate,
value = exec_cast_value ( estate ,
value = exec_cast_value ( estate ,
value ,
value ,
isnull ,
valtype ,
valtype ,
valtypmod ,
reqtype ,
reqtype ,
& finfo_input ,
typioparam ,
reqtypmod ,
reqtypmod ,
isnull ) ;
& finfo_input ,
typioparam ) ;
}
}
return value ;
return value ;
@ -6171,6 +6211,7 @@ exec_simple_recheck_plan(PLpgSQL_expr *expr, CachedPlan *cplan)
expr - > expr_simple_lxid = InvalidLocalTransactionId ;
expr - > expr_simple_lxid = InvalidLocalTransactionId ;
/* Also stash away the expression result type */
/* Also stash away the expression result type */
expr - > expr_simple_type = exprType ( ( Node * ) tle - > expr ) ;
expr - > expr_simple_type = exprType ( ( Node * ) tle - > expr ) ;
expr - > expr_simple_typmod = exprTypmod ( ( Node * ) tle - > expr ) ;
}
}
/* ----------
/* ----------
@ -6371,10 +6412,12 @@ exec_eval_using_params(PLpgSQL_execstate *estate, List *params)
{
{
PLpgSQL_expr * param = ( PLpgSQL_expr * ) lfirst ( lc ) ;
PLpgSQL_expr * param = ( PLpgSQL_expr * ) lfirst ( lc ) ;
bool isnull ;
bool isnull ;
int32 ppdtypmod ;
ppd - > values [ i ] = exec_eval_expr ( estate , param ,
ppd - > values [ i ] = exec_eval_expr ( estate , param ,
& isnull ,
& isnull ,
& ppd - > types [ i ] ) ;
& ppd - > types [ i ] ,
& ppdtypmod ) ;
ppd - > nulls [ i ] = isnull ? ' n ' : ' ' ;
ppd - > nulls [ i ] = isnull ? ' n ' : ' ' ;
ppd - > freevals [ i ] = false ;
ppd - > freevals [ i ] = false ;
@ -6452,13 +6495,14 @@ exec_dynquery_with_params(PLpgSQL_execstate *estate,
Datum query ;
Datum query ;
bool isnull ;
bool isnull ;
Oid restype ;
Oid restype ;
int32 restypmod ;
char * querystr ;
char * querystr ;
/*
/*
* Evaluate the string expression after the EXECUTE keyword . Its result is
* Evaluate the string expression after the EXECUTE keyword . Its result is
* the querystring we have to execute .
* the querystring we have to execute .
*/
*/
query = exec_eval_expr ( estate , dynquery , & isnull , & restype ) ;
query = exec_eval_expr ( estate , dynquery , & isnull , & restype , & restypmod ) ;
if ( isnull )
if ( isnull )
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_NULL_VALUE_NOT_ALLOWED ) ,
( errcode ( ERRCODE_NULL_VALUE_NOT_ALLOWED ) ,