On Fri, Jun 28, 2013 at 12:08:21PM -0400, Noah Misch wrote:
> On Fri, Jun 28, 2013 at 05:21:29PM +0200, Pavel Stehule wrote:
> > 2013/6/28 Noah Misch <n...@leadboat.com>:
> > > Okay.  I failed to note the first time through that while the patch uses 
> > > the
> > > same option names for RAISE and GET STACKED DIAGNOSTICS, the existing 
> > > option
> > > lists for those commands differ:
> > >
> > > --RAISE option--    --GET STACKED DIAGNOSTICS option--
> > > ERRCODE             RETURNED_SQLSTATE
> > > MESSAGE             MESSAGE_TEXT
> > > DETAIL              PG_EXCEPTION_DETAIL
> > > HINT                PG_EXCEPTION_HINT
> > > CONTEXT             PG_EXCEPTION_CONTEXT
> > >
> > > To be consistent with that pattern, I think we would use COLUMN, 
> > > CONSTRAINT,
> > > TABLE, TYPE and SCHEMA as the new RAISE options.
> > 
> > I understand to your motivation, but I am not sure. Minimally word
> > "TYPE" is too general. I have not strong opinion in this area. maybe
> > DATATYPE ??
> 
> I'm not positive either.  DATATYPE rather than TYPE makes sense.

Here's a revision bearing the discussed name changes and protocol
documentation tweaks, along with some cosmetic adjustments.  If this seems
good to you, I will commit it.

-- 
Noah Misch
EnterpriseDB                                 http://www.enterprisedb.com
*** a/doc/src/sgml/libpq.sgml
--- b/doc/src/sgml/libpq.sgml
***************
*** 2712,2720 **** char *PQresultErrorField(const PGresult *res, int fieldcode);
            <term><symbol>PG_DIAG_TABLE_NAME</></term>
            <listitem>
             <para>
!             If the error was associated with a specific table, the name of
!             the table.  (When this field is present, the schema name field
!             provides the name of the table's schema.)
             </para>
            </listitem>
           </varlistentry>
--- 2712,2720 ----
            <term><symbol>PG_DIAG_TABLE_NAME</></term>
            <listitem>
             <para>
!             If the error was associated with a specific table, the name of the
!             table.  (Refer to the schema name field for the name of the
!             table's schema.)
             </para>
            </listitem>
           </varlistentry>
***************
*** 2723,2731 **** char *PQresultErrorField(const PGresult *res, int fieldcode);
            <term><symbol>PG_DIAG_COLUMN_NAME</></term>
            <listitem>
             <para>
!             If the error was associated with a specific table column, the
!             name of the column.  (When this field is present, the schema
!             and table name fields identify the table.)
             </para>
            </listitem>
           </varlistentry>
--- 2723,2731 ----
            <term><symbol>PG_DIAG_COLUMN_NAME</></term>
            <listitem>
             <para>
!             If the error was associated with a specific table column, the name
!             of the column.  (Refer to the schema and table name fields to
!             identify the table.)
             </para>
            </listitem>
           </varlistentry>
***************
*** 2734,2742 **** char *PQresultErrorField(const PGresult *res, int fieldcode);
            <term><symbol>PG_DIAG_DATATYPE_NAME</></term>
            <listitem>
             <para>
!             If the error was associated with a specific data type, the name
!             of the data type.  (When this field is present, the schema name
!             field provides the name of the data type's schema.)
             </para>
            </listitem>
           </varlistentry>
--- 2734,2742 ----
            <term><symbol>PG_DIAG_DATATYPE_NAME</></term>
            <listitem>
             <para>
!             If the error was associated with a specific data type, the name of
!             the data type.  (Refer to the schema name field for the name of
!             the data type's schema.)
             </para>
            </listitem>
           </varlistentry>
***************
*** 2745,2755 **** char *PQresultErrorField(const PGresult *res, int fieldcode);
            <term><symbol>PG_DIAG_CONSTRAINT_NAME</></term>
            <listitem>
             <para>
!             If the error was associated with a specific constraint,
!             the name of the constraint.  The table or domain that the
!             constraint belongs to is reported using the fields listed
!             above.  (For this purpose, indexes are treated as constraints,
!             even if they weren't created with constraint syntax.)
             </para>
            </listitem>
           </varlistentry>
--- 2745,2755 ----
            <term><symbol>PG_DIAG_CONSTRAINT_NAME</></term>
            <listitem>
             <para>
!             If the error was associated with a specific constraint, the name
!             of the constraint.  Refer to fields listed above for the
!             associated table or domain.  (For this purpose, indexes are
!             treated as constraints, even if they weren't created with
!             constraint syntax.)
             </para>
            </listitem>
           </varlistentry>
***************
*** 2787,2795 **** char *PQresultErrorField(const PGresult *res, int fieldcode);
  
         <note>
          <para>
!          The fields for schema name, table name, column name, data type
!          name, and constraint name are supplied only for a limited number
!          of error types; see <xref linkend="errcodes-appendix">.
          </para>
         </note>
  
--- 2787,2800 ----
  
         <note>
          <para>
!          The fields for schema name, table name, column name, data type name,
!          and constraint name are supplied only for a limited number of error
!          types; see <xref linkend="errcodes-appendix">.  Do not assume that
!          the presence of any of these fields guarantees the presence of
!          another field.  Core error sources observe the interrelationships
!          noted above, but user-defined functions may use these fields in other
!          ways.  In the same vein, do not assume that these fields denote
!          contemporary objects in the current database.
          </para>
         </note>
  
*** a/doc/src/sgml/plpgsql.sgml
--- b/doc/src/sgml/plpgsql.sgml
***************
*** 2665,2675 **** GET STACKED DIAGNOSTICS <replaceable>variable</replaceable> 
= <replaceable>item<
--- 2665,2700 ----
           <entry>the SQLSTATE error code of the exception</entry>
          </row>
          <row>
+          <entry><literal>COLUMN_NAME</literal></entry>
+          <entry>text</entry>
+          <entry>the name of column related to exception</entry>
+         </row>
+         <row>
+          <entry><literal>CONSTRAINT_NAME</literal></entry>
+          <entry>text</entry>
+          <entry>the name of constraint related to exception</entry>
+         </row>
+         <row>
+          <entry><literal>PG_DATATYPE_NAME</literal></entry>
+          <entry>text</entry>
+          <entry>the name of datatype related to exception</entry>
+         </row>
+         <row>
           <entry><literal>MESSAGE_TEXT</literal></entry>
           <entry>text</entry>
           <entry>the text of the exception's primary message</entry>
          </row>
          <row>
+          <entry><literal>TABLE_NAME</literal></entry>
+          <entry>text</entry>
+          <entry>the name of table related to exception</entry>
+         </row>
+         <row>
+          <entry><literal>SCHEMA_NAME</literal></entry>
+          <entry>text</entry>
+          <entry>the name of schema related to exception</entry>
+         </row>
+         <row>
           <entry><literal>PG_EXCEPTION_DETAIL</literal></entry>
           <entry>text</entry>
           <entry>the text of the exception's detail message, if any</entry>
***************
*** 3355,3360 **** RAISE NOTICE 'Calling cs_create_job(%)', v_job_id;
--- 3380,3396 ----
          five-character SQLSTATE code.</para>
        </listitem>
       </varlistentry>
+ 
+      <varlistentry>
+       <term><literal>COLUMN</literal></term>
+       <term><literal>CONSTRAINT</literal></term>
+       <term><literal>DATATYPE</literal></term>
+       <term><literal>TABLE</literal></term>
+       <term><literal>SCHEMA</literal></term>
+       <listitem>
+        <para>Supplies the name of a related object.</para>
+       </listitem>
+      </varlistentry>
      </variablelist>
     </para>
  
*** a/doc/src/sgml/protocol.sgml
--- b/doc/src/sgml/protocol.sgml
***************
*** 4788,4795 **** message.
  <listitem>
  <para>
          Table name: if the error was associated with a specific table, the
!         name of the table.  (When this field is present, the schema name field
!         provides the name of the table's schema.)
  </para>
  </listitem>
  </varlistentry>
--- 4788,4795 ----
  <listitem>
  <para>
          Table name: if the error was associated with a specific table, the
!         name of the table.  (Refer to the schema name field for the name of
!         the table's schema.)
  </para>
  </listitem>
  </varlistentry>
***************
*** 4801,4808 **** message.
  <listitem>
  <para>
          Column name: if the error was associated with a specific table column,
!         the name of the column.  (When this field is present, the schema and
!         table name fields identify the table.)
  </para>
  </listitem>
  </varlistentry>
--- 4801,4808 ----
  <listitem>
  <para>
          Column name: if the error was associated with a specific table column,
!         the name of the column.  (Refer to the schema and table name fields to
!         identify the table.)
  </para>
  </listitem>
  </varlistentry>
***************
*** 4814,4821 **** message.
  <listitem>
  <para>
          Data type name: if the error was associated with a specific data type,
!         the name of the data type.  (When this field is present, the schema
!         name field provides the name of the data type's schema.)
  </para>
  </listitem>
  </varlistentry>
--- 4814,4821 ----
  <listitem>
  <para>
          Data type name: if the error was associated with a specific data type,
!         the name of the data type.  (Refer to the schema name field for the
!         name of the data type's schema.)
  </para>
  </listitem>
  </varlistentry>
***************
*** 4827,4836 **** message.
  <listitem>
  <para>
          Constraint name: if the error was associated with a specific
!         constraint, the name of the constraint.  The table or domain that the
!         constraint belongs to is reported using the fields listed above.  (For
!         this purpose, indexes are treated as constraints, even if they weren't
!         created with constraint syntax.)
  </para>
  </listitem>
  </varlistentry>
--- 4827,4836 ----
  <listitem>
  <para>
          Constraint name: if the error was associated with a specific
!         constraint, the name of the constraint.  Refer to fields listed above
!         for the associated table or domain.  (For this purpose, indexes are
!         treated as constraints, even if they weren't created with constraint
!         syntax.)
  </para>
  </listitem>
  </varlistentry>
***************
*** 4876,4882 **** message.
   <para>
    The fields for schema name, table name, column name, data type name, and
    constraint name are supplied only for a limited number of error types;
!   see <xref linkend="errcodes-appendix">.
   </para>
  </note>
  
--- 4876,4887 ----
   <para>
    The fields for schema name, table name, column name, data type name, and
    constraint name are supplied only for a limited number of error types;
!   see <xref linkend="errcodes-appendix">.  Frontends should not assume that
!   the presence of any of these fields guarantees the presence of another
!   field.  Core error sources observe the interrelationships noted above, but
!   user-defined functions may use these fields in other ways.  In the same
!   vein, clients should not assume that these fields denote contemporary
!   objects in the current database.
   </para>
  </note>
  
*** a/src/pl/plpgsql/src/pl_exec.c
--- b/src/pl/plpgsql/src/pl_exec.c
***************
*** 1569,1579 **** exec_stmt_getdiag(PLpgSQL_execstate *estate, 
PLpgSQL_stmt_getdiag *stmt)
--- 1569,1604 ----
                                                        
unpack_sql_state(estate->cur_error->sqlerrcode));
                                break;
  
+                       case PLPGSQL_GETDIAG_COLUMN_NAME:
+                               exec_assign_c_string(estate, var,
+                                                                        
estate->cur_error->column_name);
+                               break;
+ 
+                       case PLPGSQL_GETDIAG_CONSTRAINT_NAME:
+                               exec_assign_c_string(estate, var,
+                                                                        
estate->cur_error->constraint_name);
+                               break;
+ 
+                       case PLPGSQL_GETDIAG_DATATYPE_NAME:
+                               exec_assign_c_string(estate, var,
+                                                                        
estate->cur_error->datatype_name);
+                               break;
+ 
                        case PLPGSQL_GETDIAG_MESSAGE_TEXT:
                                exec_assign_c_string(estate, var,
                                                                         
estate->cur_error->message);
                                break;
  
+                       case PLPGSQL_GETDIAG_TABLE_NAME:
+                               exec_assign_c_string(estate, var,
+                                                                        
estate->cur_error->table_name);
+                               break;
+ 
+                       case PLPGSQL_GETDIAG_SCHEMA_NAME:
+                               exec_assign_c_string(estate, var,
+                                                                        
estate->cur_error->schema_name);
+                               break;
+ 
                        default:
                                elog(ERROR, "unrecognized diagnostic item kind: 
%d",
                                         diag_item->kind);
***************
*** 2799,2804 **** exec_init_tuple_store(PLpgSQL_execstate *estate)
--- 2824,2839 ----
        estate->rettupdesc = rsi->expectedDesc;
  }
  
+ #define SET_RAISE_OPTION_TEXT(opt, name) \
+ do { \
+       if (opt) \
+               ereport(ERROR, \
+                               (errcode(ERRCODE_SYNTAX_ERROR), \
+                                errmsg("RAISE option already specified: %s", \
+                                               name))); \
+       opt = pstrdup(extval); \
+ } while (0)
+ 
  /* ----------
   * exec_stmt_raise                    Build a message and throw it with elog()
   * ----------
***************
*** 2811,2816 **** exec_stmt_raise(PLpgSQL_execstate *estate, 
PLpgSQL_stmt_raise *stmt)
--- 2846,2856 ----
        char       *err_message = NULL;
        char       *err_detail = NULL;
        char       *err_hint = NULL;
+       char       *err_column = NULL;
+       char       *err_constraint = NULL;
+       char       *err_datatype = NULL;
+       char       *err_table = NULL;
+       char       *err_schema = NULL;
        ListCell   *lc;
  
        /* RAISE with no parameters: re-throw current exception */
***************
*** 2927,2954 **** exec_stmt_raise(PLpgSQL_execstate *estate, 
PLpgSQL_stmt_raise *stmt)
                                condname = pstrdup(extval);
                                break;
                        case PLPGSQL_RAISEOPTION_MESSAGE:
!                               if (err_message)
!                                       ereport(ERROR,
!                                                       
(errcode(ERRCODE_SYNTAX_ERROR),
!                                                        errmsg("RAISE option 
already specified: %s",
!                                                                       
"MESSAGE")));
!                               err_message = pstrdup(extval);
                                break;
                        case PLPGSQL_RAISEOPTION_DETAIL:
!                               if (err_detail)
!                                       ereport(ERROR,
!                                                       
(errcode(ERRCODE_SYNTAX_ERROR),
!                                                        errmsg("RAISE option 
already specified: %s",
!                                                                       
"DETAIL")));
!                               err_detail = pstrdup(extval);
                                break;
                        case PLPGSQL_RAISEOPTION_HINT:
!                               if (err_hint)
!                                       ereport(ERROR,
!                                                       
(errcode(ERRCODE_SYNTAX_ERROR),
!                                                        errmsg("RAISE option 
already specified: %s",
!                                                                       
"HINT")));
!                               err_hint = pstrdup(extval);
                                break;
                        default:
                                elog(ERROR, "unrecognized raise option: %d", 
opt->opt_type);
--- 2967,2994 ----
                                condname = pstrdup(extval);
                                break;
                        case PLPGSQL_RAISEOPTION_MESSAGE:
!                               SET_RAISE_OPTION_TEXT(err_message, "MESSAGE");
                                break;
                        case PLPGSQL_RAISEOPTION_DETAIL:
!                               SET_RAISE_OPTION_TEXT(err_detail, "DETAIL");
                                break;
                        case PLPGSQL_RAISEOPTION_HINT:
!                               SET_RAISE_OPTION_TEXT(err_hint, "HINT");
!                               break;
!                       case PLPGSQL_RAISEOPTION_COLUMN:
!                               SET_RAISE_OPTION_TEXT(err_column, "COLUMN");
!                               break;
!                       case PLPGSQL_RAISEOPTION_CONSTRAINT:
!                               SET_RAISE_OPTION_TEXT(err_constraint, 
"CONSTRAINT");
!                               break;
!                       case PLPGSQL_RAISEOPTION_DATATYPE:
!                               SET_RAISE_OPTION_TEXT(err_datatype, "DATATYPE");
!                               break;
!                       case PLPGSQL_RAISEOPTION_TABLE:
!                               SET_RAISE_OPTION_TEXT(err_table, "TABLE");
!                               break;
!                       case PLPGSQL_RAISEOPTION_SCHEMA:
!                               SET_RAISE_OPTION_TEXT(err_schema, "SCHEMA");
                                break;
                        default:
                                elog(ERROR, "unrecognized raise option: %d", 
opt->opt_type);
***************
*** 2982,2988 **** exec_stmt_raise(PLpgSQL_execstate *estate, 
PLpgSQL_stmt_raise *stmt)
                        (err_code ? errcode(err_code) : 0,
                         errmsg_internal("%s", err_message),
                         (err_detail != NULL) ? errdetail_internal("%s", 
err_detail) : 0,
!                        (err_hint != NULL) ? errhint("%s", err_hint) : 0));
  
        estate->err_text = NULL;        /* un-suppress... */
  
--- 3022,3038 ----
                        (err_code ? errcode(err_code) : 0,
                         errmsg_internal("%s", err_message),
                         (err_detail != NULL) ? errdetail_internal("%s", 
err_detail) : 0,
!                        (err_hint != NULL) ? errhint("%s", err_hint) : 0,
!                        (err_column != NULL) ?
!                        err_generic_string(PG_DIAG_COLUMN_NAME, err_column) : 
0,
!                        (err_constraint != NULL) ?
!                        err_generic_string(PG_DIAG_CONSTRAINT_NAME, 
err_constraint) : 0,
!                        (err_datatype != NULL) ?
!                        err_generic_string(PG_DIAG_DATATYPE_NAME, 
err_datatype) : 0,
!                        (err_table != NULL) ?
!                        err_generic_string(PG_DIAG_TABLE_NAME, err_table) : 0,
!                        (err_schema != NULL) ?
!                        err_generic_string(PG_DIAG_SCHEMA_NAME, err_schema) : 
0));
  
        estate->err_text = NULL;        /* un-suppress... */
  
***************
*** 2994,2999 **** exec_stmt_raise(PLpgSQL_execstate *estate, 
PLpgSQL_stmt_raise *stmt)
--- 3044,3059 ----
                pfree(err_detail);
        if (err_hint != NULL)
                pfree(err_hint);
+       if (err_column != NULL)
+               pfree(err_column);
+       if (err_constraint != NULL)
+               pfree(err_constraint);
+       if (err_datatype != NULL)
+               pfree(err_datatype);
+       if (err_table != NULL)
+               pfree(err_table);
+       if (err_schema != NULL)
+               pfree(err_schema);
  
        return PLPGSQL_RC_OK;
  }
*** a/src/pl/plpgsql/src/pl_funcs.c
--- b/src/pl/plpgsql/src/pl_funcs.c
***************
*** 285,292 **** plpgsql_getdiag_kindname(int kind)
--- 285,302 ----
                        return "PG_EXCEPTION_HINT";
                case PLPGSQL_GETDIAG_RETURNED_SQLSTATE:
                        return "RETURNED_SQLSTATE";
+               case PLPGSQL_GETDIAG_COLUMN_NAME:
+                       return "COLUMN_NAME";
+               case PLPGSQL_GETDIAG_CONSTRAINT_NAME:
+                       return "CONSTRAINT_NAME";
+               case PLPGSQL_GETDIAG_DATATYPE_NAME:
+                       return "PG_DATATYPE_NAME";
                case PLPGSQL_GETDIAG_MESSAGE_TEXT:
                        return "MESSAGE_TEXT";
+               case PLPGSQL_GETDIAG_TABLE_NAME:
+                       return "TABLE_NAME";
+               case PLPGSQL_GETDIAG_SCHEMA_NAME:
+                       return "SCHEMA_NAME";
        }
  
        return "unknown";
***************
*** 1317,1322 **** dump_raise(PLpgSQL_stmt_raise *stmt)
--- 1327,1347 ----
                                case PLPGSQL_RAISEOPTION_HINT:
                                        printf("    HINT = ");
                                        break;
+                               case PLPGSQL_RAISEOPTION_COLUMN:
+                                       printf("    COLUMN = ");
+                                       break;
+                               case PLPGSQL_RAISEOPTION_CONSTRAINT:
+                                       printf("    CONSTRAINT = ");
+                                       break;
+                               case PLPGSQL_RAISEOPTION_DATATYPE:
+                                       printf("    DATATYPE = ");
+                                       break;
+                               case PLPGSQL_RAISEOPTION_TABLE:
+                                       printf("    TABLE = ");
+                                       break;
+                               case PLPGSQL_RAISEOPTION_SCHEMA:
+                                       printf("    SCHEMA = ");
+                                       break;
                        }
                        dump_expr(opt->expr);
                        printf("\n");
*** a/src/pl/plpgsql/src/pl_gram.y
--- b/src/pl/plpgsql/src/pl_gram.y
***************
*** 251,260 **** static List                    *read_raise_options(void);
--- 251,265 ----
  %token <keyword>      K_CASE
  %token <keyword>      K_CLOSE
  %token <keyword>      K_COLLATE
+ %token <keyword>      K_COLUMN
+ %token <keyword>      K_COLUMN_NAME
  %token <keyword>      K_CONSTANT
+ %token <keyword>      K_CONSTRAINT
+ %token <keyword>      K_CONSTRAINT_NAME
  %token <keyword>      K_CONTINUE
  %token <keyword>      K_CURRENT
  %token <keyword>      K_CURSOR
+ %token <keyword>      K_DATATYPE
  %token <keyword>      K_DEBUG
  %token <keyword>      K_DECLARE
  %token <keyword>      K_DEFAULT
***************
*** 298,303 **** static List                    *read_raise_options(void);
--- 303,309 ----
  %token <keyword>      K_OPTION
  %token <keyword>      K_OR
  %token <keyword>      K_PERFORM
+ %token <keyword>      K_PG_DATATYPE_NAME
  %token <keyword>      K_PG_EXCEPTION_CONTEXT
  %token <keyword>      K_PG_EXCEPTION_DETAIL
  %token <keyword>      K_PG_EXCEPTION_HINT
***************
*** 311,321 **** static List                    *read_raise_options(void);
--- 317,331 ----
  %token <keyword>      K_REVERSE
  %token <keyword>      K_ROWTYPE
  %token <keyword>      K_ROW_COUNT
+ %token <keyword>      K_SCHEMA
+ %token <keyword>      K_SCHEMA_NAME
  %token <keyword>      K_SCROLL
  %token <keyword>      K_SLICE
  %token <keyword>      K_SQLSTATE
  %token <keyword>      K_STACKED
  %token <keyword>      K_STRICT
+ %token <keyword>      K_TABLE
+ %token <keyword>      K_TABLE_NAME
  %token <keyword>      K_THEN
  %token <keyword>      K_TO
  %token <keyword>      K_TYPE
***************
*** 896,902 **** stmt_getdiag   : K_GET getdiag_area_opt K_DIAGNOSTICS 
getdiag_list ';'
--- 906,917 ----
                                                                case 
PLPGSQL_GETDIAG_ERROR_DETAIL:
                                                                case 
PLPGSQL_GETDIAG_ERROR_HINT:
                                                                case 
PLPGSQL_GETDIAG_RETURNED_SQLSTATE:
+                                                               case 
PLPGSQL_GETDIAG_COLUMN_NAME:
+                                                               case 
PLPGSQL_GETDIAG_CONSTRAINT_NAME:
+                                                               case 
PLPGSQL_GETDIAG_DATATYPE_NAME:
                                                                case 
PLPGSQL_GETDIAG_MESSAGE_TEXT:
+                                                               case 
PLPGSQL_GETDIAG_TABLE_NAME:
+                                                               case 
PLPGSQL_GETDIAG_SCHEMA_NAME:
                                                                        if 
(!new->is_stacked)
                                                                                
ereport(ERROR,
                                                                                
                (errcode(ERRCODE_SYNTAX_ERROR),
***************
*** 971,979 **** getdiag_item :
--- 986,1009 ----
                                                                                
                K_PG_EXCEPTION_CONTEXT, "pg_exception_context"))
                                                        $$ = 
PLPGSQL_GETDIAG_ERROR_CONTEXT;
                                                else if (tok_is_keyword(tok, 
&yylval,
+                                                                               
                K_COLUMN_NAME, "column_name"))
+                                                       $$ = 
PLPGSQL_GETDIAG_COLUMN_NAME;
+                                               else if (tok_is_keyword(tok, 
&yylval,
+                                                                               
                K_CONSTRAINT_NAME, "constraint_name"))
+                                                       $$ = 
PLPGSQL_GETDIAG_CONSTRAINT_NAME;
+                                               else if (tok_is_keyword(tok, 
&yylval,
+                                                                               
                K_PG_DATATYPE_NAME, "pg_datatype_name"))
+                                                       $$ = 
PLPGSQL_GETDIAG_DATATYPE_NAME;
+                                               else if (tok_is_keyword(tok, 
&yylval,
                                                                                
                K_MESSAGE_TEXT, "message_text"))
                                                        $$ = 
PLPGSQL_GETDIAG_MESSAGE_TEXT;
                                                else if (tok_is_keyword(tok, 
&yylval,
+                                                                               
                K_TABLE_NAME, "table_name"))
+                                                       $$ = 
PLPGSQL_GETDIAG_TABLE_NAME;
+                                               else if (tok_is_keyword(tok, 
&yylval,
+                                                                               
                K_SCHEMA_NAME, "schema_name"))
+                                                       $$ = 
PLPGSQL_GETDIAG_SCHEMA_NAME;
+                                               else if (tok_is_keyword(tok, 
&yylval,
                                                                                
                K_RETURNED_SQLSTATE, "returned_sqlstate"))
                                                        $$ = 
PLPGSQL_GETDIAG_RETURNED_SQLSTATE;
                                                else
***************
*** 2231,2239 **** unreserved_keyword   :
--- 2261,2274 ----
                                | K_ALIAS
                                | K_ARRAY
                                | K_BACKWARD
+                               | K_COLUMN
+                               | K_COLUMN_NAME
                                | K_CONSTANT
+                               | K_CONSTRAINT
+                               | K_CONSTRAINT_NAME
                                | K_CURRENT
                                | K_CURSOR
+                               | K_DATATYPE
                                | K_DEBUG
                                | K_DETAIL
                                | K_DUMP
***************
*** 2252,2257 **** unreserved_keyword   :
--- 2287,2293 ----
                                | K_NO
                                | K_NOTICE
                                | K_OPTION
+                               | K_PG_DATATYPE_NAME
                                | K_PG_EXCEPTION_CONTEXT
                                | K_PG_EXCEPTION_DETAIL
                                | K_PG_EXCEPTION_HINT
***************
*** 2263,2272 **** unreserved_keyword   :
--- 2299,2312 ----
                                | K_REVERSE
                                | K_ROW_COUNT
                                | K_ROWTYPE
+                               | K_SCHEMA
+                               | K_SCHEMA_NAME
                                | K_SCROLL
                                | K_SLICE
                                | K_SQLSTATE
                                | K_STACKED
+                               | K_TABLE
+                               | K_TABLE_NAME
                                | K_TYPE
                                | K_USE_COLUMN
                                | K_USE_VARIABLE
***************
*** 3631,3636 **** read_raise_options(void)
--- 3671,3691 ----
                else if (tok_is_keyword(tok, &yylval,
                                                                K_HINT, "hint"))
                        opt->opt_type = PLPGSQL_RAISEOPTION_HINT;
+               else if (tok_is_keyword(tok, &yylval,
+                                                               K_COLUMN, 
"column"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_COLUMN;
+               else if (tok_is_keyword(tok, &yylval,
+                                                               K_CONSTRAINT, 
"constraint"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_CONSTRAINT;
+               else if (tok_is_keyword(tok, &yylval,
+                                                               K_DATATYPE, 
"datatype"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_DATATYPE;
+               else if (tok_is_keyword(tok, &yylval,
+                                                               K_TABLE, 
"table"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_TABLE;
+               else if (tok_is_keyword(tok, &yylval,
+                                                               K_SCHEMA, 
"schema"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_SCHEMA;
                else
                        yyerror("unrecognized RAISE statement option");
  
*** a/src/pl/plpgsql/src/pl_scanner.c
--- b/src/pl/plpgsql/src/pl_scanner.c
***************
*** 109,117 **** static const ScanKeyword unreserved_keywords[] = {
--- 109,122 ----
        PG_KEYWORD("alias", K_ALIAS, UNRESERVED_KEYWORD)
        PG_KEYWORD("array", K_ARRAY, UNRESERVED_KEYWORD)
        PG_KEYWORD("backward", K_BACKWARD, UNRESERVED_KEYWORD)
+       PG_KEYWORD("column", K_COLUMN, UNRESERVED_KEYWORD)
+       PG_KEYWORD("column_name", K_COLUMN_NAME, UNRESERVED_KEYWORD)
        PG_KEYWORD("constant", K_CONSTANT, UNRESERVED_KEYWORD)
+       PG_KEYWORD("constraint", K_CONSTRAINT, UNRESERVED_KEYWORD)
+       PG_KEYWORD("constraint_name", K_CONSTRAINT_NAME, UNRESERVED_KEYWORD)
        PG_KEYWORD("current", K_CURRENT, UNRESERVED_KEYWORD)
        PG_KEYWORD("cursor", K_CURSOR, UNRESERVED_KEYWORD)
+       PG_KEYWORD("datatype", K_DATATYPE, UNRESERVED_KEYWORD)
        PG_KEYWORD("debug", K_DEBUG, UNRESERVED_KEYWORD)
        PG_KEYWORD("detail", K_DETAIL, UNRESERVED_KEYWORD)
        PG_KEYWORD("dump", K_DUMP, UNRESERVED_KEYWORD)
***************
*** 130,135 **** static const ScanKeyword unreserved_keywords[] = {
--- 135,141 ----
        PG_KEYWORD("no", K_NO, UNRESERVED_KEYWORD)
        PG_KEYWORD("notice", K_NOTICE, UNRESERVED_KEYWORD)
        PG_KEYWORD("option", K_OPTION, UNRESERVED_KEYWORD)
+       PG_KEYWORD("pg_datatype_name", K_PG_DATATYPE_NAME, UNRESERVED_KEYWORD)
        PG_KEYWORD("pg_exception_context", K_PG_EXCEPTION_CONTEXT, 
UNRESERVED_KEYWORD)
        PG_KEYWORD("pg_exception_detail", K_PG_EXCEPTION_DETAIL, 
UNRESERVED_KEYWORD)
        PG_KEYWORD("pg_exception_hint", K_PG_EXCEPTION_HINT, UNRESERVED_KEYWORD)
***************
*** 141,150 **** static const ScanKeyword unreserved_keywords[] = {
--- 147,160 ----
        PG_KEYWORD("reverse", K_REVERSE, UNRESERVED_KEYWORD)
        PG_KEYWORD("row_count", K_ROW_COUNT, UNRESERVED_KEYWORD)
        PG_KEYWORD("rowtype", K_ROWTYPE, UNRESERVED_KEYWORD)
+       PG_KEYWORD("schema", K_SCHEMA, UNRESERVED_KEYWORD)
+       PG_KEYWORD("schema_name", K_SCHEMA_NAME, UNRESERVED_KEYWORD)
        PG_KEYWORD("scroll", K_SCROLL, UNRESERVED_KEYWORD)
        PG_KEYWORD("slice", K_SLICE, UNRESERVED_KEYWORD)
        PG_KEYWORD("sqlstate", K_SQLSTATE, UNRESERVED_KEYWORD)
        PG_KEYWORD("stacked", K_STACKED, UNRESERVED_KEYWORD)
+       PG_KEYWORD("table", K_TABLE, UNRESERVED_KEYWORD)
+       PG_KEYWORD("table_name", K_TABLE_NAME, UNRESERVED_KEYWORD)
        PG_KEYWORD("type", K_TYPE, UNRESERVED_KEYWORD)
        PG_KEYWORD("use_column", K_USE_COLUMN, UNRESERVED_KEYWORD)
        PG_KEYWORD("use_variable", K_USE_VARIABLE, UNRESERVED_KEYWORD)
*** a/src/pl/plpgsql/src/plpgsql.h
--- b/src/pl/plpgsql/src/plpgsql.h
***************
*** 128,134 **** enum
        PLPGSQL_GETDIAG_ERROR_DETAIL,
        PLPGSQL_GETDIAG_ERROR_HINT,
        PLPGSQL_GETDIAG_RETURNED_SQLSTATE,
!       PLPGSQL_GETDIAG_MESSAGE_TEXT
  };
  
  /* --------
--- 128,139 ----
        PLPGSQL_GETDIAG_ERROR_DETAIL,
        PLPGSQL_GETDIAG_ERROR_HINT,
        PLPGSQL_GETDIAG_RETURNED_SQLSTATE,
!       PLPGSQL_GETDIAG_COLUMN_NAME,
!       PLPGSQL_GETDIAG_CONSTRAINT_NAME,
!       PLPGSQL_GETDIAG_DATATYPE_NAME,
!       PLPGSQL_GETDIAG_MESSAGE_TEXT,
!       PLPGSQL_GETDIAG_TABLE_NAME,
!       PLPGSQL_GETDIAG_SCHEMA_NAME
  };
  
  /* --------
***************
*** 140,146 **** enum
        PLPGSQL_RAISEOPTION_ERRCODE,
        PLPGSQL_RAISEOPTION_MESSAGE,
        PLPGSQL_RAISEOPTION_DETAIL,
!       PLPGSQL_RAISEOPTION_HINT
  };
  
  /* --------
--- 145,156 ----
        PLPGSQL_RAISEOPTION_ERRCODE,
        PLPGSQL_RAISEOPTION_MESSAGE,
        PLPGSQL_RAISEOPTION_DETAIL,
!       PLPGSQL_RAISEOPTION_HINT,
!       PLPGSQL_RAISEOPTION_COLUMN,
!       PLPGSQL_RAISEOPTION_CONSTRAINT,
!       PLPGSQL_RAISEOPTION_DATATYPE,
!       PLPGSQL_RAISEOPTION_TABLE,
!       PLPGSQL_RAISEOPTION_SCHEMA
  };
  
  /* --------
*** a/src/test/regress/expected/plpgsql.out
--- b/src/test/regress/expected/plpgsql.out
***************
*** 3974,3979 **** select raise_test();
--- 3974,4013 ----
  NOTICE:  22012
  ERROR:  substitute message
  drop function raise_test();
+ -- test passing column_name, constraint_name, datatype_name, table_name
+ -- and schema_name error fields
+ create or replace function stacked_diagnostics_test() returns void as $$
+ declare _column_name text;
+         _constraint_name text;
+         _datatype_name text;
+         _table_name text;
+         _schema_name text;
+ begin
+   raise exception using
+     column = '>>some column name<<',
+     constraint = '>>some constraint name<<',
+     datatype = '>>some datatype name<<',
+     table = '>>some table name<<',
+     schema = '>>some schema name<<';
+ exception when others then
+   get stacked diagnostics
+         _column_name = column_name,
+         _constraint_name = constraint_name,
+         _datatype_name = pg_datatype_name,
+         _table_name = table_name,
+         _schema_name = schema_name;
+   raise notice 'column %, constraint %, type %, table %, schema %',
+     _column_name, _constraint_name, _datatype_name, _table_name, _schema_name;
+ end;
+ $$ language plpgsql;
+ select stacked_diagnostics_test();
+ NOTICE:  column >>some column name<<, constraint >>some constraint name<<, 
type >>some datatype name<<, table >>some table name<<, schema >>some schema 
name<<
+  stacked_diagnostics_test 
+ --------------------------
+  
+ (1 row)
+ 
+ drop function stacked_diagnostics_test();
  -- test CASE statement
  create or replace function case_test(bigint) returns text as $$
  declare a int = 10;
*** a/src/test/regress/sql/plpgsql.sql
--- b/src/test/regress/sql/plpgsql.sql
***************
*** 3262,3267 **** select raise_test();
--- 3262,3299 ----
  
  drop function raise_test();
  
+ -- test passing column_name, constraint_name, datatype_name, table_name
+ -- and schema_name error fields
+ 
+ create or replace function stacked_diagnostics_test() returns void as $$
+ declare _column_name text;
+         _constraint_name text;
+         _datatype_name text;
+         _table_name text;
+         _schema_name text;
+ begin
+   raise exception using
+     column = '>>some column name<<',
+     constraint = '>>some constraint name<<',
+     datatype = '>>some datatype name<<',
+     table = '>>some table name<<',
+     schema = '>>some schema name<<';
+ exception when others then
+   get stacked diagnostics
+         _column_name = column_name,
+         _constraint_name = constraint_name,
+         _datatype_name = pg_datatype_name,
+         _table_name = table_name,
+         _schema_name = schema_name;
+   raise notice 'column %, constraint %, type %, table %, schema %',
+     _column_name, _constraint_name, _datatype_name, _table_name, _schema_name;
+ end;
+ $$ language plpgsql;
+ 
+ select stacked_diagnostics_test();
+ 
+ drop function stacked_diagnostics_test();
+ 
  -- test CASE statement
  
  create or replace function case_test(bigint) returns text as $$
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to