-<!-- $PostgreSQL: pgsql/doc/src/sgml/errcodes.sgml,v 1.6 2004/05/16 23:18:52 neilc Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/errcodes.sgml,v 1.7 2004/07/31 23:04:54 tgl Exp $ -->
<appendix id="errcodes-appendix">
<title><productname>PostgreSQL</productname> Error Codes</title>
within the class but do not have any more-specific code assigned.
</para>
+ <para>
+ The <application>PL/pgSQL</> condition name for each error code is the
+ same as the phrase shown in the table, with underscores substituted
+ for spaces. For example, code <literal>22012</>, DIVISION BY ZERO,
+ has condition name <literal>DIVISION_BY_ZERO</>. Condition names can
+ be written in either upper or lower case.
+ </para>
+
<!--
The following table should correspond to the contents of
- src/include/utils/errcodes.h.
+ src/include/utils/errcodes.h and src/pl/plpgsql/src/plerrcodes.h.
-->
<table id="errcodes-table">
<row>
<entry><literal>0100C</literal></entry>
-<entry>WARNING DYNAMIC RESULT SETS RETURNED</entry>
+<entry>DYNAMIC RESULT SETS RETURNED</entry>
</row>
<row>
<entry><literal>01008</literal></entry>
-<entry>WARNING IMPLICIT ZERO BIT PADDING</entry>
+<entry>IMPLICIT ZERO BIT PADDING</entry>
</row>
<row>
<entry><literal>01003</literal></entry>
-<entry>WARNING NULL VALUE ELIMINATED IN SET FUNCTION</entry>
+<entry>NULL VALUE ELIMINATED IN SET FUNCTION</entry>
+</row>
+
+<row>
+<entry><literal>01007</literal></entry>
+<entry>PRIVILEGE NOT GRANTED</entry>
+</row>
+
+<row>
+<entry><literal>01006</literal></entry>
+<entry>PRIVILEGE NOT REVOKED</entry>
</row>
<row>
<entry><literal>01004</literal></entry>
-<entry>WARNING STRING DATA RIGHT TRUNCATION</entry>
+<entry>STRING DATA RIGHT TRUNCATION</entry>
</row>
<row>
<entry><literal>01P01</literal></entry>
-<entry>WARNING DEPRECATED FEATURE</entry>
+<entry>DEPRECATED FEATURE</entry>
</row>
<row>
<row>
<entry><literal>0F001</literal></entry>
-<entry>INVALID SPECIFICATION</entry>
+<entry>INVALID LOCATOR SPECIFICATION</entry>
</row>
<row>
<entry><literal>2202E</literal></entry>
-<entry>ARRAY ELEMENT ERROR</entry>
+<entry>ARRAY SUBSCRIPT ERROR</entry>
</row>
<row>
<row>
+<entry>Class 3B</entry>
+<entry>Savepoint Exception</entry>
+</row>
+
+<row>
+<entry><literal>3B000</literal></entry>
+<entry>SAVEPOINT EXCEPTION</entry>
+</row>
+
+<row>
+<entry><literal>3B001</literal></entry>
+<entry>INVALID SAVEPOINT SPECIFICATION</entry>
+</row>
+
+
+<row>
<entry>Class 3D</entry>
<entry>Invalid Catalog Name</entry>
</row>
<row>
<entry><literal>40002</literal></entry>
-<entry>INTEGRITY CONSTRAINT VIOLATION</entry>
+<entry>TRANSACTION INTEGRITY CONSTRAINT VIOLATION</entry>
</row>
<row>
<row>
<entry><literal>42P05</literal></entry>
-<entry>DUPLICATE PSTATEMENT</entry>
+<entry>DUPLICATE PREPARED STATEMENT</entry>
</row>
<row>
<row>
<entry><literal>42P14</literal></entry>
-<entry>INVALID PSTATEMENT DEFINITION</entry>
+<entry>INVALID PREPARED STATEMENT DEFINITION</entry>
</row>
<row>
<row>
+<entry>Class P0</entry>
+<entry><application>PL/pgSQL</> Error</entry>
+</row>
+
+<row>
+<entry><literal>P0000</literal></entry>
+<entry>PLPGSQL ERROR</entry>
+</row>
+
+<row>
+<entry><literal>P0001</literal></entry>
+<entry>RAISE EXCEPTION</entry>
+</row>
+
+
+<row>
<entry>Class XX</entry>
<entry>Internal Error</entry>
</row>
<!--
-$PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.42 2004/07/31 07:39:17 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.43 2004/07/31 23:04:54 tgl Exp $
-->
<chapter id="plpgsql">
BEGIN
<replaceable>statements</replaceable>
EXCEPTION
- WHEN <replaceable>condition</replaceable> THEN
+ WHEN <replaceable>condition</replaceable> <optional> OR <replaceable>condition</replaceable> ... </optional> THEN
<replaceable>handler_statements</replaceable>
- <optional> WHEN <replaceable>condition</replaceable> THEN
- <replaceable>handler_statements</replaceable>
- ...
- </optional>
+ <optional> WHEN <replaceable>condition</replaceable> <optional> OR <replaceable>condition</replaceable> ... </optional> THEN
+ <replaceable>handler_statements</replaceable>
+ ... </optional>
END;
</synopsis>
</para>
as though the <literal>EXCEPTION</> clause were not there at all:
the error can be caught by an enclosing block with
<literal>EXCEPTION</>, or if there is none it aborts processing
- of the function. The special condition name <literal>OTHERS</>
+ of the function.
+ </para>
+
+ <para>
+ The <replaceable>condition</replaceable> names can be any of those
+ shown in <xref linkend="errcodes-appendix">. A category name matches
+ any error within its category.
+ The special condition name <literal>OTHERS</>
matches every error type except <literal>QUERY_CANCELED</>.
- (It is possible, but usually not a good idea, to trap
+ (It is possible, but often unwise, to trap
<literal>QUERY_CANCELED</> by name.)
+ Condition names are not case-sensitive.
</para>
<para>
the <literal>EXCEPTION</> clause. The value returned in the
<command>RETURN</> statement will be the incremented value of
<literal>x</>, but the effects of the <command>UPDATE</> command will
- have been rolled back. The <command>INSERT</> command is not rolled
- back, however, so the end result is that the database contains
- <literal>Tom Jones</> not <literal>Joe Jones</>.
+ have been rolled back. The <command>INSERT</> command preceding the
+ block is not rolled back, however, so the end result is that the database
+ contains <literal>Tom Jones</> not <literal>Joe Jones</>.
</para>
<tip>
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.71 2004/07/31 00:45:43 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.72 2004/07/31 23:04:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
(PGSIXBIT(ch1) + (PGSIXBIT(ch2) << 6) + (PGSIXBIT(ch3) << 12) + \
(PGSIXBIT(ch4) << 18) + (PGSIXBIT(ch5) << 24))
+/* These macros depend on the fact that '0' becomes a zero in SIXBIT */
+#define ERRCODE_TO_CATEGORY(ec) ((ec) & ((1 << 12) - 1))
+#define ERRCODE_IS_CATEGORY(ec) (((ec) & ~((1 << 12) - 1)) == 0)
+
/* SQLSTATE codes for errors are defined in a separate file */
#include "utils/errcodes.h"
* procedural language
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.58 2004/07/31 07:39:20 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.59 2004/07/31 23:04:56 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
PLpgSQL_stmt *stmt;
PLpgSQL_stmts *stmts;
PLpgSQL_stmt_block *program;
+ PLpgSQL_condition *condition;
PLpgSQL_exception *exception;
PLpgSQL_exceptions *exceptions;
PLpgSQL_nsitem *nsitem;
%type <exceptions> exception_sect proc_exceptions
%type <exception> proc_exception
+%type <condition> proc_conditions
%type <intlist> raise_params
%type <ival> raise_level raise_param
%token K_NOTICE
%token K_NULL
%token K_OPEN
+%token K_OR
%token K_PERFORM
%token K_ROW_COUNT
%token K_RAISE
}
;
-proc_exception : K_WHEN lno opt_lblname K_THEN proc_sect
+proc_exception : K_WHEN lno proc_conditions K_THEN proc_sect
{
PLpgSQL_exception *new;
new = malloc(sizeof(PLpgSQL_exception));
memset(new, 0, sizeof(PLpgSQL_exception));
- new->lineno = $2;
- new->label = $3;
- new->action = $5;
+ new->lineno = $2;
+ new->conditions = $3;
+ new->action = $5;
$$ = new;
}
;
+proc_conditions : proc_conditions K_OR opt_lblname
+ {
+ PLpgSQL_condition *new;
+ PLpgSQL_condition *old;
+
+ new = malloc(sizeof(PLpgSQL_condition));
+ memset(new, 0, sizeof(PLpgSQL_condition));
+
+ new->condname = $3;
+ new->next = NULL;
+
+ for (old = $1; old->next != NULL; old = old->next)
+ /* skip */ ;
+ old->next = new;
+
+ $$ = $1;
+ }
+ | opt_lblname
+ {
+ PLpgSQL_condition *new;
+
+ new = malloc(sizeof(PLpgSQL_condition));
+ memset(new, 0, sizeof(PLpgSQL_condition));
+
+ new->condname = $1;
+ new->next = NULL;
+
+ $$ = new;
+ }
+ ;
+
expr_until_semi :
{ $$ = plpgsql_read_expression(';', ";"); }
;
* procedural language
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.110 2004/07/31 20:55:44 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.111 2004/07/31 23:04:56 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
static bool
-exception_matches_label(ErrorData *edata, const char *label)
+exception_matches_conditions(ErrorData *edata, PLpgSQL_condition *cond)
{
- int i;
-
- /*
- * OTHERS matches everything *except* query-canceled;
- * if you're foolish enough, you can match that explicitly.
- */
- if (pg_strcasecmp(label, "OTHERS") == 0)
- {
- if (edata->sqlerrcode == ERRCODE_QUERY_CANCELED)
- return false;
- else
- return true;
- }
- for (i = 0; exception_label_map[i].label != NULL; i++)
+ for (; cond != NULL; cond = cond->next)
{
- if (pg_strcasecmp(label, exception_label_map[i].label) == 0)
- return (edata->sqlerrcode == exception_label_map[i].sqlerrstate);
+ const char *condname = cond->condname;
+ int i;
+
+ /*
+ * OTHERS matches everything *except* query-canceled;
+ * if you're foolish enough, you can match that explicitly.
+ */
+ if (pg_strcasecmp(condname, "OTHERS") == 0)
+ {
+ if (edata->sqlerrcode == ERRCODE_QUERY_CANCELED)
+ return false;
+ else
+ return true;
+ }
+ for (i = 0; exception_label_map[i].label != NULL; i++)
+ {
+ if (pg_strcasecmp(condname, exception_label_map[i].label) == 0)
+ {
+ int labelerrcode = exception_label_map[i].sqlerrstate;
+
+ /* Exact match? */
+ if (edata->sqlerrcode == labelerrcode)
+ return true;
+ /* Category match? */
+ if (ERRCODE_IS_CATEGORY(labelerrcode) &&
+ ERRCODE_TO_CATEGORY(edata->sqlerrcode) == labelerrcode)
+ return true;
+ /*
+ * You would think we should "break" here, but there are some
+ * duplicate names in the table, so keep looking.
+ */
+ }
+ }
+ /* Should we raise an error if condname is unrecognized?? */
}
- /* Should we raise an error if label is unrecognized?? */
return false;
}
{
PLpgSQL_exception *exception = exceptions->exceptions[j];
- if (exception_matches_label(edata, exception->label))
+ if (exception_matches_conditions(edata, exception->conditions))
{
rc = exec_stmts(estate, exception->action);
break;
* procedural language
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.33 2004/07/31 07:39:20 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.34 2004/07/31 23:04:56 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
for (i = 0; i < block->exceptions->exceptions_used; i++)
{
PLpgSQL_exception *exc = block->exceptions->exceptions[i];
+ PLpgSQL_condition *cond;
dump_ind();
- printf(" EXCEPTION WHEN %s THEN\n", exc->label);
+ printf(" EXCEPTION WHEN ");
+ for (cond = exc->conditions; cond; cond = cond->next)
+ {
+ if (cond != exc->conditions)
+ printf(" OR ");
+ printf("%s", cond->condname);
+ }
+ printf(" THEN\n");
dump_stmts(exc->action);
}
}
*
* Copyright (c) 2003, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/plerrcodes.h,v 1.1 2004/07/31 07:39:20 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/plerrcodes.h,v 1.2 2004/07/31 23:04:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
-{ "SUCCESSFUL_COMPLETION", ERRCODE_SUCCESSFUL_COMPLETION },
-{ "WARNING", ERRCODE_WARNING },
-{ "WARNING_DYNAMIC_RESULT_SETS_RETURNED", ERRCODE_WARNING_DYNAMIC_RESULT_SETS_RETURNED },
-{ "WARNING_IMPLICIT_ZERO_BIT_PADDING", ERRCODE_WARNING_IMPLICIT_ZERO_BIT_PADDING },
-{ "WARNING_NULL_VALUE_ELIMINATED_IN_SET_FUNCTION", ERRCODE_WARNING_NULL_VALUE_ELIMINATED_IN_SET_FUNCTION },
-{ "WARNING_PRIVILEGE_NOT_GRANTED", ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED },
-{ "WARNING_PRIVILEGE_NOT_REVOKED", ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED },
-{ "WARNING_STRING_DATA_RIGHT_TRUNCATION", ERRCODE_WARNING_STRING_DATA_RIGHT_TRUNCATION },
-{ "WARNING_DEPRECATED_FEATURE", ERRCODE_WARNING_DEPRECATED_FEATURE },
-{ "NO_DATA", ERRCODE_NO_DATA },
-{ "NO_ADDITIONAL_DYNAMIC_RESULT_SETS_RETURNED", ERRCODE_NO_ADDITIONAL_DYNAMIC_RESULT_SETS_RETURNED },
+/* Success and warnings can't be caught, so omit them from table */
{ "SQL_STATEMENT_NOT_YET_COMPLETE", ERRCODE_SQL_STATEMENT_NOT_YET_COMPLETE },
{ "CONNECTION_EXCEPTION", ERRCODE_CONNECTION_EXCEPTION },
{ "CONNECTION_DOES_NOT_EXIST", ERRCODE_CONNECTION_DOES_NOT_EXIST },
{ "FEATURE_NOT_SUPPORTED", ERRCODE_FEATURE_NOT_SUPPORTED },
{ "INVALID_TRANSACTION_INITIATION", ERRCODE_INVALID_TRANSACTION_INITIATION },
{ "LOCATOR_EXCEPTION", ERRCODE_LOCATOR_EXCEPTION },
-{ "L_E_INVALID_SPECIFICATION", ERRCODE_L_E_INVALID_SPECIFICATION },
+{ "INVALID_LOCATOR_SPECIFICATION", ERRCODE_L_E_INVALID_SPECIFICATION },
{ "INVALID_GRANTOR", ERRCODE_INVALID_GRANTOR },
{ "INVALID_GRANT_OPERATION", ERRCODE_INVALID_GRANT_OPERATION },
{ "INVALID_ROLE_SPECIFICATION", ERRCODE_INVALID_ROLE_SPECIFICATION },
{ "ESCAPE_CHARACTER_CONFLICT", ERRCODE_ESCAPE_CHARACTER_CONFLICT },
{ "INDICATOR_OVERFLOW", ERRCODE_INDICATOR_OVERFLOW },
{ "INTERVAL_FIELD_OVERFLOW", ERRCODE_INTERVAL_FIELD_OVERFLOW },
-{ "INVALID_ARGUMENT_FOR_LOG", ERRCODE_INVALID_ARGUMENT_FOR_LOG },
+{ "INVALID_ARGUMENT_FOR_LOGARITHM", ERRCODE_INVALID_ARGUMENT_FOR_LOG },
{ "INVALID_ARGUMENT_FOR_POWER_FUNCTION", ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION },
{ "INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION", ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION },
{ "INVALID_CHARACTER_VALUE_FOR_CAST", ERRCODE_INVALID_CHARACTER_VALUE_FOR_CAST },
{ "DEPENDENT_OBJECTS_STILL_EXIST", ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST },
{ "INVALID_TRANSACTION_TERMINATION", ERRCODE_INVALID_TRANSACTION_TERMINATION },
{ "SQL_ROUTINE_EXCEPTION", ERRCODE_SQL_ROUTINE_EXCEPTION },
-{ "S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT", ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT },
-{ "S_R_E_MODIFYING_SQL_DATA_NOT_PERMITTED", ERRCODE_S_R_E_MODIFYING_SQL_DATA_NOT_PERMITTED },
-{ "S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED", ERRCODE_S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED },
-{ "S_R_E_READING_SQL_DATA_NOT_PERMITTED", ERRCODE_S_R_E_READING_SQL_DATA_NOT_PERMITTED },
+{ "FUNCTION_EXECUTED_NO_RETURN_STATEMENT", ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT },
+{ "MODIFYING_SQL_DATA_NOT_PERMITTED", ERRCODE_S_R_E_MODIFYING_SQL_DATA_NOT_PERMITTED },
+{ "PROHIBITED_SQL_STATEMENT_ATTEMPTED", ERRCODE_S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED },
+{ "READING_SQL_DATA_NOT_PERMITTED", ERRCODE_S_R_E_READING_SQL_DATA_NOT_PERMITTED },
{ "INVALID_CURSOR_NAME", ERRCODE_INVALID_CURSOR_NAME },
{ "EXTERNAL_ROUTINE_EXCEPTION", ERRCODE_EXTERNAL_ROUTINE_EXCEPTION },
-{ "E_R_E_CONTAINING_SQL_NOT_PERMITTED", ERRCODE_E_R_E_CONTAINING_SQL_NOT_PERMITTED },
-{ "E_R_E_MODIFYING_SQL_DATA_NOT_PERMITTED", ERRCODE_E_R_E_MODIFYING_SQL_DATA_NOT_PERMITTED },
-{ "E_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED", ERRCODE_E_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED },
-{ "E_R_E_READING_SQL_DATA_NOT_PERMITTED", ERRCODE_E_R_E_READING_SQL_DATA_NOT_PERMITTED },
+{ "CONTAINING_SQL_NOT_PERMITTED", ERRCODE_E_R_E_CONTAINING_SQL_NOT_PERMITTED },
+{ "MODIFYING_SQL_DATA_NOT_PERMITTED", ERRCODE_E_R_E_MODIFYING_SQL_DATA_NOT_PERMITTED },
+{ "PROHIBITED_SQL_STATEMENT_ATTEMPTED", ERRCODE_E_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED },
+{ "READING_SQL_DATA_NOT_PERMITTED", ERRCODE_E_R_E_READING_SQL_DATA_NOT_PERMITTED },
{ "EXTERNAL_ROUTINE_INVOCATION_EXCEPTION", ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION },
-{ "E_R_I_E_INVALID_SQLSTATE_RETURNED", ERRCODE_E_R_I_E_INVALID_SQLSTATE_RETURNED },
-{ "E_R_I_E_NULL_VALUE_NOT_ALLOWED", ERRCODE_E_R_I_E_NULL_VALUE_NOT_ALLOWED },
-{ "E_R_I_E_TRIGGER_PROTOCOL_VIOLATED", ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED },
-{ "E_R_I_E_SRF_PROTOCOL_VIOLATED", ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED },
+{ "INVALID_SQLSTATE_RETURNED", ERRCODE_E_R_I_E_INVALID_SQLSTATE_RETURNED },
+{ "NULL_VALUE_NOT_ALLOWED", ERRCODE_E_R_I_E_NULL_VALUE_NOT_ALLOWED },
+{ "TRIGGER_PROTOCOL_VIOLATED", ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED },
+{ "SRF_PROTOCOL_VIOLATED", ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED },
{ "SAVEPOINT_EXCEPTION", ERRCODE_SAVEPOINT_EXCEPTION },
-{ "S_E_INVALID_SPECIFICATION", ERRCODE_S_E_INVALID_SPECIFICATION },
+{ "INVALID_SAVEPOINT_SPECIFICATION", ERRCODE_S_E_INVALID_SPECIFICATION },
{ "INVALID_CATALOG_NAME", ERRCODE_INVALID_CATALOG_NAME },
{ "INVALID_SCHEMA_NAME", ERRCODE_INVALID_SCHEMA_NAME },
{ "TRANSACTION_ROLLBACK", ERRCODE_TRANSACTION_ROLLBACK },
-{ "T_R_INTEGRITY_CONSTRAINT_VIOLATION", ERRCODE_T_R_INTEGRITY_CONSTRAINT_VIOLATION },
-{ "T_R_SERIALIZATION_FAILURE", ERRCODE_T_R_SERIALIZATION_FAILURE },
-{ "T_R_STATEMENT_COMPLETION_UNKNOWN", ERRCODE_T_R_STATEMENT_COMPLETION_UNKNOWN },
-{ "T_R_DEADLOCK_DETECTED", ERRCODE_T_R_DEADLOCK_DETECTED },
+{ "TRANSACTION_INTEGRITY_CONSTRAINT_VIOLATION", ERRCODE_T_R_INTEGRITY_CONSTRAINT_VIOLATION },
+{ "SERIALIZATION_FAILURE", ERRCODE_T_R_SERIALIZATION_FAILURE },
+{ "STATEMENT_COMPLETION_UNKNOWN", ERRCODE_T_R_STATEMENT_COMPLETION_UNKNOWN },
+{ "DEADLOCK_DETECTED", ERRCODE_T_R_DEADLOCK_DETECTED },
{ "SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION", ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION },
{ "SYNTAX_ERROR", ERRCODE_SYNTAX_ERROR },
{ "INSUFFICIENT_PRIVILEGE", ERRCODE_INSUFFICIENT_PRIVILEGE },
{ "DUPLICATE_CURSOR", ERRCODE_DUPLICATE_CURSOR },
{ "DUPLICATE_DATABASE", ERRCODE_DUPLICATE_DATABASE },
{ "DUPLICATE_FUNCTION", ERRCODE_DUPLICATE_FUNCTION },
-{ "DUPLICATE_PSTATEMENT", ERRCODE_DUPLICATE_PSTATEMENT },
+{ "DUPLICATE_PREPARED_STATEMENT", ERRCODE_DUPLICATE_PSTATEMENT },
{ "DUPLICATE_SCHEMA", ERRCODE_DUPLICATE_SCHEMA },
{ "DUPLICATE_TABLE", ERRCODE_DUPLICATE_TABLE },
{ "DUPLICATE_ALIAS", ERRCODE_DUPLICATE_ALIAS },
{ "INVALID_CURSOR_DEFINITION", ERRCODE_INVALID_CURSOR_DEFINITION },
{ "INVALID_DATABASE_DEFINITION", ERRCODE_INVALID_DATABASE_DEFINITION },
{ "INVALID_FUNCTION_DEFINITION", ERRCODE_INVALID_FUNCTION_DEFINITION },
-{ "INVALID_PSTATEMENT_DEFINITION", ERRCODE_INVALID_PSTATEMENT_DEFINITION },
+{ "INVALID_PREPARED_STATEMENT_DEFINITION", ERRCODE_INVALID_PSTATEMENT_DEFINITION },
{ "INVALID_SCHEMA_DEFINITION", ERRCODE_INVALID_SCHEMA_DEFINITION },
{ "INVALID_TABLE_DEFINITION", ERRCODE_INVALID_TABLE_DEFINITION },
{ "INVALID_OBJECT_DEFINITION", ERRCODE_INVALID_OBJECT_DEFINITION },
* procedural language
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.48 2004/07/31 07:39:20 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.49 2004/07/31 23:04:56 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
} PLpgSQL_stmts;
+typedef struct PLpgSQL_condition
+{ /* One EXCEPTION condition name */
+ char *condname;
+ struct PLpgSQL_condition *next;
+} PLpgSQL_condition;
+
typedef struct
{ /* One EXCEPTION ... WHEN clause */
int lineno;
- char *label;
+ PLpgSQL_condition *conditions;
PLpgSQL_stmts *action;
} PLpgSQL_exception;
* procedural language
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/scan.l,v 1.35 2004/06/03 22:56:43 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/scan.l,v 1.36 2004/07/31 23:04:56 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
notice { return K_NOTICE; }
null { return K_NULL; }
open { return K_OPEN; }
+or { return K_OR; }
perform { return K_PERFORM; }
raise { return K_RAISE; }
rename { return K_RENAME; }
--
create function trap_zero_divide(int) returns int as $$
declare x int;
-declare sx smallint;
+ sx smallint;
begin
begin -- start a subtransaction
raise notice 'should see this';
NOTICE: should see this only if -100 <> 0
NOTICE: should see this only if -100 fits in smallint
ERROR: -100 is less than zero
+create function trap_matching_test(int) returns int as $$
+declare x int;
+ sx smallint;
+ y int;
+begin
+ begin -- start a subtransaction
+ x := 100 / $1;
+ sx := $1;
+ select into y unique1 from tenk1 where unique2 =
+ (select unique2 from tenk1 b where ten = $1);
+ exception
+ when data_exception then -- category match
+ raise notice 'caught data_exception';
+ x := -1;
+ when NUMERIC_VALUE_OUT_OF_RANGE OR CARDINALITY_VIOLATION then
+ raise notice 'caught numeric_value_out_of_range or cardinality_violation';
+ x := -2;
+ end;
+ return x;
+end$$ language plpgsql;
+select trap_matching_test(50);
+ trap_matching_test
+--------------------
+ 2
+(1 row)
+
+select trap_matching_test(0);
+NOTICE: caught data_exception
+ trap_matching_test
+--------------------
+ -1
+(1 row)
+
+select trap_matching_test(100000);
+NOTICE: caught data_exception
+ trap_matching_test
+--------------------
+ -1
+(1 row)
+
+select trap_matching_test(1);
+NOTICE: caught numeric_value_out_of_range or cardinality_violation
+ trap_matching_test
+--------------------
+ -2
+(1 row)
+
+create temp table foo (f1 int);
+create function blockme() returns int as $$
+declare x int;
+begin
+ x := 1;
+ insert into foo values(x);
+ begin
+ x := x + 1;
+ insert into foo values(x);
+ -- we assume this will take longer than 1 second:
+ select count(*) into x from tenk1 a, tenk1 b, tenk1 c;
+ exception
+ when others then
+ raise notice 'caught others?';
+ return -1;
+ when query_canceled then
+ raise notice 'nyeah nyeah, can''t stop me';
+ x := x * 10;
+ end;
+ insert into foo values(x);
+ return x;
+end$$ language plpgsql;
+set statement_timeout to 1000;
+select blockme();
+NOTICE: nyeah nyeah, can't stop me
+ blockme
+---------
+ 20
+(1 row)
+
+reset statement_timeout;
+select * from foo;
+ f1
+----
+ 1
+ 20
+(2 rows)
+
create function trap_zero_divide(int) returns int as $$
declare x int;
-declare sx smallint;
+ sx smallint;
begin
begin -- start a subtransaction
raise notice 'should see this';
select trap_zero_divide(0);
select trap_zero_divide(100000);
select trap_zero_divide(-100);
+
+create function trap_matching_test(int) returns int as $$
+declare x int;
+ sx smallint;
+ y int;
+begin
+ begin -- start a subtransaction
+ x := 100 / $1;
+ sx := $1;
+ select into y unique1 from tenk1 where unique2 =
+ (select unique2 from tenk1 b where ten = $1);
+ exception
+ when data_exception then -- category match
+ raise notice 'caught data_exception';
+ x := -1;
+ when NUMERIC_VALUE_OUT_OF_RANGE OR CARDINALITY_VIOLATION then
+ raise notice 'caught numeric_value_out_of_range or cardinality_violation';
+ x := -2;
+ end;
+ return x;
+end$$ language plpgsql;
+
+select trap_matching_test(50);
+select trap_matching_test(0);
+select trap_matching_test(100000);
+select trap_matching_test(1);
+
+create temp table foo (f1 int);
+
+create function blockme() returns int as $$
+declare x int;
+begin
+ x := 1;
+ insert into foo values(x);
+ begin
+ x := x + 1;
+ insert into foo values(x);
+ -- we assume this will take longer than 1 second:
+ select count(*) into x from tenk1 a, tenk1 b, tenk1 c;
+ exception
+ when others then
+ raise notice 'caught others?';
+ return -1;
+ when query_canceled then
+ raise notice 'nyeah nyeah, can''t stop me';
+ x := x * 10;
+ end;
+ insert into foo values(x);
+ return x;
+end$$ language plpgsql;
+
+set statement_timeout to 1000;
+
+select blockme();
+
+reset statement_timeout;
+
+select * from foo;