diff -c -r --new-file pgsql.old/src/pl/plpgsql/src/pl_comp.c pgsql.new/src/pl/plpgsql/src/pl_comp.c *** pgsql.old/src/pl/plpgsql/src/pl_comp.c 2005-05-06 19:24:55.000000000 +0200 --- pgsql.new/src/pl/plpgsql/src/pl_comp.c 2005-05-30 07:41:25.000000000 +0200 *************** *** 622,634 **** function->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE); /* ! * Create the magic FOUND variable. */ var = plpgsql_build_variable("found", 0, plpgsql_build_datatype(BOOLOID, -1), true); function->found_varno = var->dno; /* * Forget about the above created variables */ --- 622,645 ---- function->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE); /* ! * Create the magic FOUND, SQLSTATE and SQLERRM variables. */ var = plpgsql_build_variable("found", 0, plpgsql_build_datatype(BOOLOID, -1), true); function->found_varno = var->dno; + var = plpgsql_build_variable("sqlstate", 0, + plpgsql_build_datatype(TEXTOID, -1), + true); + function->sqlstate_varno = var->dno; + var = plpgsql_build_variable("sqlerrm", 0, + plpgsql_build_datatype(TEXTOID, -1), + true); + function->sqlerrm_varno = var->dno; + + + /* * Forget about the above created variables */ diff -c -r --new-file pgsql.old/src/pl/plpgsql/src/pl_exec.c pgsql.new/src/pl/plpgsql/src/pl_exec.c *** pgsql.old/src/pl/plpgsql/src/pl_exec.c 2005-05-06 19:24:55.000000000 +0200 --- pgsql.new/src/pl/plpgsql/src/pl_exec.c 2005-05-30 08:55:09.000000000 +0200 *************** *** 181,186 **** --- 181,189 ---- static bool compatible_tupdesc(TupleDesc td1, TupleDesc td2); static void exec_set_found(PLpgSQL_execstate *estate, bool state); + static char *unpack_sql_state(int ssval); + static void exec_reset_sqlstate(PLpgSQL_execstate *estate, bool init); + /* ---------- * plpgsql_exec_function Called by the call handler for *************** *** 275,281 **** * Set the magic variable FOUND to false */ exec_set_found(&estate, false); ! /* * Now call the toplevel block of statements */ --- 278,284 ---- * Set the magic variable FOUND to false */ exec_set_found(&estate, false); ! exec_reset_sqlstate(&estate, true); /* * Now call the toplevel block of statements */ *************** *** 845,850 **** --- 848,854 ---- { ErrorData *edata; ListCell *e; + PLpgSQL_var *var; /* Save error info */ MemoryContextSwitchTo(oldcontext); *************** *** 855,860 **** --- 859,872 ---- RollbackAndReleaseCurrentSubTransaction(); MemoryContextSwitchTo(oldcontext); CurrentResourceOwner = oldowner; + + var = (PLpgSQL_var *) (estate->datums[estate->sqlstate_varno]); + pfree((void *) (var->value)); + var->value = DirectFunctionCall1(textin, CStringGetDatum(unpack_sql_state(edata->sqlerrcode))); + + var = (PLpgSQL_var *) (estate->datums[estate->sqlerrm_varno]); + pfree((void *) (var->value)); + var->value = DirectFunctionCall1(textin, CStringGetDatum(edata->message)); /* * If AtEOSubXact_SPI() popped any SPI context of the subxact, *************** *** 874,885 **** break; } } /* If no match found, re-throw the error */ if (e == NULL) ReThrowError(edata); else ! FreeErrorData(edata); } PG_END_TRY(); } --- 886,899 ---- break; } } + exec_reset_sqlstate(estate, false); /* Oracle comp. */ /* If no match found, re-throw the error */ if (e == NULL) ReThrowError(edata); else ! FreeErrorData(edata); ! // } PG_END_TRY(); } *************** *** 919,924 **** --- 933,964 ---- return PLPGSQL_RC_OK; } + static void + exec_reset_sqlstate(PLpgSQL_execstate *estate, bool init) + { + /* setup SQLSTATE and SQLERRM */ + PLpgSQL_var *sqlstate, *sqlerrm; + + sqlstate = (PLpgSQL_var *) (estate->datums[estate->sqlstate_varno]); + sqlerrm = (PLpgSQL_var *) (estate->datums[estate->sqlerrm_varno]); + + if (!init) + { + pfree((void *) (sqlstate->value)); + pfree((void *) (sqlerrm->value)); + } + + sqlstate->isnull = false; + sqlstate->freeval = true; + sqlstate->value = DirectFunctionCall1(textin, CStringGetDatum("00000")); + + sqlerrm->isnull = false; + sqlerrm->freeval = true; + sqlerrm->value = DirectFunctionCall1(textin, CStringGetDatum("Successful completion")); + } + + + /* ---------- * exec_stmts Iterate over a list of statements *************** *** 1993,1998 **** --- 2033,2041 ---- estate->trig_argv = NULL; estate->found_varno = func->found_varno; + estate->sqlstate_varno = func->sqlstate_varno; + estate->sqlerrm_varno = func->sqlerrm_varno; + estate->ndatums = func->ndatums; estate->datums = palloc(sizeof(PLpgSQL_datum *) * estate->ndatums); /* caller is expected to fill the datums array */ *************** *** 4318,4320 **** --- 4361,4382 ---- FreeExecutorState(simple_eval_estate); simple_eval_estate = NULL; } + + /* + * unpack MAKE_SQLSTATE code + * This code is copied from backend/utils/error/elog.c. + */ + static char * + unpack_sql_state(int ssval) + { + static char tbuf[12]; + int i; + + for (i = 0; i < 5; i++) + { + tbuf[i] = PGUNSIXBIT(ssval); + ssval >>= 6; + } + tbuf[i] = '\0'; + return tbuf; + } diff -c -r --new-file pgsql.old/src/pl/plpgsql/src/plpgsql.h pgsql.new/src/pl/plpgsql/src/plpgsql.h *** pgsql.old/src/pl/plpgsql/src/plpgsql.h 2005-04-05 08:22:16.000000000 +0200 --- pgsql.new/src/pl/plpgsql/src/plpgsql.h 2005-05-30 07:39:32.000000000 +0200 *************** *** 583,588 **** --- 583,590 ---- int tg_nargs_varno; int ndatums; + int sqlstate_varno; + int sqlerrm_varno; PLpgSQL_datum **datums; PLpgSQL_stmt_block *action; } PLpgSQL_function; *************** *** 624,629 **** --- 626,633 ---- PLpgSQL_function *err_func; /* current func */ PLpgSQL_stmt *err_stmt; /* current stmt */ const char *err_text; /* additional state info */ + int sqlstate_varno; + int sqlerrm_varno; } PLpgSQL_execstate;