Code review for SELECT INTO STRICT patch: use saner choices of error
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 16 Jun 2006 23:29:27 +0000 (23:29 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 16 Jun 2006 23:29:27 +0000 (23:29 +0000)
SQLSTATEs, fix some documentation problems.

doc/src/sgml/errcodes.sgml
doc/src/sgml/plpgsql.sgml
src/include/utils/errcodes.h
src/pl/plpgsql/src/gram.y
src/pl/plpgsql/src/pl_exec.c
src/pl/plpgsql/src/plerrcodes.h
src/pl/plpgsql/src/scan.l

index fc7c8fb649364546bd5b0e88bd0b6219ec987796..76c657946814a2a57a934220240a28db8f505316 100644 (file)
 <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 &mdash; Internal Error</></entry>
index a5c1a18dffa342898009e00fd61c7b0329753781..ef76a83688fedfe98ac71c253cd7c300782f152f 100644 (file)
@@ -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>
index d84a2e7ed2760f6a5a88328bede4ba0840cad6e6..3ac8c041bfd6b812bf75a54003857ba4aef49084 100644 (file)
 /* 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) */
index 75f69b9c6bcf9ebd8febd4055838461f2f7d1c44..4f1ea52caeda7dc438b09ccbc6ce8f776e25935f 100644 (file)
@@ -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
index 2640397fe21c223cfd5a0888131d7c9a393e9dc9..be72029322778e7c38b37316053d2432f507e57e 100644 (file)
@@ -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")));
 
        /*
index f0de298d1295f358dddc79310a916c12efbfb269..2e5fa9bb96beda0a109b8ecd545d2942e17e780a 100644 (file)
 },
 
 {
-       "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
 },
-
-
index e7b9a2319d94e9d7c002f555edfb53ba603db93f..a04361eb11e4211f760ec309e0d67e921fae2485 100644 (file)
@@ -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;                        }