diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml index 17e62744c5e7665298ab825caa78284e05fdf660..7d2b37e41d7b801b20e2e5c41a0544bef14df2ed 100644 --- a/doc/src/sgml/plpgsql.sgml +++ b/doc/src/sgml/plpgsql.sgml @@ -1,5 +1,5 @@ <!-- -$PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.68 2005/05/26 00:16:31 momjian Exp $ +$PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.69 2005/05/26 04:08:31 momjian Exp $ --> <chapter id="plpgsql"> @@ -2007,13 +2007,12 @@ END LOOP; </indexterm> <para> - Any error occurring in <application>PL/pgSQL</> sets variables - <varname>SQLSTATE</> and <varname>SQLERRM</>, and, by default, - aborts execution of the function, and indeed of the surrounding - transaction as well. You can trap errors and recover from them by - using a <command>BEGIN</> block with an <literal>EXCEPTION</> - clause. The syntax is an extension of the normal syntax for a - <command>BEGIN</> block: + By default, any error occurring in a <application>PL/pgSQL</> + function aborts execution of the function, and indeed of the + surrounding transaction as well. You can trap errors and recover + from them by using a <command>BEGIN</> block with an + <literal>EXCEPTION</> clause. The syntax is an extension of the + normal syntax for a <command>BEGIN</> block: <synopsis> <optional> <<<replaceable>label</replaceable>>> </optional> diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y index 39a7a01bebe3fc37e808fcc167de98f6bad77d0d..028323192fa394a3987afc08a182d4428afee8de 100644 --- a/src/pl/plpgsql/src/gram.y +++ b/src/pl/plpgsql/src/gram.y @@ -4,7 +4,7 @@ * procedural language * * IDENTIFICATION - * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.71 2005/05/26 03:18:53 neilc Exp $ + * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.72 2005/05/26 04:08:31 momjian Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -80,11 +80,6 @@ static void plpgsql_sql_error_callback(void *arg); int n_initvars; int *initvarnos; } declhdr; - struct - { - int sqlstate_varno; - int sqlerrm_varno; - } fict_vars; List *list; PLpgSQL_type *dtype; PLpgSQL_datum *scalar; /* a VAR, RECFIELD, or TRIGARG */ @@ -101,7 +96,6 @@ static void plpgsql_sql_error_callback(void *arg); PLpgSQL_diag_item *diagitem; } -%type <fict_vars> fict_vars_sect %type <declhdr> decl_sect %type <varname> decl_varname %type <str> decl_renname @@ -250,22 +244,19 @@ opt_semi : | ';' ; -pl_block : decl_sect fict_vars_sect K_BEGIN lno proc_sect exception_sect K_END +pl_block : decl_sect K_BEGIN lno proc_sect exception_sect K_END { PLpgSQL_stmt_block *new; new = palloc0(sizeof(PLpgSQL_stmt_block)); new->cmd_type = PLPGSQL_STMT_BLOCK; - new->lineno = $4; + new->lineno = $3; new->label = $1.label; new->n_initvars = $1.n_initvars; new->initvarnos = $1.initvarnos; - new->body = $5; - new->exceptions = $6; - - new->sqlstate_varno = $2.sqlstate_varno; - new->sqlerrm_varno = $2.sqlerrm_varno; + new->body = $4; + new->exceptions = $5; plpgsql_ns_pop(); @@ -273,20 +264,6 @@ pl_block : decl_sect fict_vars_sect K_BEGIN lno proc_sect exception_sect K_END } ; -fict_vars_sect : - { - PLpgSQL_variable *var; - - plpgsql_ns_setlocal(false); - var = plpgsql_build_variable("sqlstate", 0, - plpgsql_build_datatype(TEXTOID, -1), true); - $$.sqlstate_varno = var->dno; - var = plpgsql_build_variable("sqlerrm", 0, - plpgsql_build_datatype(TEXTOID, -1), true); - $$.sqlerrm_varno = var->dno; - plpgsql_add_initdatums(NULL); - } - ; decl_sect : opt_label { diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index c602da21601f7b196b89aa541c27324dbe3b20c3..3c6216a3e56c797ad197030bd0cd0cce618f3428 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -3,7 +3,7 @@ * procedural language * * IDENTIFICATION - * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.140 2005/05/26 03:18:53 neilc Exp $ + * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.141 2005/05/26 04:08:31 momjian Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -180,7 +180,6 @@ static Datum exec_simple_cast_value(Datum value, Oid valtype, static void exec_init_tuple_store(PLpgSQL_execstate *estate); 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); /* ---------- @@ -748,20 +747,6 @@ exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block) int i; int n; - - /* setup SQLSTATE and SQLERRM */ - PLpgSQL_var *var; - - var = (PLpgSQL_var *) (estate->datums[block->sqlstate_varno]); - var->isnull = false; - var->freeval = true; - var->value = DirectFunctionCall1(textin, CStringGetDatum("00000")); - - var = (PLpgSQL_var *) (estate->datums[block->sqlerrm_varno]); - var->isnull = false; - var->freeval = true; - var->value = DirectFunctionCall1(textin, CStringGetDatum("Successful completion")); - /* * First initialize all variables declared in this block */ @@ -777,7 +762,7 @@ exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block) if (var->freeval) { - pfree(DatumGetPointer(var->value)); + pfree((void *) (var->value)); var->freeval = false; } @@ -870,15 +855,6 @@ exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block) RollbackAndReleaseCurrentSubTransaction(); MemoryContextSwitchTo(oldcontext); CurrentResourceOwner = oldowner; - - /* set SQLSTATE and SQLERRM variables */ - var = (PLpgSQL_var *) (estate->datums[block->sqlstate_varno]); - pfree(DatumGetPointer(var->value)); - var->value = DirectFunctionCall1(textin, CStringGetDatum(unpack_sql_state(edata->sqlerrcode))); - - var = (PLpgSQL_var *) (estate->datums[block->sqlerrm_varno]); - pfree(DatumGetPointer(var->value)); - var->value = DirectFunctionCall1(textin, CStringGetDatum(edata->message)); /* * If AtEOSubXact_SPI() popped any SPI context of the subxact, @@ -943,26 +919,6 @@ exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block) return PLPGSQL_RC_OK; } -/* - * 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; -} - - /* ---------- * exec_stmts Iterate over a list of statements diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h index f3b14fdf643910d56f8edc243fc75f01a58e1bfa..17a466e01e8cd5b4b48de63c7c21f4dba8fd78c5 100644 --- a/src/pl/plpgsql/src/plpgsql.h +++ b/src/pl/plpgsql/src/plpgsql.h @@ -3,7 +3,7 @@ * procedural language * * IDENTIFICATION - * $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.59 2005/05/26 00:16:31 momjian Exp $ + * $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.60 2005/05/26 04:08:31 momjian Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -336,11 +336,9 @@ typedef struct int lineno; char *label; List *body; /* List of statements */ - List *exceptions; /* List of WHEN clauses */ - int n_initvars; - int *initvarnos; - int sqlstate_varno; - int sqlerrm_varno; + List *exceptions; /* List of WHEN clauses */ + int n_initvars; + int *initvarnos; } PLpgSQL_stmt_block; diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out index aa50550f23f4e162c222fef83726a45f3505d8e9..08fbe46b3a240f4932ff382d3370ed20f44e580d 100644 --- a/src/test/regress/expected/plpgsql.out +++ b/src/test/regress/expected/plpgsql.out @@ -2380,29 +2380,3 @@ ERROR: control reached end of function without RETURN CONTEXT: PL/pgSQL function "missing_return_expr" drop function void_return_expr(); drop function missing_return_expr(); --- test SQLSTATE and SQLERRM -create function trap_exceptions() returns void as $_$ -begin - begin - raise exception 'first exception'; - exception when others then - raise notice '% %', SQLSTATE, SQLERRM; - end; - raise notice '% %', SQLSTATE, SQLERRM; - begin - raise exception 'last exception'; - exception when others then - raise notice '% %', SQLSTATE, SQLERRM; - end; - return; -end; $_$ language plpgsql; -select trap_exceptions(); -NOTICE: P0001 first exception -NOTICE: 00000 Successful completion -NOTICE: P0001 last exception - trap_exceptions ------------------ - -(1 row) - -drop function trap_exceptions(); diff --git a/src/test/regress/sql/plpgsql.sql b/src/test/regress/sql/plpgsql.sql index 3703587ad16c1cbccfc6d8a9ce9a3c0e923de580..7ea7c8c6e0c558243f82b891059b0a77a848debf 100644 --- a/src/test/regress/sql/plpgsql.sql +++ b/src/test/regress/sql/plpgsql.sql @@ -2018,24 +2018,3 @@ select missing_return_expr(); drop function void_return_expr(); drop function missing_return_expr(); - --- test SQLSTATE and SQLERRM -create function trap_exceptions() returns void as $_$ -begin - begin - raise exception 'first exception'; - exception when others then - raise notice '% %', SQLSTATE, SQLERRM; - end; - raise notice '% %', SQLSTATE, SQLERRM; - begin - raise exception 'last exception'; - exception when others then - raise notice '% %', SQLSTATE, SQLERRM; - end; - return; -end; $_$ language plpgsql; - -select trap_exceptions(); - -drop function trap_exceptions();