diff --git a/doc/src/sgml/errcodes.sgml b/doc/src/sgml/errcodes.sgml index b5617c985073e1c0c39708852e7623ed93143d27..bf06cfaf5e5874d6f821c54acff1e8f51d0ae1d6 100644 --- a/doc/src/sgml/errcodes.sgml +++ b/doc/src/sgml/errcodes.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/errcodes.sgml,v 1.19 2006/06/16 22:41:45 tgl Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/errcodes.sgml,v 1.20 2006/06/16 23:29:26 tgl Exp $ --> <appendix id="errcodes-appendix"> <title><productname>PostgreSQL</productname> Error Codes</title> @@ -1344,6 +1344,18 @@ <entry>raise_exception</entry> </row> +<row> +<entry><literal>P0002</literal></entry> +<entry>NO DATA FOUND</entry> +<entry>no_data_found</entry> +</row> + +<row> +<entry><literal>P0003</literal></entry> +<entry>TOO MANY ROWS</entry> +<entry>too_many_rows</entry> +</row> + <row> <entry spanname="span13"><emphasis role="bold">Class XX — Internal Error</></entry> diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml index 1f09b9e99c71154e886b30403638a8529a888a84..ac5b2b4cfc60271841ea9ae9c49721657140d8be 100644 --- a/doc/src/sgml/plpgsql.sgml +++ b/doc/src/sgml/plpgsql.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.96 2006/06/15 18:02:22 momjian Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.97 2006/06/16 23:29:26 tgl Exp $ --> <chapter id="plpgsql"> <title><application>PL/pgSQL</application> - <acronym>SQL</acronym> Procedural Language</title> @@ -1076,8 +1076,8 @@ tax := subtotal * 0.06; </indexterm> <para> - The result of a <command>SELECT</command> command yielding multiple columns (but - only one row) can be assigned to a record variable, row-type + The result of a <command>SELECT</command> command yielding multiple + columns (but only one row) can be assigned to a record variable, row-type variable, or list of scalar variables. This is done by: <synopsis> @@ -1126,23 +1126,24 @@ SELECT INTO <optional>STRICT</optional> <replaceable>target</replaceable> <repla <replaceable>target</replaceable> will be set to the first row returned by the query, or if the query returned no rows, null values are assigned. (Note that <quote>the first row</> is not - well-defined unless you've used <literal>ORDER BY</>.) - You can check the special <literal>FOUND</literal> variable to - determine if any rows were found: + well-defined unless you've used <literal>ORDER BY</>.) Any result rows + after the first row are discarded. + You can check the special <literal>FOUND</literal> variable (see + <xref linkend="plpgsql-statements-diagnostics">) to + determine whether a row was returned: <programlisting> -SELECT INTO STRICT myrec * FROM emp WHERE empname = myname; +SELECT INTO myrec * FROM emp WHERE empname = myname; IF NOT FOUND THEN RAISE EXCEPTION 'employee % not found', myname; END IF; </programlisting> - <para> - If the <literal>STRICT</literal> option is specified, a query must + If the <literal>STRICT</literal> option is specified, the query must return exactly one row or a run-time error will be thrown, either <literal>NO_DATA_FOUND</> (no rows) or <literal>TOO_MANY_ROWS</> - (more than one row). You can must use exception blocks to determine - the number of rows generated by the query: + (more than one row). You can use an exception block if you wish + to catch the error, for example: <programlisting> BEGIN; @@ -1154,11 +1155,17 @@ BEGIN; RAISE EXCEPTION 'employee % not unique', myname; END; </programlisting> - Only <command>SELECT INTO STRICT</command> allows you to check if more - than one row was retrieved. <command>SELECT INTO STRICT</command> - matches Oracle's PL/SQL <command>SELECT INTO</command> behavior. + Successful execution of <command>SELECT INTO STRICT</command> + always sets <literal>FOUND</literal> to true. </para> + <note> + <para> + <command>SELECT INTO STRICT</command> matches the behavior of + Oracle PL/SQL's <command>SELECT INTO</command> statement. + </para> + </note> + </sect2> <sect2 id="plpgsql-statements-perform"> @@ -1987,7 +1994,7 @@ END LOOP <optional> <replaceable>label</replaceable> </optional>; the loop. If the <literal>BY</> clause isn't specified the iteration step is 1 otherwise it's the value specified in the <literal>BY</> clause. If <literal>REVERSE</> is specified then the step value is - considered negative. + considered negative. </para> <para> @@ -2764,7 +2771,7 @@ RAISE EXCEPTION 'Nonexistent ID --> %', user_id; <para> Data type <type>name</type>; the name of the table that caused the trigger invocation. This is now deprecated, and could disappear in a future - release. Use <literal>TG_TABLE_NAME</> instead. + release. Use <literal>TG_TABLE_NAME</> instead. </para> </listitem> </varlistentry> @@ -2774,7 +2781,7 @@ RAISE EXCEPTION 'Nonexistent ID --> %', user_id; <listitem> <para> Data type <type>name</type>; the name of the table that - caused the trigger invocation. + caused the trigger invocation. </para> </listitem> </varlistentry> @@ -2784,7 +2791,7 @@ RAISE EXCEPTION 'Nonexistent ID --> %', user_id; <listitem> <para> Data type <type>name</type>; the name of the schema of the - table that caused the trigger invocation. + table that caused the trigger invocation. </para> </listitem> </varlistentry> diff --git a/src/include/utils/errcodes.h b/src/include/utils/errcodes.h index fc59a32fb91bb6fc2d417ba5614632b656ff4b27..8ba809d2ee8fd7095a2d93252e101dbfb70b0afe 100644 --- a/src/include/utils/errcodes.h +++ b/src/include/utils/errcodes.h @@ -11,7 +11,7 @@ * * Copyright (c) 2003-2006, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/include/utils/errcodes.h,v 1.19 2006/03/05 15:59:07 momjian Exp $ + * $PostgreSQL: pgsql/src/include/utils/errcodes.h,v 1.20 2006/06/16 23:29:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -331,6 +331,8 @@ /* Class P0 - PL/pgSQL Error (PostgreSQL-specific error class) */ #define ERRCODE_PLPGSQL_ERROR MAKE_SQLSTATE('P','0', '0','0','0') #define ERRCODE_RAISE_EXCEPTION MAKE_SQLSTATE('P','0', '0','0','1') +#define ERRCODE_NO_DATA_FOUND MAKE_SQLSTATE('P','0', '0','0','2') +#define ERRCODE_TOO_MANY_ROWS MAKE_SQLSTATE('P','0', '0','0','3') /* Class XX - Internal Error (PostgreSQL-specific error class) */ /* (this is for "can't-happen" conditions and software bugs) */ diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y index 21a0bd6541e0e3c7c88201b192cb247944ec999e..4ced4402ebee17b61440f7de2eb24f9c3c4788fd 100644 --- a/src/pl/plpgsql/src/gram.y +++ b/src/pl/plpgsql/src/gram.y @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.92 2006/06/15 18:02:22 momjian Exp $ + * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.93 2006/06/16 23:29:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -157,7 +157,6 @@ static void check_labels(const char *start_label, %token K_ELSE %token K_ELSIF %token K_END -%token K_STRICT %token K_EXCEPTION %token K_EXECUTE %token K_EXIT @@ -187,6 +186,7 @@ static void check_labels(const char *start_label, %token K_RETURN_NEXT %token K_REVERSE %token K_SELECT +%token K_STRICT %token K_THEN %token K_TO %token K_TYPE diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index e74dcac23111cbd16784901b0845b57cd2ac4261..4188fe1eb1cd2cfed2e849279d4fc088936f371d 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.172 2006/06/16 18:42:23 tgl Exp $ + * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.173 2006/06/16 23:29:27 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1721,7 +1721,7 @@ exec_stmt_select(PLpgSQL_execstate *estate, PLpgSQL_stmt_select *stmt) { if (stmt->strict) ereport(ERROR, - (errcode(ERRCODE_NO_DATA), + (errcode(ERRCODE_NO_DATA_FOUND), errmsg("query returned no rows"))); /* set the target to NULL(s) */ @@ -1732,7 +1732,7 @@ exec_stmt_select(PLpgSQL_execstate *estate, PLpgSQL_stmt_select *stmt) if (n > 1 && stmt->strict) ereport(ERROR, - (errcode(ERRCODE_CARDINALITY_VIOLATION), + (errcode(ERRCODE_TOO_MANY_ROWS), errmsg("query returned more than one row"))); /* diff --git a/src/pl/plpgsql/src/plerrcodes.h b/src/pl/plpgsql/src/plerrcodes.h index fedd4d0c7e7fb312a5cc731e41cf2456379863fb..478bf3b080683a8ca5526c450c198291946b465c 100644 --- a/src/pl/plpgsql/src/plerrcodes.h +++ b/src/pl/plpgsql/src/plerrcodes.h @@ -9,7 +9,7 @@ * * Copyright (c) 2003-2006, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/pl/plpgsql/src/plerrcodes.h,v 1.8 2006/06/15 18:02:22 momjian Exp $ + * $PostgreSQL: pgsql/src/pl/plpgsql/src/plerrcodes.h,v 1.9 2006/06/16 23:29:27 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -712,23 +712,21 @@ }, { - "internal_error", ERRCODE_INTERNAL_ERROR + "no_data_found", ERRCODE_NO_DATA_FOUND }, { - "data_corrupted", ERRCODE_DATA_CORRUPTED + "too_many_rows", ERRCODE_TOO_MANY_ROWS }, { - "index_corrupted", ERRCODE_INDEX_CORRUPTED + "internal_error", ERRCODE_INTERNAL_ERROR }, { - "no_data_found", ERRCODE_NO_DATA + "data_corrupted", ERRCODE_DATA_CORRUPTED }, { - "too_many_rows", ERRCODE_CARDINALITY_VIOLATION + "index_corrupted", ERRCODE_INDEX_CORRUPTED }, - - diff --git a/src/pl/plpgsql/src/scan.l b/src/pl/plpgsql/src/scan.l index 1dca30a5666db303356e8d1692764d3877b497ee..7220949063c3038b93cb155e2948edf0bb4cde0d 100644 --- a/src/pl/plpgsql/src/scan.l +++ b/src/pl/plpgsql/src/scan.l @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/pl/plpgsql/src/scan.l,v 1.51 2006/06/15 18:02:22 momjian Exp $ + * $PostgreSQL: pgsql/src/pl/plpgsql/src/scan.l,v 1.52 2006/06/16 23:29:27 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -129,7 +129,6 @@ else { return K_ELSE; } elseif { return K_ELSIF; } elsif { return K_ELSIF; } end { return K_END; } -strict { return K_STRICT; } exception { return K_EXCEPTION; } execute { return K_EXECUTE; } exit { return K_EXIT; } @@ -158,6 +157,7 @@ return { return K_RETURN; } reverse { return K_REVERSE; } row_count { return K_ROW_COUNT; } select { return K_SELECT; } +strict { return K_STRICT; } then { return K_THEN; } to { return K_TO; } type { return K_TYPE; }