]> granicus.if.org Git - postgresql/commitdiff
Expose object name error fields in PL/pgSQL.
authorNoah Misch <noah@leadboat.com>
Wed, 3 Jul 2013 11:29:23 +0000 (07:29 -0400)
committerNoah Misch <noah@leadboat.com>
Wed, 3 Jul 2013 11:30:15 +0000 (07:30 -0400)
Specifically, permit attaching them to the error in RAISE and retrieving
them from a caught error in GET STACKED DIAGNOSTICS.  RAISE enforces
nothing about the content of the fields; for its purposes, they are just
additional string fields.  Consequently, clarify in the protocol and
libpq documentation that the usual relationships between error fields,
like a schema name appearing wherever a table name appears, are not
universal.  This freedom has other applications; consider a FDW
propagating an error from an RDBMS having no schema support.

Back-patch to 9.3, where core support for the error fields was
introduced.  This prevents the confusion of having a release where libpq
exposes the fields and PL/pgSQL does not.

Pavel Stehule, lexical revisions by Noah Misch.

doc/src/sgml/libpq.sgml
doc/src/sgml/plpgsql.sgml
doc/src/sgml/protocol.sgml
src/pl/plpgsql/src/pl_exec.c
src/pl/plpgsql/src/pl_funcs.c
src/pl/plpgsql/src/pl_gram.y
src/pl/plpgsql/src/pl_scanner.c
src/pl/plpgsql/src/plpgsql.h
src/test/regress/expected/plpgsql.out
src/test/regress/sql/plpgsql.sql

index 07db5e4d3568db3555c280d7872badcf9cd914ce..a3c7de8b89b139ffeffb22f181b7b97d54e277ac 100644 (file)
@@ -2712,9 +2712,9 @@ 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.)
+            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,9 +2723,9 @@ 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.)
+            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,9 +2734,9 @@ 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.)
+            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,11 +2745,11 @@ 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.)
+            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,9 +2787,14 @@ 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">.
+         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>
 
index 19498c6767688e6e930dcdc880356f14eacdb92b..6fffec18b7081081a0bea07ad836162a2b5e9206 100644 (file)
@@ -2664,11 +2664,36 @@ GET STACKED DIAGNOSTICS <replaceable>variable</replaceable> = <replaceable>item<
          <entry>text</entry>
          <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>
@@ -3355,6 +3380,17 @@ RAISE NOTICE 'Calling cs_create_job(%)', v_job_id;
         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>
 
index f1cafa59d24e0590c6e704c058ba0a4f204ab776..0b2e60eeb13182d34362f1b3376474084cfdc690 100644 (file)
@@ -4788,8 +4788,8 @@ 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.)
+        name of the table.  (Refer to the schema name field for the name of
+        the table's schema.)
 </para>
 </listitem>
 </varlistentry>
@@ -4801,8 +4801,8 @@ 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.)
+        the name of the column.  (Refer to the schema and table name fields to
+        identify the table.)
 </para>
 </listitem>
 </varlistentry>
@@ -4814,8 +4814,8 @@ 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.)
+        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,10 +4827,10 @@ 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.)
+        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,7 +4876,12 @@ 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">.
+  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>
 
index 70e67d9eb70ef0dae58504f64d2ed52feae3c77f..57789fc365b140d4df67c1b39e8ce4fcd7bad4b6 100644 (file)
@@ -1569,11 +1569,36 @@ exec_stmt_getdiag(PLpgSQL_execstate *estate, PLpgSQL_stmt_getdiag *stmt)
                                                        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,6 +2824,16 @@ exec_init_tuple_store(PLpgSQL_execstate *estate)
        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,6 +2846,11 @@ exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
        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,28 +2967,28 @@ 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);
+                               SET_RAISE_OPTION_TEXT(err_message, "MESSAGE");
                                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);
+                               SET_RAISE_OPTION_TEXT(err_detail, "DETAIL");
                                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);
+                               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,7 +3022,17 @@ 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));
+                        (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,6 +3044,16 @@ exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
                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;
 }
index 9d561c2322e4aee798e09cf1dab33b1164cc6435..87e528fe5bfdd4e820f581dfb72ec43905b24ebd 100644 (file)
@@ -285,8 +285,18 @@ plpgsql_getdiag_kindname(int kind)
                        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,6 +1327,21 @@ dump_raise(PLpgSQL_stmt_raise *stmt)
                                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");
index a790ee30ea9546ef74ed922fa2d3ce0b61c036ad..086987a58a41e802b4322bcb02efd5b312d6d9a6 100644 (file)
@@ -251,10 +251,15 @@ static    List                    *read_raise_options(void);
 %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,6 +303,7 @@ static      List                    *read_raise_options(void);
 %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,11 +317,15 @@ static    List                    *read_raise_options(void);
 %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,7 +906,12 @@ stmt_getdiag       : K_GET getdiag_area_opt K_DIAGNOSTICS getdiag_list ';'
                                                                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),
@@ -970,9 +985,24 @@ getdiag_item :
                                                else if (tok_is_keyword(tok, &yylval,
                                                                                                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;
@@ -2231,9 +2261,14 @@ unreserved_keyword       :
                                | 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,6 +2287,7 @@ unreserved_keyword        :
                                | K_NO
                                | K_NOTICE
                                | K_OPTION
+                               | K_PG_DATATYPE_NAME
                                | K_PG_EXCEPTION_CONTEXT
                                | K_PG_EXCEPTION_DETAIL
                                | K_PG_EXCEPTION_HINT
@@ -2263,10 +2299,14 @@ unreserved_keyword      :
                                | 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,6 +3671,21 @@ read_raise_options(void)
                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");
 
index 9b6f57e723fcb5a5bf218a3950dc2239982a4b4d..84c51260d2554a80de77f92074462cc4a415a308 100644 (file)
@@ -109,9 +109,14 @@ static const ScanKeyword unreserved_keywords[] = {
        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,6 +135,7 @@ static const ScanKeyword unreserved_keywords[] = {
        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,10 +147,14 @@ static const ScanKeyword unreserved_keywords[] = {
        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)
index 5cc44a0e1c6d243bdc7157538698225277fb2570..cdf39929e0f85baa48bbad0e88627b63c6f069d6 100644 (file)
@@ -128,7 +128,12 @@ enum
        PLPGSQL_GETDIAG_ERROR_DETAIL,
        PLPGSQL_GETDIAG_ERROR_HINT,
        PLPGSQL_GETDIAG_RETURNED_SQLSTATE,
-       PLPGSQL_GETDIAG_MESSAGE_TEXT
+       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,7 +145,12 @@ enum
        PLPGSQL_RAISEOPTION_ERRCODE,
        PLPGSQL_RAISEOPTION_MESSAGE,
        PLPGSQL_RAISEOPTION_DETAIL,
-       PLPGSQL_RAISEOPTION_HINT
+       PLPGSQL_RAISEOPTION_HINT,
+       PLPGSQL_RAISEOPTION_COLUMN,
+       PLPGSQL_RAISEOPTION_CONSTRAINT,
+       PLPGSQL_RAISEOPTION_DATATYPE,
+       PLPGSQL_RAISEOPTION_TABLE,
+       PLPGSQL_RAISEOPTION_SCHEMA
 };
 
 /* --------
index fdd8c6b466ebb6e45fa57ee952c03bb029fd261d..b413267b1b30108e5298b7e8a25852d849d8bf71 100644 (file)
@@ -3974,6 +3974,40 @@ select raise_test();
 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;
index 017bd0b63f195152321b87d389a7e87e1381cbde..9ef9deab2e49de0de05f453fa35681d34e4fe08a 100644 (file)
@@ -3262,6 +3262,38 @@ select raise_test();
 
 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 $$