|
|
|
|
@ -153,6 +153,8 @@ static int exec_stmt_return_query(PLpgSQL_execstate *estate, |
|
|
|
|
PLpgSQL_stmt_return_query *stmt); |
|
|
|
|
static int exec_stmt_raise(PLpgSQL_execstate *estate, |
|
|
|
|
PLpgSQL_stmt_raise *stmt); |
|
|
|
|
static int exec_stmt_assert(PLpgSQL_execstate *estate, |
|
|
|
|
PLpgSQL_stmt_assert *stmt); |
|
|
|
|
static int exec_stmt_execsql(PLpgSQL_execstate *estate, |
|
|
|
|
PLpgSQL_stmt_execsql *stmt); |
|
|
|
|
static int exec_stmt_dynexecute(PLpgSQL_execstate *estate, |
|
|
|
|
@ -363,8 +365,8 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo, |
|
|
|
|
estate.err_text = NULL; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Provide a more helpful message if a CONTINUE or RAISE has been used |
|
|
|
|
* outside the context it can work in. |
|
|
|
|
* Provide a more helpful message if a CONTINUE has been used outside |
|
|
|
|
* the context it can work in. |
|
|
|
|
*/ |
|
|
|
|
if (rc == PLPGSQL_RC_CONTINUE) |
|
|
|
|
ereport(ERROR, |
|
|
|
|
@ -730,8 +732,8 @@ plpgsql_exec_trigger(PLpgSQL_function *func, |
|
|
|
|
estate.err_text = NULL; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Provide a more helpful message if a CONTINUE or RAISE has been used |
|
|
|
|
* outside the context it can work in. |
|
|
|
|
* Provide a more helpful message if a CONTINUE has been used outside |
|
|
|
|
* the context it can work in. |
|
|
|
|
*/ |
|
|
|
|
if (rc == PLPGSQL_RC_CONTINUE) |
|
|
|
|
ereport(ERROR, |
|
|
|
|
@ -862,8 +864,8 @@ plpgsql_exec_event_trigger(PLpgSQL_function *func, EventTriggerData *trigdata) |
|
|
|
|
estate.err_text = NULL; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Provide a more helpful message if a CONTINUE or RAISE has been used |
|
|
|
|
* outside the context it can work in. |
|
|
|
|
* Provide a more helpful message if a CONTINUE has been used outside |
|
|
|
|
* the context it can work in. |
|
|
|
|
*/ |
|
|
|
|
if (rc == PLPGSQL_RC_CONTINUE) |
|
|
|
|
ereport(ERROR, |
|
|
|
|
@ -1027,12 +1029,14 @@ exception_matches_conditions(ErrorData *edata, PLpgSQL_condition *cond) |
|
|
|
|
int sqlerrstate = cond->sqlerrstate; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* OTHERS matches everything *except* query-canceled; if you're |
|
|
|
|
* foolish enough, you can match that explicitly. |
|
|
|
|
* OTHERS matches everything *except* query-canceled and |
|
|
|
|
* assert-failure. If you're foolish enough, you can match those |
|
|
|
|
* explicitly. |
|
|
|
|
*/ |
|
|
|
|
if (sqlerrstate == 0) |
|
|
|
|
{ |
|
|
|
|
if (edata->sqlerrcode != ERRCODE_QUERY_CANCELED) |
|
|
|
|
if (edata->sqlerrcode != ERRCODE_QUERY_CANCELED && |
|
|
|
|
edata->sqlerrcode != ERRCODE_ASSERT_FAILURE) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
/* Exact match? */ |
|
|
|
|
@ -1471,6 +1475,10 @@ exec_stmt(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt) |
|
|
|
|
rc = exec_stmt_raise(estate, (PLpgSQL_stmt_raise *) stmt); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case PLPGSQL_STMT_ASSERT: |
|
|
|
|
rc = exec_stmt_assert(estate, (PLpgSQL_stmt_assert *) stmt); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case PLPGSQL_STMT_EXECSQL: |
|
|
|
|
rc = exec_stmt_execsql(estate, (PLpgSQL_stmt_execsql *) stmt); |
|
|
|
|
break; |
|
|
|
|
@ -3117,6 +3125,48 @@ exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt) |
|
|
|
|
return PLPGSQL_RC_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
|
* exec_stmt_assert Assert statement |
|
|
|
|
* ---------- |
|
|
|
|
*/ |
|
|
|
|
static int |
|
|
|
|
exec_stmt_assert(PLpgSQL_execstate *estate, PLpgSQL_stmt_assert *stmt) |
|
|
|
|
{ |
|
|
|
|
bool value; |
|
|
|
|
bool isnull; |
|
|
|
|
|
|
|
|
|
/* do nothing when asserts are not enabled */ |
|
|
|
|
if (!plpgsql_check_asserts) |
|
|
|
|
return PLPGSQL_RC_OK; |
|
|
|
|
|
|
|
|
|
value = exec_eval_boolean(estate, stmt->cond, &isnull); |
|
|
|
|
exec_eval_cleanup(estate); |
|
|
|
|
|
|
|
|
|
if (isnull || !value) |
|
|
|
|
{ |
|
|
|
|
char *message = NULL; |
|
|
|
|
|
|
|
|
|
if (stmt->message != NULL) |
|
|
|
|
{ |
|
|
|
|
Datum val; |
|
|
|
|
Oid typeid; |
|
|
|
|
int32 typmod; |
|
|
|
|
|
|
|
|
|
val = exec_eval_expr(estate, stmt->message, |
|
|
|
|
&isnull, &typeid, &typmod); |
|
|
|
|
if (!isnull) |
|
|
|
|
message = convert_value_to_string(estate, val, typeid); |
|
|
|
|
/* we mustn't do exec_eval_cleanup here */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ereport(ERROR, |
|
|
|
|
(errcode(ERRCODE_ASSERT_FAILURE), |
|
|
|
|
message ? errmsg_internal("%s", message) : |
|
|
|
|
errmsg("assertion failed"))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return PLPGSQL_RC_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
|
* Initialize a mostly empty execution state |
|
|
|
|
|