<!--
-$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">
</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>
* 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.
*
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 */
PLpgSQL_diag_item *diagitem;
}
-%type <fict_vars> fict_vars_sect
%type <declhdr> decl_sect
%type <varname> decl_varname
%type <str> decl_renname
| ';'
;
-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();
}
;
-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
{
* 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.
*
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);
/* ----------
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
*/
if (var->freeval)
{
- pfree(DatumGetPointer(var->value));
+ pfree((void *) (var->value));
var->freeval = false;
}
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,
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
* 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.
*
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;
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();
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();