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