proposal: enable new error fields in plpgsql (9.4)

Started by Pavel Stehulealmost 13 years ago23 messages
#1Pavel Stehule
pavel.stehule@gmail.com
1 attachment(s)

Hello

now a most "hard" work is done and I would to enable access to new
error fields from plpgsql.

these new fields are column_name, constraint_name, datatype_name,
table_name and schema_name.

This proposal has impact on two plpgsql statements - RAISE and GET
STACKED DIAGNOSTICS.

I am sending initial implementation

Comments, notes?

Regards

Pavel

Attachments:

enhanced_error_fields_plpgsql_initial.patchapplication/octet-stream; name=enhanced_error_fields_plpgsql_initial.patchDownload
*** a/doc/src/sgml/plpgsql.sgml
--- b/doc/src/sgml/plpgsql.sgml
***************
*** 2635,2645 **** GET STACKED DIAGNOSTICS <replaceable>variable</replaceable> = <replaceable>item<
--- 2635,2670 ----
           <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>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>
***************
*** 3325,3330 **** RAISE NOTICE 'Calling cs_create_job(%)', v_job_id;
--- 3350,3390 ----
          five-character SQLSTATE code.</para>
        </listitem>
       </varlistentry>
+ 
+      <varlistentry>
+       <term><literal>COLUMN_NAME</literal></term>
+       <listitem>
+        <para>Specifies the column name field of exception</para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
+       <term><literal>CONSTRAINT_NAME</literal></term>
+       <listitem>
+        <para>Specifies the constraint name field of exception</para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
+       <term><literal>DATATYPE_NAME</literal></term>
+       <listitem>
+        <para>Specifies the data type name field of exception</para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
+       <term><literal>TABLE_NAME</literal></term>
+       <listitem>
+        <para>Specifies the table name field of exception</para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
+       <term><literal>SCHEMA_NAME</literal></term>
+       <listitem>
+        <para>Specifies the schema name field of exception</para>
+       </listitem>
+      </varlistentry>
      </variablelist>
     </para>
  
*** 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_name = NULL;
+ 	char	   *err_constraint_name = NULL;
+ 	char	   *err_datatype_name = NULL;
+ 	char	   *err_table_name = NULL;
+ 	char	   *err_schema_name = NULL;
  	ListCell   *lc;
  
  	/* RAISE with no parameters: re-throw current exception */
***************
*** 2926,2955 **** exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
  				err_code = plpgsql_recognize_err_condition(extval, true);
  				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);
  		}
--- 2966,3004 ----
  				err_code = plpgsql_recognize_err_condition(extval, true);
  				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_NAME:
! 				SET_RAISE_OPTION_TEXT(err_column_name, "COLUMN_NAME");
  				break;
+ 
+ 			case PLPGSQL_RAISEOPTION_CONSTRAINT_NAME:
+ 				SET_RAISE_OPTION_TEXT(err_constraint_name, "CONSTRAINT_NAME");
+ 				break;
+ 
+ 			case PLPGSQL_RAISEOPTION_DATATYPE_NAME:
+ 				SET_RAISE_OPTION_TEXT(err_datatype_name, "DATATYPE_NAME");
+ 				break;
+ 
+ 			case PLPGSQL_RAISEOPTION_TABLE_NAME:
+ 				SET_RAISE_OPTION_TEXT(err_table_name, "TABLE_NAME");
+ 				break;
+ 
+ 			case PLPGSQL_RAISEOPTION_SCHEMA_NAME:
+ 				SET_RAISE_OPTION_TEXT(err_schema_name, "SCHEMA_NAME");
+ 				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... */
  
--- 3031,3047 ----
  			(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_name != NULL) ?
! 				 err_generic_string(PG_DIAG_COLUMN_NAME, err_column_name) : 0,
! 			 (err_constraint_name != NULL) ?
! 				 err_generic_string(PG_DIAG_CONSTRAINT_NAME, err_constraint_name) : 0,
! 			 (err_datatype_name != NULL) ?
! 				 err_generic_string(PG_DIAG_DATATYPE_NAME, err_datatype_name) : 0,
! 			 (err_table_name != NULL) ?
! 				 err_generic_string(PG_DIAG_TABLE_NAME, err_table_name) : 0,
! 			 (err_schema_name != NULL) ?
! 				 err_generic_string(PG_DIAG_SCHEMA_NAME, err_schema_name) : 0));
  
  	estate->err_text = NULL;	/* un-suppress... */
  
***************
*** 2994,2999 **** exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
--- 3053,3068 ----
  		pfree(err_detail);
  	if (err_hint != NULL)
  		pfree(err_hint);
+ 	if (err_column_name != NULL)
+ 		pfree(err_column_name);
+ 	if (err_constraint_name != NULL)
+ 		pfree(err_constraint_name);
+ 	if (err_datatype_name != NULL)
+ 		pfree(err_datatype_name);
+ 	if (err_table_name != NULL)
+ 		pfree(err_table_name);
+ 	if (err_schema_name != NULL)
+ 		pfree(err_schema_name);
  
  	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 "DATATYPE_TEXT";
  		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_NAME:
+ 					printf("    COLUMN_NAME = ");
+ 					break;
+ 				case PLPGSQL_RAISEOPTION_CONSTRAINT_NAME:
+ 					printf("    CONSTRAINT_NAME = ");
+ 					break;
+ 				case PLPGSQL_RAISEOPTION_DATATYPE_NAME:
+ 					printf("    DATATYPE_NAME = ");
+ 					break;
+ 				case PLPGSQL_RAISEOPTION_TABLE_NAME:
+ 					printf("    TABLE_NAME = ");
+ 					break;
+ 				case PLPGSQL_RAISEOPTION_SCHEMA_NAME:
+ 					printf("    SCHEMA_NAME = ");
+ 					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,263 ----
  %token <keyword>	K_CASE
  %token <keyword>	K_CLOSE
  %token <keyword>	K_COLLATE
+ %token <keyword>	K_COLUMN_NAME
  %token <keyword>	K_CONSTANT
+ %token <keyword>	K_CONSTRAINT_NAME
  %token <keyword>	K_CONTINUE
  %token <keyword>	K_CURRENT
  %token <keyword>	K_CURSOR
+ %token <keyword>	K_DATATYPE_NAME
  %token <keyword>	K_DEBUG
  %token <keyword>	K_DECLARE
  %token <keyword>	K_DEFAULT
***************
*** 311,321 **** static	List			*read_raise_options(void);
--- 314,326 ----
  %token <keyword>	K_REVERSE
  %token <keyword>	K_ROWTYPE
  %token <keyword>	K_ROW_COUNT
+ %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_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 ';'
--- 901,912 ----
  								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 :
--- 981,1004 ----
  												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_DATATYPE_NAME, "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	:
--- 2256,2267 ----
  				| K_ALIAS
  				| K_ARRAY
  				| K_BACKWARD
+ 				| K_COLUMN_NAME
  				| K_CONSTANT
+ 				| K_CONSTRAINT_NAME
  				| K_CURRENT
  				| K_CURSOR
+ 				| K_DATATYPE_NAME
  				| K_DEBUG
  				| K_DETAIL
  				| K_DUMP
***************
*** 2263,2268 **** unreserved_keyword	:
--- 2291,2298 ----
  				| K_REVERSE
  				| K_ROW_COUNT
  				| K_ROWTYPE
+ 				| K_TABLE_NAME
+ 				| K_SCHEMA_NAME
  				| K_SCROLL
  				| K_SLICE
  				| K_SQLSTATE
***************
*** 3631,3637 **** read_raise_options(void)
--- 3661,3683 ----
  		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_NAME, "column_name"))
+ 			opt->opt_type = PLPGSQL_RAISEOPTION_COLUMN_NAME;
+ 		else if (tok_is_keyword(tok, &yylval,
+ 								K_CONSTRAINT_NAME, "constraint_name"))
+ 			opt->opt_type = PLPGSQL_RAISEOPTION_CONSTRAINT_NAME;
+ 		else if (tok_is_keyword(tok, &yylval,
+ 								K_DATATYPE_NAME, "datatype_name"))
+ 			opt->opt_type = PLPGSQL_RAISEOPTION_DATATYPE_NAME;
+ 		else if (tok_is_keyword(tok, &yylval,
+ 								K_TABLE_NAME, "table_name"))
+ 			opt->opt_type = PLPGSQL_RAISEOPTION_TABLE_NAME;
+ 		else if (tok_is_keyword(tok, &yylval,
+ 								K_SCHEMA_NAME, "schema_name"))
+ 			opt->opt_type = PLPGSQL_RAISEOPTION_SCHEMA_NAME;
  		else
+ 		
  			yyerror("unrecognized RAISE statement option");
  
  		tok = yylex();
*** a/src/pl/plpgsql/src/pl_scanner.c
--- b/src/pl/plpgsql/src/pl_scanner.c
***************
*** 109,117 **** static const ScanKeyword unreserved_keywords[] = {
--- 109,120 ----
  	PG_KEYWORD("alias", K_ALIAS, UNRESERVED_KEYWORD)
  	PG_KEYWORD("array", K_ARRAY, UNRESERVED_KEYWORD)
  	PG_KEYWORD("backward", K_BACKWARD, UNRESERVED_KEYWORD)
+ 	PG_KEYWORD("column_name", K_COLUMN_NAME, UNRESERVED_KEYWORD)
  	PG_KEYWORD("constant", K_CONSTANT, 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_name", K_DATATYPE_NAME, UNRESERVED_KEYWORD)
  	PG_KEYWORD("debug", K_DEBUG, UNRESERVED_KEYWORD)
  	PG_KEYWORD("detail", K_DETAIL, UNRESERVED_KEYWORD)
  	PG_KEYWORD("dump", K_DUMP, UNRESERVED_KEYWORD)
***************
*** 141,150 **** static const ScanKeyword unreserved_keywords[] = {
--- 144,155 ----
  	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_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_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_NAME,
! 	PLPGSQL_RAISEOPTION_CONSTRAINT_NAME,
! 	PLPGSQL_RAISEOPTION_DATATYPE_NAME,
! 	PLPGSQL_RAISEOPTION_TABLE_NAME,
! 	PLPGSQL_RAISEOPTION_SCHEMA_NAME
  };
  
  /* --------
*** 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_name = '>>some column name<<',
+     constraint_name = '>>some constraint name<<',
+     datatype_name = '>>some datatype name<<',
+     table_name = '>>some table name<<',
+     schema_name = '>>some schema name<<';
+ exception when others then
+   get stacked diagnostics
+         _column_name = column_name,
+         _constraint_name = constraint_name,
+         _datatype_name = datatype_name,
+         _table_name = table_name,
+         _schema_name = schema_name;
+   raise notice 'column_name: %, constraint_name: %, datatype_name: %, table_name: %, schema_name: %',
+     _column_name, _constraint_name, _datatype_name, _table_name, _schema_name;
+ end;
+ $$ language plpgsql;
+ select stacked_diagnostics_test();
+ NOTICE:  column_name: >>some column name<<, constraint_name: >>some constraint name<<, datatype_name: >>some datatype name<<, table_name: >>some table name<<, schema_name: >>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_name = '>>some column name<<',
+     constraint_name = '>>some constraint name<<',
+     datatype_name = '>>some datatype name<<',
+     table_name = '>>some table name<<',
+     schema_name = '>>some schema name<<';
+ exception when others then
+   get stacked diagnostics
+         _column_name = column_name,
+         _constraint_name = constraint_name,
+         _datatype_name = datatype_name,
+         _table_name = table_name,
+         _schema_name = schema_name;
+   raise notice 'column_name: %, constraint_name: %, datatype_name: %, table_name: %, schema_name: %',
+     _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 $$
#2Marko Tiikkaja
pgmail@joh.to
In reply to: Pavel Stehule (#1)
Re: proposal: enable new error fields in plpgsql (9.4)

On 2/1/13 1:47 PM, Pavel Stehule wrote:

now a most "hard" work is done and I would to enable access to new
error fields from plpgsql.

Is there a compelling reason why we wouldn't provide these already in 9.3?

Regards,
Marko Tiikkaja

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#3Pavel Stehule
pavel.stehule@gmail.com
In reply to: Marko Tiikkaja (#2)
Re: proposal: enable new error fields in plpgsql (9.4)

2013/2/1 Marko Tiikkaja <pgmail@joh.to>:

On 2/1/13 1:47 PM, Pavel Stehule wrote:

now a most "hard" work is done and I would to enable access to new
error fields from plpgsql.

Is there a compelling reason why we wouldn't provide these already in 9.3?

a time for assign to last commitfest is out.

this patch is relative simple and really close to enhanced error
fields feature - but depends if some from commiters will have a time
for commit to 9.3 - so I am expecting primary target 9.4, but I am not
be angry if it will be commited early.

Regards

Pavel

Regards,
Marko Tiikkaja

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#4Peter Eisentraut
peter_e@gmx.net
In reply to: Pavel Stehule (#3)
Re: proposal: enable new error fields in plpgsql (9.4)

On 2/1/13 8:00 AM, Pavel Stehule wrote:

2013/2/1 Marko Tiikkaja <pgmail@joh.to>:

On 2/1/13 1:47 PM, Pavel Stehule wrote:

now a most "hard" work is done and I would to enable access to new
error fields from plpgsql.

Is there a compelling reason why we wouldn't provide these already in 9.3?

a time for assign to last commitfest is out.

this patch is relative simple and really close to enhanced error
fields feature - but depends if some from commiters will have a time
for commit to 9.3 - so I am expecting primary target 9.4, but I am not
be angry if it will be commited early.

If we don't have access to those fields on PL/pgSQL, what was the point
of the patch to begin with? Surely, accessing them from C wasn't the
main use case?

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#5Pavel Stehule
pavel.stehule@gmail.com
In reply to: Peter Eisentraut (#4)
Re: proposal: enable new error fields in plpgsql (9.4)

2013/2/1 Peter Eisentraut <peter_e@gmx.net>:

On 2/1/13 8:00 AM, Pavel Stehule wrote:

2013/2/1 Marko Tiikkaja <pgmail@joh.to>:

On 2/1/13 1:47 PM, Pavel Stehule wrote:

now a most "hard" work is done and I would to enable access to new
error fields from plpgsql.

Is there a compelling reason why we wouldn't provide these already in 9.3?

a time for assign to last commitfest is out.

this patch is relative simple and really close to enhanced error
fields feature - but depends if some from commiters will have a time
for commit to 9.3 - so I am expecting primary target 9.4, but I am not
be angry if it will be commited early.

If we don't have access to those fields on PL/pgSQL, what was the point
of the patch to begin with? Surely, accessing them from C wasn't the
main use case?

These fields are available for application developers now. But is a
true, so without this patch, GET STACKED DIAGNOSTICS statement will
not be fully consistent, because some fields are accessible and others
not

Pavel

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#6Pavel Stehule
pavel.stehule@gmail.com
In reply to: Pavel Stehule (#5)
Re: proposal: enable new error fields in plpgsql (9.4)

2013/2/1 Pavel Stehule <pavel.stehule@gmail.com>:

2013/2/1 Peter Eisentraut <peter_e@gmx.net>:

On 2/1/13 8:00 AM, Pavel Stehule wrote:

2013/2/1 Marko Tiikkaja <pgmail@joh.to>:

On 2/1/13 1:47 PM, Pavel Stehule wrote:

now a most "hard" work is done and I would to enable access to new
error fields from plpgsql.

Is there a compelling reason why we wouldn't provide these already in 9.3?

a time for assign to last commitfest is out.

this patch is relative simple and really close to enhanced error
fields feature - but depends if some from commiters will have a time
for commit to 9.3 - so I am expecting primary target 9.4, but I am not
be angry if it will be commited early.

If we don't have access to those fields on PL/pgSQL, what was the point
of the patch to begin with? Surely, accessing them from C wasn't the
main use case?

These fields are available for application developers now. But is a
true, so without this patch, GET STACKED DIAGNOSTICS statement will
not be fully consistent, because some fields are accessible and others
not

there is one stronger argument for commit this patch now. With this
patch, we are able to wrote regression tests for new fields via
plpgsql.

Regards

Pavel

Pavel

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#7Rushabh Lathia
rushabh.lathia@gmail.com
In reply to: Pavel Stehule (#6)
Re: proposal: enable new error fields in plpgsql (9.4)

Hi Pavel,

I gone through the discussion over here and found that with this patch we
enable the new error fields in plpgsql. Its a simple patch to expose the new
error fields in plpgsql.

Patch gets applied cleanly. make and make install too went smooth. make
check
was smooth too. Patch also include test coverage

I tested the functionality with manual test and its woking as expected.

BTW in the patch I found one additional new like in read_raise_options():

@@ -3631,7 +3661,23 @@ 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_NAME, "column_name"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_COLUMN_NAME;
+               else if (tok_is_keyword(tok, &yylval,
+
K_CONSTRAINT_NAME, "constraint_name"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_CONSTRAINT_NAME;
+               else if (tok_is_keyword(tok, &yylval,
+
K_DATATYPE_NAME, "datatype_name"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_DATATYPE_NAME;
+               else if (tok_is_keyword(tok, &yylval,
+
K_TABLE_NAME, "table_name"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_TABLE_NAME;
+               else if (tok_is_keyword(tok, &yylval,
+
K_SCHEMA_NAME, "schema_name"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_SCHEMA_NAME;
                else
+
                        yyerror("unrecognized RAISE statement option");

can you please remove that.

Apart from that patch looks good to me.

Thanks,
Rushabh

On Fri, Feb 1, 2013 at 7:29 PM, Pavel Stehule <pavel.stehule@gmail.com>wrote:

2013/2/1 Pavel Stehule <pavel.stehule@gmail.com>:

2013/2/1 Peter Eisentraut <peter_e@gmx.net>:

On 2/1/13 8:00 AM, Pavel Stehule wrote:

2013/2/1 Marko Tiikkaja <pgmail@joh.to>:

On 2/1/13 1:47 PM, Pavel Stehule wrote:

now a most "hard" work is done and I would to enable access to new
error fields from plpgsql.

Is there a compelling reason why we wouldn't provide these already in

9.3?

a time for assign to last commitfest is out.

this patch is relative simple and really close to enhanced error
fields feature - but depends if some from commiters will have a time
for commit to 9.3 - so I am expecting primary target 9.4, but I am not
be angry if it will be commited early.

If we don't have access to those fields on PL/pgSQL, what was the point
of the patch to begin with? Surely, accessing them from C wasn't the
main use case?

These fields are available for application developers now. But is a
true, so without this patch, GET STACKED DIAGNOSTICS statement will
not be fully consistent, because some fields are accessible and others
not

there is one stronger argument for commit this patch now. With this
patch, we are able to wrote regression tests for new fields via
plpgsql.

Regards

Pavel

Pavel

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

--
Rushabh Lathia

#8Pavel Stehule
pavel.stehule@gmail.com
In reply to: Rushabh Lathia (#7)
Re: proposal: enable new error fields in plpgsql (9.4)

2013/6/25 Rushabh Lathia <rushabh.lathia@gmail.com>:

Hi Pavel,

I gone through the discussion over here and found that with this patch we
enable the new error fields in plpgsql. Its a simple patch to expose the new
error fields in plpgsql.

Patch gets applied cleanly. make and make install too went smooth. make
check
was smooth too. Patch also include test coverage

I tested the functionality with manual test and its woking as expected.

BTW in the patch I found one additional new like in read_raise_options():

@@ -3631,7 +3661,23 @@ 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_NAME, "column_name"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_COLUMN_NAME;
+               else if (tok_is_keyword(tok, &yylval,
+
K_CONSTRAINT_NAME, "constraint_name"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_CONSTRAINT_NAME;
+               else if (tok_is_keyword(tok, &yylval,
+
K_DATATYPE_NAME, "datatype_name"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_DATATYPE_NAME;
+               else if (tok_is_keyword(tok, &yylval,
+
K_TABLE_NAME, "table_name"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_TABLE_NAME;
+               else if (tok_is_keyword(tok, &yylval,
+
K_SCHEMA_NAME, "schema_name"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_SCHEMA_NAME;
else
+
yyerror("unrecognized RAISE statement option");

can you please remove that.

No, these fields are there as was proposed - it enhance possibilities
to PLpgSQL developers - they can use these fields for custom
exceptions. It is same like possibility to specify SQLCODE, MESSAGE,
HINT in current RAISE statement implementation.

Why you dislike it?

Regards

Pavel

Apart from that patch looks good to me.

Thanks,
Rushabh

On Fri, Feb 1, 2013 at 7:29 PM, Pavel Stehule <pavel.stehule@gmail.com>
wrote:

2013/2/1 Pavel Stehule <pavel.stehule@gmail.com>:

2013/2/1 Peter Eisentraut <peter_e@gmx.net>:

On 2/1/13 8:00 AM, Pavel Stehule wrote:

2013/2/1 Marko Tiikkaja <pgmail@joh.to>:

On 2/1/13 1:47 PM, Pavel Stehule wrote:

now a most "hard" work is done and I would to enable access to new
error fields from plpgsql.

Is there a compelling reason why we wouldn't provide these already in
9.3?

a time for assign to last commitfest is out.

this patch is relative simple and really close to enhanced error
fields feature - but depends if some from commiters will have a time
for commit to 9.3 - so I am expecting primary target 9.4, but I am not
be angry if it will be commited early.

If we don't have access to those fields on PL/pgSQL, what was the point
of the patch to begin with? Surely, accessing them from C wasn't the
main use case?

These fields are available for application developers now. But is a
true, so without this patch, GET STACKED DIAGNOSTICS statement will
not be fully consistent, because some fields are accessible and others
not

there is one stronger argument for commit this patch now. With this
patch, we are able to wrote regression tests for new fields via
plpgsql.

Regards

Pavel

Pavel

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

--
Rushabh Lathia

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#9Rushabh Lathia
rushabh.lathia@gmail.com
In reply to: Pavel Stehule (#8)
Re: proposal: enable new error fields in plpgsql (9.4)

On Tue, Jun 25, 2013 at 2:41 PM, Pavel Stehule <pavel.stehule@gmail.com>wrote:

2013/6/25 Rushabh Lathia <rushabh.lathia@gmail.com>:

Hi Pavel,

I gone through the discussion over here and found that with this patch we
enable the new error fields in plpgsql. Its a simple patch to expose the

new

error fields in plpgsql.

Patch gets applied cleanly. make and make install too went smooth. make
check
was smooth too. Patch also include test coverage

I tested the functionality with manual test and its woking as expected.

BTW in the patch I found one additional new like in read_raise_options():

@@ -3631,7 +3661,23 @@ 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_NAME, "column_name"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_COLUMN_NAME;
+               else if (tok_is_keyword(tok, &yylval,
+
K_CONSTRAINT_NAME, "constraint_name"))
+                       opt->opt_type =

PLPGSQL_RAISEOPTION_CONSTRAINT_NAME;

+               else if (tok_is_keyword(tok, &yylval,
+
K_DATATYPE_NAME, "datatype_name"))
+                       opt->opt_type =

PLPGSQL_RAISEOPTION_DATATYPE_NAME;

+               else if (tok_is_keyword(tok, &yylval,
+
K_TABLE_NAME, "table_name"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_TABLE_NAME;
+               else if (tok_is_keyword(tok, &yylval,
+
K_SCHEMA_NAME, "schema_name"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_SCHEMA_NAME;
else
+
yyerror("unrecognized RAISE statement option");

can you please remove that.

No, these fields are there as was proposed - it enhance possibilities
to PLpgSQL developers - they can use these fields for custom
exceptions. It is same like possibility to specify SQLCODE, MESSAGE,
HINT in current RAISE statement implementation.

Why you dislike it?

Seems like some confusion.

I noticed additional new line which has been added into your patch in
function
read_raise_options()::pl_gram.y @ line number 3680. And in the earlier mail
thats what I asked to remove.

Regards

Pavel

Apart from that patch looks good to me.

Thanks,
Rushabh

On Fri, Feb 1, 2013 at 7:29 PM, Pavel Stehule <pavel.stehule@gmail.com>
wrote:

2013/2/1 Pavel Stehule <pavel.stehule@gmail.com>:

2013/2/1 Peter Eisentraut <peter_e@gmx.net>:

On 2/1/13 8:00 AM, Pavel Stehule wrote:

2013/2/1 Marko Tiikkaja <pgmail@joh.to>:

On 2/1/13 1:47 PM, Pavel Stehule wrote:

now a most "hard" work is done and I would to enable access to new
error fields from plpgsql.

Is there a compelling reason why we wouldn't provide these already

in

9.3?

a time for assign to last commitfest is out.

this patch is relative simple and really close to enhanced error
fields feature - but depends if some from commiters will have a time
for commit to 9.3 - so I am expecting primary target 9.4, but I am

not

be angry if it will be commited early.

If we don't have access to those fields on PL/pgSQL, what was the

point

of the patch to begin with? Surely, accessing them from C wasn't the
main use case?

These fields are available for application developers now. But is a
true, so without this patch, GET STACKED DIAGNOSTICS statement will
not be fully consistent, because some fields are accessible and others
not

there is one stronger argument for commit this patch now. With this
patch, we are able to wrote regression tests for new fields via
plpgsql.

Regards

Pavel

Pavel

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

--
Rushabh Lathia

--
Rushabh Lathia

#10Pavel Stehule
pavel.stehule@gmail.com
In reply to: Rushabh Lathia (#9)
Re: proposal: enable new error fields in plpgsql (9.4)

2013/6/25 Rushabh Lathia <rushabh.lathia@gmail.com>:

On Tue, Jun 25, 2013 at 2:41 PM, Pavel Stehule <pavel.stehule@gmail.com>
wrote:

2013/6/25 Rushabh Lathia <rushabh.lathia@gmail.com>:

Hi Pavel,

I gone through the discussion over here and found that with this patch
we
enable the new error fields in plpgsql. Its a simple patch to expose the
new
error fields in plpgsql.

Patch gets applied cleanly. make and make install too went smooth. make
check
was smooth too. Patch also include test coverage

I tested the functionality with manual test and its woking as expected.

BTW in the patch I found one additional new like in
read_raise_options():

@@ -3631,7 +3661,23 @@ 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_NAME, "column_name"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_COLUMN_NAME;
+               else if (tok_is_keyword(tok, &yylval,
+
K_CONSTRAINT_NAME, "constraint_name"))
+                       opt->opt_type =
PLPGSQL_RAISEOPTION_CONSTRAINT_NAME;
+               else if (tok_is_keyword(tok, &yylval,
+
K_DATATYPE_NAME, "datatype_name"))
+                       opt->opt_type =
PLPGSQL_RAISEOPTION_DATATYPE_NAME;
+               else if (tok_is_keyword(tok, &yylval,
+
K_TABLE_NAME, "table_name"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_TABLE_NAME;
+               else if (tok_is_keyword(tok, &yylval,
+
K_SCHEMA_NAME, "schema_name"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_SCHEMA_NAME;
else
+
yyerror("unrecognized RAISE statement option");

can you please remove that.

No, these fields are there as was proposed - it enhance possibilities
to PLpgSQL developers - they can use these fields for custom
exceptions. It is same like possibility to specify SQLCODE, MESSAGE,
HINT in current RAISE statement implementation.

Why you dislike it?

Seems like some confusion.

I noticed additional new line which has been added into your patch in
function
read_raise_options()::pl_gram.y @ line number 3680. And in the earlier mail
thats what I asked to remove.

I am sorry

I remove these new lines

Regards

Pavel

Regards

Pavel

Apart from that patch looks good to me.

Thanks,
Rushabh

On Fri, Feb 1, 2013 at 7:29 PM, Pavel Stehule <pavel.stehule@gmail.com>
wrote:

2013/2/1 Pavel Stehule <pavel.stehule@gmail.com>:

2013/2/1 Peter Eisentraut <peter_e@gmx.net>:

On 2/1/13 8:00 AM, Pavel Stehule wrote:

2013/2/1 Marko Tiikkaja <pgmail@joh.to>:

On 2/1/13 1:47 PM, Pavel Stehule wrote:

now a most "hard" work is done and I would to enable access to
new
error fields from plpgsql.

Is there a compelling reason why we wouldn't provide these already
in
9.3?

a time for assign to last commitfest is out.

this patch is relative simple and really close to enhanced error
fields feature - but depends if some from commiters will have a
time
for commit to 9.3 - so I am expecting primary target 9.4, but I am
not
be angry if it will be commited early.

If we don't have access to those fields on PL/pgSQL, what was the
point
of the patch to begin with? Surely, accessing them from C wasn't
the
main use case?

These fields are available for application developers now. But is a
true, so without this patch, GET STACKED DIAGNOSTICS statement will
not be fully consistent, because some fields are accessible and
others
not

there is one stronger argument for commit this patch now. With this
patch, we are able to wrote regression tests for new fields via
plpgsql.

Regards

Pavel

Pavel

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

--
Rushabh Lathia

--
Rushabh Lathia

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#11Pavel Stehule
pavel.stehule@gmail.com
In reply to: Rushabh Lathia (#7)
1 attachment(s)
Re: proposal: enable new error fields in plpgsql (9.4)

Hello

2013/6/25 Rushabh Lathia <rushabh.lathia@gmail.com>:

Hi Pavel,

I gone through the discussion over here and found that with this patch we
enable the new error fields in plpgsql. Its a simple patch to expose the new
error fields in plpgsql.

Patch gets applied cleanly. make and make install too went smooth. make
check
was smooth too. Patch also include test coverage

I tested the functionality with manual test and its woking as expected.

BTW in the patch I found one additional new like in read_raise_options():

@@ -3631,7 +3661,23 @@ 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_NAME, "column_name"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_COLUMN_NAME;
+               else if (tok_is_keyword(tok, &yylval,
+
K_CONSTRAINT_NAME, "constraint_name"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_CONSTRAINT_NAME;
+               else if (tok_is_keyword(tok, &yylval,
+
K_DATATYPE_NAME, "datatype_name"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_DATATYPE_NAME;
+               else if (tok_is_keyword(tok, &yylval,
+
K_TABLE_NAME, "table_name"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_TABLE_NAME;
+               else if (tok_is_keyword(tok, &yylval,
+
K_SCHEMA_NAME, "schema_name"))
+                       opt->opt_type = PLPGSQL_RAISEOPTION_SCHEMA_NAME;
else
+
yyerror("unrecognized RAISE statement option");

can you please remove that.

cleaned patch is in attachment

Apart from that patch looks good to me.

:) thank you for review

Regards

Pavel Stehule

Show quoted text

Thanks,
Rushabh

On Fri, Feb 1, 2013 at 7:29 PM, Pavel Stehule <pavel.stehule@gmail.com>
wrote:

2013/2/1 Pavel Stehule <pavel.stehule@gmail.com>:

2013/2/1 Peter Eisentraut <peter_e@gmx.net>:

On 2/1/13 8:00 AM, Pavel Stehule wrote:

2013/2/1 Marko Tiikkaja <pgmail@joh.to>:

On 2/1/13 1:47 PM, Pavel Stehule wrote:

now a most "hard" work is done and I would to enable access to new
error fields from plpgsql.

Is there a compelling reason why we wouldn't provide these already in
9.3?

a time for assign to last commitfest is out.

this patch is relative simple and really close to enhanced error
fields feature - but depends if some from commiters will have a time
for commit to 9.3 - so I am expecting primary target 9.4, but I am not
be angry if it will be commited early.

If we don't have access to those fields on PL/pgSQL, what was the point
of the patch to begin with? Surely, accessing them from C wasn't the
main use case?

These fields are available for application developers now. But is a
true, so without this patch, GET STACKED DIAGNOSTICS statement will
not be fully consistent, because some fields are accessible and others
not

there is one stronger argument for commit this patch now. With this
patch, we are able to wrote regression tests for new fields via
plpgsql.

Regards

Pavel

Pavel

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

--
Rushabh Lathia

Attachments:

enhanced_error_fields_plpgsql.patchapplication/octet-stream; name=enhanced_error_fields_plpgsql.patchDownload
*** 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>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,3420 ----
          five-character SQLSTATE code.</para>
        </listitem>
       </varlistentry>
+ 
+      <varlistentry>
+       <term><literal>COLUMN_NAME</literal></term>
+       <listitem>
+        <para>Specifies the column name field of exception</para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
+       <term><literal>CONSTRAINT_NAME</literal></term>
+       <listitem>
+        <para>Specifies the constraint name field of exception</para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
+       <term><literal>DATATYPE_NAME</literal></term>
+       <listitem>
+        <para>Specifies the data type name field of exception</para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
+       <term><literal>TABLE_NAME</literal></term>
+       <listitem>
+        <para>Specifies the table name field of exception</para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
+       <term><literal>SCHEMA_NAME</literal></term>
+       <listitem>
+        <para>Specifies the schema name field of exception</para>
+       </listitem>
+      </varlistentry>
      </variablelist>
     </para>
  
*** 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_name = NULL;
+ 	char	   *err_constraint_name = NULL;
+ 	char	   *err_datatype_name = NULL;
+ 	char	   *err_table_name = NULL;
+ 	char	   *err_schema_name = NULL;
  	ListCell   *lc;
  
  	/* RAISE with no parameters: re-throw current exception */
***************
*** 2926,2955 **** exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
  				err_code = plpgsql_recognize_err_condition(extval, true);
  				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);
  		}
--- 2966,3004 ----
  				err_code = plpgsql_recognize_err_condition(extval, true);
  				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_NAME:
! 				SET_RAISE_OPTION_TEXT(err_column_name, "COLUMN_NAME");
  				break;
+ 
+ 			case PLPGSQL_RAISEOPTION_CONSTRAINT_NAME:
+ 				SET_RAISE_OPTION_TEXT(err_constraint_name, "CONSTRAINT_NAME");
+ 				break;
+ 
+ 			case PLPGSQL_RAISEOPTION_DATATYPE_NAME:
+ 				SET_RAISE_OPTION_TEXT(err_datatype_name, "DATATYPE_NAME");
+ 				break;
+ 
+ 			case PLPGSQL_RAISEOPTION_TABLE_NAME:
+ 				SET_RAISE_OPTION_TEXT(err_table_name, "TABLE_NAME");
+ 				break;
+ 
+ 			case PLPGSQL_RAISEOPTION_SCHEMA_NAME:
+ 				SET_RAISE_OPTION_TEXT(err_schema_name, "SCHEMA_NAME");
+ 				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... */
  
--- 3031,3047 ----
  			(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_name != NULL) ?
! 				 err_generic_string(PG_DIAG_COLUMN_NAME, err_column_name) : 0,
! 			 (err_constraint_name != NULL) ?
! 				 err_generic_string(PG_DIAG_CONSTRAINT_NAME, err_constraint_name) : 0,
! 			 (err_datatype_name != NULL) ?
! 				 err_generic_string(PG_DIAG_DATATYPE_NAME, err_datatype_name) : 0,
! 			 (err_table_name != NULL) ?
! 				 err_generic_string(PG_DIAG_TABLE_NAME, err_table_name) : 0,
! 			 (err_schema_name != NULL) ?
! 				 err_generic_string(PG_DIAG_SCHEMA_NAME, err_schema_name) : 0));
  
  	estate->err_text = NULL;	/* un-suppress... */
  
***************
*** 2994,2999 **** exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
--- 3053,3068 ----
  		pfree(err_detail);
  	if (err_hint != NULL)
  		pfree(err_hint);
+ 	if (err_column_name != NULL)
+ 		pfree(err_column_name);
+ 	if (err_constraint_name != NULL)
+ 		pfree(err_constraint_name);
+ 	if (err_datatype_name != NULL)
+ 		pfree(err_datatype_name);
+ 	if (err_table_name != NULL)
+ 		pfree(err_table_name);
+ 	if (err_schema_name != NULL)
+ 		pfree(err_schema_name);
  
  	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 "DATATYPE_TEXT";
  		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_NAME:
+ 					printf("    COLUMN_NAME = ");
+ 					break;
+ 				case PLPGSQL_RAISEOPTION_CONSTRAINT_NAME:
+ 					printf("    CONSTRAINT_NAME = ");
+ 					break;
+ 				case PLPGSQL_RAISEOPTION_DATATYPE_NAME:
+ 					printf("    DATATYPE_NAME = ");
+ 					break;
+ 				case PLPGSQL_RAISEOPTION_TABLE_NAME:
+ 					printf("    TABLE_NAME = ");
+ 					break;
+ 				case PLPGSQL_RAISEOPTION_SCHEMA_NAME:
+ 					printf("    SCHEMA_NAME = ");
+ 					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,263 ----
  %token <keyword>	K_CASE
  %token <keyword>	K_CLOSE
  %token <keyword>	K_COLLATE
+ %token <keyword>	K_COLUMN_NAME
  %token <keyword>	K_CONSTANT
+ %token <keyword>	K_CONSTRAINT_NAME
  %token <keyword>	K_CONTINUE
  %token <keyword>	K_CURRENT
  %token <keyword>	K_CURSOR
+ %token <keyword>	K_DATATYPE_NAME
  %token <keyword>	K_DEBUG
  %token <keyword>	K_DECLARE
  %token <keyword>	K_DEFAULT
***************
*** 311,321 **** static	List			*read_raise_options(void);
--- 314,326 ----
  %token <keyword>	K_REVERSE
  %token <keyword>	K_ROWTYPE
  %token <keyword>	K_ROW_COUNT
+ %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_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 ';'
--- 901,912 ----
  								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 :
--- 981,1004 ----
  												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_DATATYPE_NAME, "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	:
--- 2256,2267 ----
  				| K_ALIAS
  				| K_ARRAY
  				| K_BACKWARD
+ 				| K_COLUMN_NAME
  				| K_CONSTANT
+ 				| K_CONSTRAINT_NAME
  				| K_CURRENT
  				| K_CURSOR
+ 				| K_DATATYPE_NAME
  				| K_DEBUG
  				| K_DETAIL
  				| K_DUMP
***************
*** 2263,2268 **** unreserved_keyword	:
--- 2291,2298 ----
  				| K_REVERSE
  				| K_ROW_COUNT
  				| K_ROWTYPE
+ 				| K_TABLE_NAME
+ 				| K_SCHEMA_NAME
  				| K_SCROLL
  				| K_SLICE
  				| K_SQLSTATE
***************
*** 3631,3636 **** read_raise_options(void)
--- 3661,3681 ----
  		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_NAME, "column_name"))
+ 			opt->opt_type = PLPGSQL_RAISEOPTION_COLUMN_NAME;
+ 		else if (tok_is_keyword(tok, &yylval,
+ 								K_CONSTRAINT_NAME, "constraint_name"))
+ 			opt->opt_type = PLPGSQL_RAISEOPTION_CONSTRAINT_NAME;
+ 		else if (tok_is_keyword(tok, &yylval,
+ 								K_DATATYPE_NAME, "datatype_name"))
+ 			opt->opt_type = PLPGSQL_RAISEOPTION_DATATYPE_NAME;
+ 		else if (tok_is_keyword(tok, &yylval,
+ 								K_TABLE_NAME, "table_name"))
+ 			opt->opt_type = PLPGSQL_RAISEOPTION_TABLE_NAME;
+ 		else if (tok_is_keyword(tok, &yylval,
+ 								K_SCHEMA_NAME, "schema_name"))
+ 			opt->opt_type = PLPGSQL_RAISEOPTION_SCHEMA_NAME;
  		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,120 ----
  	PG_KEYWORD("alias", K_ALIAS, UNRESERVED_KEYWORD)
  	PG_KEYWORD("array", K_ARRAY, UNRESERVED_KEYWORD)
  	PG_KEYWORD("backward", K_BACKWARD, UNRESERVED_KEYWORD)
+ 	PG_KEYWORD("column_name", K_COLUMN_NAME, UNRESERVED_KEYWORD)
  	PG_KEYWORD("constant", K_CONSTANT, 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_name", K_DATATYPE_NAME, UNRESERVED_KEYWORD)
  	PG_KEYWORD("debug", K_DEBUG, UNRESERVED_KEYWORD)
  	PG_KEYWORD("detail", K_DETAIL, UNRESERVED_KEYWORD)
  	PG_KEYWORD("dump", K_DUMP, UNRESERVED_KEYWORD)
***************
*** 141,150 **** static const ScanKeyword unreserved_keywords[] = {
--- 144,155 ----
  	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_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_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_NAME,
! 	PLPGSQL_RAISEOPTION_CONSTRAINT_NAME,
! 	PLPGSQL_RAISEOPTION_DATATYPE_NAME,
! 	PLPGSQL_RAISEOPTION_TABLE_NAME,
! 	PLPGSQL_RAISEOPTION_SCHEMA_NAME
  };
  
  /* --------
*** 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_name = '>>some column name<<',
+     constraint_name = '>>some constraint name<<',
+     datatype_name = '>>some datatype name<<',
+     table_name = '>>some table name<<',
+     schema_name = '>>some schema name<<';
+ exception when others then
+   get stacked diagnostics
+         _column_name = column_name,
+         _constraint_name = constraint_name,
+         _datatype_name = datatype_name,
+         _table_name = table_name,
+         _schema_name = schema_name;
+   raise notice 'column_name: %, constraint_name: %, datatype_name: %, table_name: %, schema_name: %',
+     _column_name, _constraint_name, _datatype_name, _table_name, _schema_name;
+ end;
+ $$ language plpgsql;
+ select stacked_diagnostics_test();
+ NOTICE:  column_name: >>some column name<<, constraint_name: >>some constraint name<<, datatype_name: >>some datatype name<<, table_name: >>some table name<<, schema_name: >>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_name = '>>some column name<<',
+     constraint_name = '>>some constraint name<<',
+     datatype_name = '>>some datatype name<<',
+     table_name = '>>some table name<<',
+     schema_name = '>>some schema name<<';
+ exception when others then
+   get stacked diagnostics
+         _column_name = column_name,
+         _constraint_name = constraint_name,
+         _datatype_name = datatype_name,
+         _table_name = table_name,
+         _schema_name = schema_name;
+   raise notice 'column_name: %, constraint_name: %, datatype_name: %, table_name: %, schema_name: %',
+     _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 $$
#12Noah Misch
noah@leadboat.com
In reply to: Pavel Stehule (#11)
Re: proposal: enable new error fields in plpgsql (9.4)

On Tue, Jun 25, 2013 at 03:56:27PM +0200, Pavel Stehule wrote:

cleaned patch is in attachment

Of the five options you're adding to GET STACKED DIAGNOSTICS, four of them
appear in the SQL standard. DATATYPE_NAME does not; I think we should call it
PG_DATATYPE_NAME in line with our other extensions in this area.

2013/2/1 Pavel Stehule <pavel.stehule@gmail.com>:

2013/2/1 Peter Eisentraut <peter_e@gmx.net>:

On 2/1/13 8:00 AM, Pavel Stehule wrote:

2013/2/1 Marko Tiikkaja <pgmail@joh.to>:

Is there a compelling reason why we wouldn't provide these already in
9.3?

a time for assign to last commitfest is out.

this patch is relative simple and really close to enhanced error
fields feature - but depends if some from commiters will have a time
for commit to 9.3 - so I am expecting primary target 9.4, but I am not
be angry if it will be commited early.

If we don't have access to those fields on PL/pgSQL, what was the point
of the patch to begin with? Surely, accessing them from C wasn't the
main use case?

These fields are available for application developers now. But is a
true, so without this patch, GET STACKED DIAGNOSTICS statement will
not be fully consistent, because some fields are accessible and others
not

I am inclined to back-patch this to 9.3. The patch is fairly mechanical, and
I think the risk of introducing bugs is less than the risk that folks will be
confused by these new-in-9.3 error fields being accessible from libpq and the
protocol, yet inaccessible from PL/pgSQL.

The existing protocol documentation says things like this:

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.)

The way you have defined RAISE does not enforce this; the user can set
TABLE_NAME without setting SCHEMA_NAME at all. I see a few options here:

1. Change RAISE to check the invariants thoroughly. For example, TABLE_NAME
would require SCHEMA name, and the pair would need to name an actual table.

2. Change RAISE to check the invariants simply. For example, it could check
that SCHEMA_NAME is present whenever TABLE_NAME is present but provide no
validation that the pair names an actual table. (I think the protocol
language basically allows this, though a brief note wouldn't hurt.)

3. Tweak the protocol documentation to clearly permit what the patch has RAISE
allow, namely the free-form use of these fields. This part of the protocol is
new in 9.3, so it won't be a big deal to change it. The libpq documentation
has similar verbiage to update.

I suppose I prefer #3. It seems fair for user code to employ these fields for
applications slightly broader than their core use, like a constraint name that
represents some userspace notion of a constraint rather than normal, cataloged
constraint. I can also imagine an application like replaying logs from
another server, recreating the messages as that server emitted them; #2 or #3
would suffice for that.

Looking beyond the immediate topic of PL/pgSQL, it seems fair for a FDW to use
these error fields to name remote objects not known locally. Suppose a
foreign INSERT fires a remote trigger, and that trigger violates a constraint
of some other remote table. Naming the remote objects would be a reasonable
design choice. postgres_fdw might have chosen to just copy fields from the
remote error (it does not do this today for the fields in question, though).
The FDW might not even have a notion of a schema, at which point it would
legitimately choose to leave that field unpopulated. Once we allow any part
of the system to generate such errors, we should let PL/pgSQL do the same.

Thoughts on that plan?

--
Noah Misch
EnterpriseDB http://www.enterprisedb.com

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#13Pavel Stehule
pavel.stehule@gmail.com
In reply to: Noah Misch (#12)
Re: proposal: enable new error fields in plpgsql (9.4)

Hello

2013/6/28 Noah Misch <noah@leadboat.com>:

On Tue, Jun 25, 2013 at 03:56:27PM +0200, Pavel Stehule wrote:

cleaned patch is in attachment

Of the five options you're adding to GET STACKED DIAGNOSTICS, four of them
appear in the SQL standard. DATATYPE_NAME does not; I think we should call it
PG_DATATYPE_NAME in line with our other extensions in this area.

yes, but It should be fixed in 9.3 enhanced fields too - it should be
consistent with PostgreSQL fields

2013/2/1 Pavel Stehule <pavel.stehule@gmail.com>:

2013/2/1 Peter Eisentraut <peter_e@gmx.net>:

On 2/1/13 8:00 AM, Pavel Stehule wrote:

2013/2/1 Marko Tiikkaja <pgmail@joh.to>:

Is there a compelling reason why we wouldn't provide these already in
9.3?

a time for assign to last commitfest is out.

this patch is relative simple and really close to enhanced error
fields feature - but depends if some from commiters will have a time
for commit to 9.3 - so I am expecting primary target 9.4, but I am not
be angry if it will be commited early.

If we don't have access to those fields on PL/pgSQL, what was the point
of the patch to begin with? Surely, accessing them from C wasn't the
main use case?

These fields are available for application developers now. But is a
true, so without this patch, GET STACKED DIAGNOSTICS statement will
not be fully consistent, because some fields are accessible and others
not

I am inclined to back-patch this to 9.3. The patch is fairly mechanical, and
I think the risk of introducing bugs is less than the risk that folks will be
confused by these new-in-9.3 error fields being accessible from libpq and the
protocol, yet inaccessible from PL/pgSQL.

+1

The existing protocol documentation says things like this:

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.)

The way you have defined RAISE does not enforce this; the user can set
TABLE_NAME without setting SCHEMA_NAME at all. I see a few options here:

1. Change RAISE to check the invariants thoroughly. For example, TABLE_NAME
would require SCHEMA name, and the pair would need to name an actual table.

2. Change RAISE to check the invariants simply. For example, it could check
that SCHEMA_NAME is present whenever TABLE_NAME is present but provide no
validation that the pair names an actual table. (I think the protocol
language basically allows this, though a brief note wouldn't hurt.)

3. Tweak the protocol documentation to clearly permit what the patch has RAISE
allow, namely the free-form use of these fields. This part of the protocol is
new in 9.3, so it won't be a big deal to change it. The libpq documentation
has similar verbiage to update.

I suppose I prefer #3. It seems fair for user code to employ these fields for
applications slightly broader than their core use, like a constraint name that
represents some userspace notion of a constraint rather than normal, cataloged
constraint. I can also imagine an application like replaying logs from
another server, recreating the messages as that server emitted them; #2 or #3
would suffice for that.

I like #3 too. These fields should be used in custom code freely - and
I don't would create some limits. Developer can use it for application
code how he likes. It was designed for this purpose.

Looking beyond the immediate topic of PL/pgSQL, it seems fair for a FDW to use
these error fields to name remote objects not known locally. Suppose a
foreign INSERT fires a remote trigger, and that trigger violates a constraint
of some other remote table. Naming the remote objects would be a reasonable
design choice. postgres_fdw might have chosen to just copy fields from the
remote error (it does not do this today for the fields in question, though).
The FDW might not even have a notion of a schema, at which point it would
legitimately choose to leave that field unpopulated. Once we allow any part
of the system to generate such errors, we should let PL/pgSQL do the same.

+1

Regards

Pavel

Thoughts on that plan?

--
Noah Misch
EnterpriseDB http://www.enterprisedb.com

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#14Noah Misch
noah@leadboat.com
In reply to: Pavel Stehule (#13)
Re: proposal: enable new error fields in plpgsql (9.4)

On Fri, Jun 28, 2013 at 07:49:46AM +0200, Pavel Stehule wrote:

2013/6/28 Noah Misch <noah@leadboat.com>:

On Tue, Jun 25, 2013 at 03:56:27PM +0200, Pavel Stehule wrote:

cleaned patch is in attachment

Of the five options you're adding to GET STACKED DIAGNOSTICS, four of them
appear in the SQL standard. DATATYPE_NAME does not; I think we should call it
PG_DATATYPE_NAME in line with our other extensions in this area.

yes, but It should be fixed in 9.3 enhanced fields too - it should be
consistent with PostgreSQL fields

What else, specifically, should be renamed? (Alternately, would you prepare a
new version of the patch incorporating the proper name changes?)

Thanks,
nm

--
Noah Misch
EnterpriseDB http://www.enterprisedb.com

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#15Pavel Stehule
pavel.stehule@gmail.com
In reply to: Noah Misch (#14)
Re: proposal: enable new error fields in plpgsql (9.4)

Hello

2013/6/28 Noah Misch <noah@leadboat.com>:

On Fri, Jun 28, 2013 at 07:49:46AM +0200, Pavel Stehule wrote:

2013/6/28 Noah Misch <noah@leadboat.com>:

On Tue, Jun 25, 2013 at 03:56:27PM +0200, Pavel Stehule wrote:

cleaned patch is in attachment

Of the five options you're adding to GET STACKED DIAGNOSTICS, four of them
appear in the SQL standard. DATATYPE_NAME does not; I think we should call it
PG_DATATYPE_NAME in line with our other extensions in this area.

yes, but It should be fixed in 9.3 enhanced fields too - it should be
consistent with PostgreSQL fields

What else, specifically, should be renamed? (Alternately, would you prepare a
new version of the patch incorporating the proper name changes?)

I looked to source code, and identifiers in our source code are
consistent, so my comment hasn't sense. Yes, I agree, so only
identifier used in GET DIAGNOSTICS statement should be renamed. So,
only DATATYPE_NAME should be renamed to PG_DATATYPE_NAME.

Regards

Pavel

Thanks,
nm

--
Noah Misch
EnterpriseDB http://www.enterprisedb.com

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#16Noah Misch
noah@leadboat.com
In reply to: Pavel Stehule (#15)
Re: proposal: enable new error fields in plpgsql (9.4)

On Fri, Jun 28, 2013 at 03:31:00PM +0200, Pavel Stehule wrote:

Hello

2013/6/28 Noah Misch <noah@leadboat.com>:

On Fri, Jun 28, 2013 at 07:49:46AM +0200, Pavel Stehule wrote:

2013/6/28 Noah Misch <noah@leadboat.com>:

On Tue, Jun 25, 2013 at 03:56:27PM +0200, Pavel Stehule wrote:

cleaned patch is in attachment

Of the five options you're adding to GET STACKED DIAGNOSTICS, four of them
appear in the SQL standard. DATATYPE_NAME does not; I think we should call it
PG_DATATYPE_NAME in line with our other extensions in this area.

yes, but It should be fixed in 9.3 enhanced fields too - it should be
consistent with PostgreSQL fields

What else, specifically, should be renamed? (Alternately, would you prepare a
new version of the patch incorporating the proper name changes?)

I looked to source code, and identifiers in our source code are
consistent, so my comment hasn't sense. Yes, I agree, so only
identifier used in GET DIAGNOSTICS statement should be renamed. So,
only DATATYPE_NAME should be renamed to PG_DATATYPE_NAME.

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.

--
Noah Misch
EnterpriseDB http://www.enterprisedb.com

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#17Pavel Stehule
pavel.stehule@gmail.com
In reply to: Noah Misch (#16)
Re: proposal: enable new error fields in plpgsql (9.4)

2013/6/28 Noah Misch <noah@leadboat.com>:

On Fri, Jun 28, 2013 at 03:31:00PM +0200, Pavel Stehule wrote:

Hello

2013/6/28 Noah Misch <noah@leadboat.com>:

On Fri, Jun 28, 2013 at 07:49:46AM +0200, Pavel Stehule wrote:

2013/6/28 Noah Misch <noah@leadboat.com>:

On Tue, Jun 25, 2013 at 03:56:27PM +0200, Pavel Stehule wrote:

cleaned patch is in attachment

Of the five options you're adding to GET STACKED DIAGNOSTICS, four of them
appear in the SQL standard. DATATYPE_NAME does not; I think we should call it
PG_DATATYPE_NAME in line with our other extensions in this area.

yes, but It should be fixed in 9.3 enhanced fields too - it should be
consistent with PostgreSQL fields

What else, specifically, should be renamed? (Alternately, would you prepare a
new version of the patch incorporating the proper name changes?)

I looked to source code, and identifiers in our source code are
consistent, so my comment hasn't sense. Yes, I agree, so only
identifier used in GET DIAGNOSTICS statement should be renamed. So,
only DATATYPE_NAME should be renamed to PG_DATATYPE_NAME.

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 ??

p.s. you cannot to specify CONTEXT in RAISE statement

Regards

Pavel

--
Noah Misch
EnterpriseDB http://www.enterprisedb.com

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#18Noah Misch
noah@leadboat.com
In reply to: Pavel Stehule (#17)
Re: proposal: enable new error fields in plpgsql (9.4)

On Fri, Jun 28, 2013 at 05:21:29PM +0200, Pavel Stehule wrote:

2013/6/28 Noah Misch <noah@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.

p.s. you cannot to specify CONTEXT in RAISE statement

Oops; right.

--
Noah Misch
EnterpriseDB http://www.enterprisedb.com

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#19Noah Misch
noah@leadboat.com
In reply to: Noah Misch (#18)
1 attachment(s)
Re: proposal: enable new error fields in plpgsql (9.4)

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 <noah@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

Attachments:

enhanced_error_fields_plpgsql-v3.patchtext/plain; charset=us-asciiDownload
*** 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 $$
#20Pavel Stehule
pavel.stehule@gmail.com
In reply to: Noah Misch (#19)
Re: proposal: enable new error fields in plpgsql (9.4)

Hello

2013/7/2 Noah Misch <noah@leadboat.com>:

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 <noah@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.

+1

Pavel

--
Noah Misch
EnterpriseDB http://www.enterprisedb.com

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#21Noah Misch
noah@leadboat.com
In reply to: Pavel Stehule (#20)
Re: proposal: enable new error fields in plpgsql (9.4)

On Wed, Jul 03, 2013 at 06:17:18AM +0200, Pavel Stehule wrote:

2013/7/2 Noah Misch <noah@leadboat.com>:

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.

+1

Done.

Rushabh, I neglected to credit you as a reviewer and realized it too late.
Sorry about that.

--
Noah Misch
EnterpriseDB http://www.enterprisedb.com

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#22Pavel Stehule
pavel.stehule@gmail.com
In reply to: Noah Misch (#21)
Re: proposal: enable new error fields in plpgsql (9.4)

2013/7/3 Noah Misch <noah@leadboat.com>:

On Wed, Jul 03, 2013 at 06:17:18AM +0200, Pavel Stehule wrote:

2013/7/2 Noah Misch <noah@leadboat.com>:

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.

+1

Done.

Thank you, very much

Regards

Pavel

Rushabh, I neglected to credit you as a reviewer and realized it too late.
Sorry about that.

--
Noah Misch
EnterpriseDB http://www.enterprisedb.com

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#23Rushabh Lathia
rushabh.lathia@gmail.com
In reply to: Noah Misch (#21)
Re: proposal: enable new error fields in plpgsql (9.4)

On Wed, Jul 3, 2013 at 5:16 PM, Noah Misch <noah@leadboat.com> wrote:

On Wed, Jul 03, 2013 at 06:17:18AM +0200, Pavel Stehule wrote:

2013/7/2 Noah Misch <noah@leadboat.com>:

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.

+1

Done.

Rushabh, I neglected to credit you as a reviewer and realized it too late.
Sorry about that.

Sorry somehow I missed this thread.

Thanks Noah.

--
Noah Misch
EnterpriseDB http://www.enterprisedb.com

--
Rushabh Lathia