提交 7cd9b137 编写于 作者: N Noah Misch

Expose object name error fields in PL/pgSQL.

Specifically, permit attaching them to the error in RAISE and retrieving
them from a caught error in GET STACKED DIAGNOSTICS.  RAISE enforces
nothing about the content of the fields; for its purposes, they are just
additional string fields.  Consequently, clarify in the protocol and
libpq documentation that the usual relationships between error fields,
like a schema name appearing wherever a table name appears, are not
universal.  This freedom has other applications; consider a FDW
propagating an error from an RDBMS having no schema support.

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

Pavel Stehule, lexical revisions by Noah Misch.
上级 69e4fd45
......@@ -2712,9 +2712,9 @@ char *PQresultErrorField(const PGresult *res, int fieldcode);
<term><symbol>PG_DIAG_TABLE_NAME</></term>
<listitem>
<para>
If the error was associated with a specific table, the name of
the table. (When this field is present, the schema name field
provides the name of the table's schema.)
If the error was associated with a specific table, the name of the
table. (Refer to the schema name field for the name of the
table's schema.)
</para>
</listitem>
</varlistentry>
......@@ -2723,9 +2723,9 @@ char *PQresultErrorField(const PGresult *res, int fieldcode);
<term><symbol>PG_DIAG_COLUMN_NAME</></term>
<listitem>
<para>
If the error was associated with a specific table column, the
name of the column. (When this field is present, the schema
and table name fields identify the table.)
If the error was associated with a specific table column, the name
of the column. (Refer to the schema and table name fields to
identify the table.)
</para>
</listitem>
</varlistentry>
......@@ -2734,9 +2734,9 @@ char *PQresultErrorField(const PGresult *res, int fieldcode);
<term><symbol>PG_DIAG_DATATYPE_NAME</></term>
<listitem>
<para>
If the error was associated with a specific data type, the name
of the data type. (When this field is present, the schema name
field provides the name of the data type's schema.)
If the error was associated with a specific data type, the name of
the data type. (Refer to the schema name field for the name of
the data type's schema.)
</para>
</listitem>
</varlistentry>
......@@ -2745,11 +2745,11 @@ char *PQresultErrorField(const PGresult *res, int fieldcode);
<term><symbol>PG_DIAG_CONSTRAINT_NAME</></term>
<listitem>
<para>
If the error was associated with a specific constraint,
the name of the constraint. The table or domain that the
constraint belongs to is reported using the fields listed
above. (For this purpose, indexes are treated as constraints,
even if they weren't created with constraint syntax.)
If the error was associated with a specific constraint, the name
of the constraint. Refer to fields listed above for the
associated table or domain. (For this purpose, indexes are
treated as constraints, even if they weren't created with
constraint syntax.)
</para>
</listitem>
</varlistentry>
......@@ -2787,9 +2787,14 @@ char *PQresultErrorField(const PGresult *res, int fieldcode);
<note>
<para>
The fields for schema name, table name, column name, data type
name, and constraint name are supplied only for a limited number
of error types; see <xref linkend="errcodes-appendix">.
The fields for schema name, table name, column name, data type name,
and constraint name are supplied only for a limited number of error
types; see <xref linkend="errcodes-appendix">. Do not assume that
the presence of any of these fields guarantees the presence of
another field. Core error sources observe the interrelationships
noted above, but user-defined functions may use these fields in other
ways. In the same vein, do not assume that these fields denote
contemporary objects in the current database.
</para>
</note>
......
......@@ -2664,11 +2664,36 @@ GET STACKED DIAGNOSTICS <replaceable>variable</replaceable> = <replaceable>item<
<entry>text</entry>
<entry>the SQLSTATE error code of the exception</entry>
</row>
<row>
<entry><literal>COLUMN_NAME</literal></entry>
<entry>text</entry>
<entry>the name of column related to exception</entry>
</row>
<row>
<entry><literal>CONSTRAINT_NAME</literal></entry>
<entry>text</entry>
<entry>the name of constraint related to exception</entry>
</row>
<row>
<entry><literal>PG_DATATYPE_NAME</literal></entry>
<entry>text</entry>
<entry>the name of datatype related to exception</entry>
</row>
<row>
<entry><literal>MESSAGE_TEXT</literal></entry>
<entry>text</entry>
<entry>the text of the exception's primary message</entry>
</row>
<row>
<entry><literal>TABLE_NAME</literal></entry>
<entry>text</entry>
<entry>the name of table related to exception</entry>
</row>
<row>
<entry><literal>SCHEMA_NAME</literal></entry>
<entry>text</entry>
<entry>the name of schema related to exception</entry>
</row>
<row>
<entry><literal>PG_EXCEPTION_DETAIL</literal></entry>
<entry>text</entry>
......@@ -3355,6 +3380,17 @@ RAISE NOTICE 'Calling cs_create_job(%)', v_job_id;
five-character SQLSTATE code.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>COLUMN</literal></term>
<term><literal>CONSTRAINT</literal></term>
<term><literal>DATATYPE</literal></term>
<term><literal>TABLE</literal></term>
<term><literal>SCHEMA</literal></term>
<listitem>
<para>Supplies the name of a related object.</para>
</listitem>
</varlistentry>
</variablelist>
</para>
......
......@@ -4788,8 +4788,8 @@ message.
<listitem>
<para>
Table name: if the error was associated with a specific table, the
name of the table. (When this field is present, the schema name field
provides the name of the table's schema.)
name of the table. (Refer to the schema name field for the name of
the table's schema.)
</para>
</listitem>
</varlistentry>
......@@ -4801,8 +4801,8 @@ message.
<listitem>
<para>
Column name: if the error was associated with a specific table column,
the name of the column. (When this field is present, the schema and
table name fields identify the table.)
the name of the column. (Refer to the schema and table name fields to
identify the table.)
</para>
</listitem>
</varlistentry>
......@@ -4814,8 +4814,8 @@ message.
<listitem>
<para>
Data type name: if the error was associated with a specific data type,
the name of the data type. (When this field is present, the schema
name field provides the name of the data type's schema.)
the name of the data type. (Refer to the schema name field for the
name of the data type's schema.)
</para>
</listitem>
</varlistentry>
......@@ -4827,10 +4827,10 @@ message.
<listitem>
<para>
Constraint name: if the error was associated with a specific
constraint, the name of the constraint. The table or domain that the
constraint belongs to is reported using the fields listed above. (For
this purpose, indexes are treated as constraints, even if they weren't
created with constraint syntax.)
constraint, the name of the constraint. Refer to fields listed above
for the associated table or domain. (For this purpose, indexes are
treated as constraints, even if they weren't created with constraint
syntax.)
</para>
</listitem>
</varlistentry>
......@@ -4876,7 +4876,12 @@ message.
<para>
The fields for schema name, table name, column name, data type name, and
constraint name are supplied only for a limited number of error types;
see <xref linkend="errcodes-appendix">.
see <xref linkend="errcodes-appendix">. Frontends should not assume that
the presence of any of these fields guarantees the presence of another
field. Core error sources observe the interrelationships noted above, but
user-defined functions may use these fields in other ways. In the same
vein, clients should not assume that these fields denote contemporary
objects in the current database.
</para>
</note>
......
......@@ -1569,11 +1569,36 @@ exec_stmt_getdiag(PLpgSQL_execstate *estate, PLpgSQL_stmt_getdiag *stmt)
unpack_sql_state(estate->cur_error->sqlerrcode));
break;
case PLPGSQL_GETDIAG_COLUMN_NAME:
exec_assign_c_string(estate, var,
estate->cur_error->column_name);
break;
case PLPGSQL_GETDIAG_CONSTRAINT_NAME:
exec_assign_c_string(estate, var,
estate->cur_error->constraint_name);
break;
case PLPGSQL_GETDIAG_DATATYPE_NAME:
exec_assign_c_string(estate, var,
estate->cur_error->datatype_name);
break;
case PLPGSQL_GETDIAG_MESSAGE_TEXT:
exec_assign_c_string(estate, var,
estate->cur_error->message);
break;
case PLPGSQL_GETDIAG_TABLE_NAME:
exec_assign_c_string(estate, var,
estate->cur_error->table_name);
break;
case PLPGSQL_GETDIAG_SCHEMA_NAME:
exec_assign_c_string(estate, var,
estate->cur_error->schema_name);
break;
default:
elog(ERROR, "unrecognized diagnostic item kind: %d",
diag_item->kind);
......@@ -2799,6 +2824,16 @@ exec_init_tuple_store(PLpgSQL_execstate *estate)
estate->rettupdesc = rsi->expectedDesc;
}
#define SET_RAISE_OPTION_TEXT(opt, name) \
do { \
if (opt) \
ereport(ERROR, \
(errcode(ERRCODE_SYNTAX_ERROR), \
errmsg("RAISE option already specified: %s", \
name))); \
opt = pstrdup(extval); \
} while (0)
/* ----------
* exec_stmt_raise Build a message and throw it with elog()
* ----------
......@@ -2811,6 +2846,11 @@ exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
char *err_message = NULL;
char *err_detail = NULL;
char *err_hint = NULL;
char *err_column = NULL;
char *err_constraint = NULL;
char *err_datatype = NULL;
char *err_table = NULL;
char *err_schema = NULL;
ListCell *lc;
/* RAISE with no parameters: re-throw current exception */
......@@ -2927,28 +2967,28 @@ exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
condname = pstrdup(extval);
break;
case PLPGSQL_RAISEOPTION_MESSAGE:
if (err_message)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("RAISE option already specified: %s",
"MESSAGE")));
err_message = pstrdup(extval);
SET_RAISE_OPTION_TEXT(err_message, "MESSAGE");
break;
case PLPGSQL_RAISEOPTION_DETAIL:
if (err_detail)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("RAISE option already specified: %s",
"DETAIL")));
err_detail = pstrdup(extval);
SET_RAISE_OPTION_TEXT(err_detail, "DETAIL");
break;
case PLPGSQL_RAISEOPTION_HINT:
if (err_hint)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("RAISE option already specified: %s",
"HINT")));
err_hint = pstrdup(extval);
SET_RAISE_OPTION_TEXT(err_hint, "HINT");
break;
case PLPGSQL_RAISEOPTION_COLUMN:
SET_RAISE_OPTION_TEXT(err_column, "COLUMN");
break;
case PLPGSQL_RAISEOPTION_CONSTRAINT:
SET_RAISE_OPTION_TEXT(err_constraint, "CONSTRAINT");
break;
case PLPGSQL_RAISEOPTION_DATATYPE:
SET_RAISE_OPTION_TEXT(err_datatype, "DATATYPE");
break;
case PLPGSQL_RAISEOPTION_TABLE:
SET_RAISE_OPTION_TEXT(err_table, "TABLE");
break;
case PLPGSQL_RAISEOPTION_SCHEMA:
SET_RAISE_OPTION_TEXT(err_schema, "SCHEMA");
break;
default:
elog(ERROR, "unrecognized raise option: %d", opt->opt_type);
......@@ -2982,7 +3022,17 @@ exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
(err_code ? errcode(err_code) : 0,
errmsg_internal("%s", err_message),
(err_detail != NULL) ? errdetail_internal("%s", err_detail) : 0,
(err_hint != NULL) ? errhint("%s", err_hint) : 0));
(err_hint != NULL) ? errhint("%s", err_hint) : 0,
(err_column != NULL) ?
err_generic_string(PG_DIAG_COLUMN_NAME, err_column) : 0,
(err_constraint != NULL) ?
err_generic_string(PG_DIAG_CONSTRAINT_NAME, err_constraint) : 0,
(err_datatype != NULL) ?
err_generic_string(PG_DIAG_DATATYPE_NAME, err_datatype) : 0,
(err_table != NULL) ?
err_generic_string(PG_DIAG_TABLE_NAME, err_table) : 0,
(err_schema != NULL) ?
err_generic_string(PG_DIAG_SCHEMA_NAME, err_schema) : 0));
estate->err_text = NULL; /* un-suppress... */
......@@ -2994,6 +3044,16 @@ exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
pfree(err_detail);
if (err_hint != NULL)
pfree(err_hint);
if (err_column != NULL)
pfree(err_column);
if (err_constraint != NULL)
pfree(err_constraint);
if (err_datatype != NULL)
pfree(err_datatype);
if (err_table != NULL)
pfree(err_table);
if (err_schema != NULL)
pfree(err_schema);
return PLPGSQL_RC_OK;
}
......
......@@ -285,8 +285,18 @@ plpgsql_getdiag_kindname(int kind)
return "PG_EXCEPTION_HINT";
case PLPGSQL_GETDIAG_RETURNED_SQLSTATE:
return "RETURNED_SQLSTATE";
case PLPGSQL_GETDIAG_COLUMN_NAME:
return "COLUMN_NAME";
case PLPGSQL_GETDIAG_CONSTRAINT_NAME:
return "CONSTRAINT_NAME";
case PLPGSQL_GETDIAG_DATATYPE_NAME:
return "PG_DATATYPE_NAME";
case PLPGSQL_GETDIAG_MESSAGE_TEXT:
return "MESSAGE_TEXT";
case PLPGSQL_GETDIAG_TABLE_NAME:
return "TABLE_NAME";
case PLPGSQL_GETDIAG_SCHEMA_NAME:
return "SCHEMA_NAME";
}
return "unknown";
......@@ -1317,6 +1327,21 @@ dump_raise(PLpgSQL_stmt_raise *stmt)
case PLPGSQL_RAISEOPTION_HINT:
printf(" HINT = ");
break;
case PLPGSQL_RAISEOPTION_COLUMN:
printf(" COLUMN = ");
break;
case PLPGSQL_RAISEOPTION_CONSTRAINT:
printf(" CONSTRAINT = ");
break;
case PLPGSQL_RAISEOPTION_DATATYPE:
printf(" DATATYPE = ");
break;
case PLPGSQL_RAISEOPTION_TABLE:
printf(" TABLE = ");
break;
case PLPGSQL_RAISEOPTION_SCHEMA:
printf(" SCHEMA = ");
break;
}
dump_expr(opt->expr);
printf("\n");
......
......@@ -251,10 +251,15 @@ static List *read_raise_options(void);
%token <keyword> K_CASE
%token <keyword> K_CLOSE
%token <keyword> K_COLLATE
%token <keyword> K_COLUMN
%token <keyword> K_COLUMN_NAME
%token <keyword> K_CONSTANT
%token <keyword> K_CONSTRAINT
%token <keyword> K_CONSTRAINT_NAME
%token <keyword> K_CONTINUE
%token <keyword> K_CURRENT
%token <keyword> K_CURSOR
%token <keyword> K_DATATYPE
%token <keyword> K_DEBUG
%token <keyword> K_DECLARE
%token <keyword> K_DEFAULT
......@@ -298,6 +303,7 @@ static List *read_raise_options(void);
%token <keyword> K_OPTION
%token <keyword> K_OR
%token <keyword> K_PERFORM
%token <keyword> K_PG_DATATYPE_NAME
%token <keyword> K_PG_EXCEPTION_CONTEXT
%token <keyword> K_PG_EXCEPTION_DETAIL
%token <keyword> K_PG_EXCEPTION_HINT
......@@ -311,11 +317,15 @@ static List *read_raise_options(void);
%token <keyword> K_REVERSE
%token <keyword> K_ROWTYPE
%token <keyword> K_ROW_COUNT
%token <keyword> K_SCHEMA
%token <keyword> K_SCHEMA_NAME
%token <keyword> K_SCROLL
%token <keyword> K_SLICE
%token <keyword> K_SQLSTATE
%token <keyword> K_STACKED
%token <keyword> K_STRICT
%token <keyword> K_TABLE
%token <keyword> K_TABLE_NAME
%token <keyword> K_THEN
%token <keyword> K_TO
%token <keyword> K_TYPE
......@@ -896,7 +906,12 @@ stmt_getdiag : K_GET getdiag_area_opt K_DIAGNOSTICS getdiag_list ';'
case PLPGSQL_GETDIAG_ERROR_DETAIL:
case PLPGSQL_GETDIAG_ERROR_HINT:
case PLPGSQL_GETDIAG_RETURNED_SQLSTATE:
case PLPGSQL_GETDIAG_COLUMN_NAME:
case PLPGSQL_GETDIAG_CONSTRAINT_NAME:
case PLPGSQL_GETDIAG_DATATYPE_NAME:
case PLPGSQL_GETDIAG_MESSAGE_TEXT:
case PLPGSQL_GETDIAG_TABLE_NAME:
case PLPGSQL_GETDIAG_SCHEMA_NAME:
if (!new->is_stacked)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
......@@ -970,9 +985,24 @@ getdiag_item :
else if (tok_is_keyword(tok, &yylval,
K_PG_EXCEPTION_CONTEXT, "pg_exception_context"))
$$ = PLPGSQL_GETDIAG_ERROR_CONTEXT;
else if (tok_is_keyword(tok, &yylval,
K_COLUMN_NAME, "column_name"))
$$ = PLPGSQL_GETDIAG_COLUMN_NAME;
else if (tok_is_keyword(tok, &yylval,
K_CONSTRAINT_NAME, "constraint_name"))
$$ = PLPGSQL_GETDIAG_CONSTRAINT_NAME;
else if (tok_is_keyword(tok, &yylval,
K_PG_DATATYPE_NAME, "pg_datatype_name"))
$$ = PLPGSQL_GETDIAG_DATATYPE_NAME;
else if (tok_is_keyword(tok, &yylval,
K_MESSAGE_TEXT, "message_text"))
$$ = PLPGSQL_GETDIAG_MESSAGE_TEXT;
else if (tok_is_keyword(tok, &yylval,
K_TABLE_NAME, "table_name"))
$$ = PLPGSQL_GETDIAG_TABLE_NAME;
else if (tok_is_keyword(tok, &yylval,
K_SCHEMA_NAME, "schema_name"))
$$ = PLPGSQL_GETDIAG_SCHEMA_NAME;
else if (tok_is_keyword(tok, &yylval,
K_RETURNED_SQLSTATE, "returned_sqlstate"))
$$ = PLPGSQL_GETDIAG_RETURNED_SQLSTATE;
......@@ -2231,9 +2261,14 @@ unreserved_keyword :
| K_ALIAS
| K_ARRAY
| K_BACKWARD
| K_COLUMN
| K_COLUMN_NAME
| K_CONSTANT
| K_CONSTRAINT
| K_CONSTRAINT_NAME
| K_CURRENT
| K_CURSOR
| K_DATATYPE
| K_DEBUG
| K_DETAIL
| K_DUMP
......@@ -2252,6 +2287,7 @@ unreserved_keyword :
| K_NO
| K_NOTICE
| K_OPTION
| K_PG_DATATYPE_NAME
| K_PG_EXCEPTION_CONTEXT
| K_PG_EXCEPTION_DETAIL
| K_PG_EXCEPTION_HINT
......@@ -2263,10 +2299,14 @@ unreserved_keyword :
| K_REVERSE
| K_ROW_COUNT
| K_ROWTYPE
| K_SCHEMA
| K_SCHEMA_NAME
| K_SCROLL
| K_SLICE
| K_SQLSTATE
| K_STACKED
| K_TABLE
| K_TABLE_NAME
| K_TYPE
| K_USE_COLUMN
| K_USE_VARIABLE
......@@ -3631,6 +3671,21 @@ read_raise_options(void)
else if (tok_is_keyword(tok, &yylval,
K_HINT, "hint"))
opt->opt_type = PLPGSQL_RAISEOPTION_HINT;
else if (tok_is_keyword(tok, &yylval,
K_COLUMN, "column"))
opt->opt_type = PLPGSQL_RAISEOPTION_COLUMN;
else if (tok_is_keyword(tok, &yylval,
K_CONSTRAINT, "constraint"))
opt->opt_type = PLPGSQL_RAISEOPTION_CONSTRAINT;
else if (tok_is_keyword(tok, &yylval,
K_DATATYPE, "datatype"))
opt->opt_type = PLPGSQL_RAISEOPTION_DATATYPE;
else if (tok_is_keyword(tok, &yylval,
K_TABLE, "table"))
opt->opt_type = PLPGSQL_RAISEOPTION_TABLE;
else if (tok_is_keyword(tok, &yylval,
K_SCHEMA, "schema"))
opt->opt_type = PLPGSQL_RAISEOPTION_SCHEMA;
else
yyerror("unrecognized RAISE statement option");
......
......@@ -109,9 +109,14 @@ static const ScanKeyword unreserved_keywords[] = {
PG_KEYWORD("alias", K_ALIAS, UNRESERVED_KEYWORD)
PG_KEYWORD("array", K_ARRAY, UNRESERVED_KEYWORD)
PG_KEYWORD("backward", K_BACKWARD, UNRESERVED_KEYWORD)
PG_KEYWORD("column", K_COLUMN, UNRESERVED_KEYWORD)
PG_KEYWORD("column_name", K_COLUMN_NAME, UNRESERVED_KEYWORD)
PG_KEYWORD("constant", K_CONSTANT, UNRESERVED_KEYWORD)
PG_KEYWORD("constraint", K_CONSTRAINT, UNRESERVED_KEYWORD)
PG_KEYWORD("constraint_name", K_CONSTRAINT_NAME, UNRESERVED_KEYWORD)
PG_KEYWORD("current", K_CURRENT, UNRESERVED_KEYWORD)
PG_KEYWORD("cursor", K_CURSOR, UNRESERVED_KEYWORD)
PG_KEYWORD("datatype", K_DATATYPE, UNRESERVED_KEYWORD)
PG_KEYWORD("debug", K_DEBUG, UNRESERVED_KEYWORD)
PG_KEYWORD("detail", K_DETAIL, UNRESERVED_KEYWORD)
PG_KEYWORD("dump", K_DUMP, UNRESERVED_KEYWORD)
......@@ -130,6 +135,7 @@ static const ScanKeyword unreserved_keywords[] = {
PG_KEYWORD("no", K_NO, UNRESERVED_KEYWORD)
PG_KEYWORD("notice", K_NOTICE, UNRESERVED_KEYWORD)
PG_KEYWORD("option", K_OPTION, UNRESERVED_KEYWORD)
PG_KEYWORD("pg_datatype_name", K_PG_DATATYPE_NAME, UNRESERVED_KEYWORD)
PG_KEYWORD("pg_exception_context", K_PG_EXCEPTION_CONTEXT, UNRESERVED_KEYWORD)
PG_KEYWORD("pg_exception_detail", K_PG_EXCEPTION_DETAIL, UNRESERVED_KEYWORD)
PG_KEYWORD("pg_exception_hint", K_PG_EXCEPTION_HINT, UNRESERVED_KEYWORD)
......@@ -141,10 +147,14 @@ static const ScanKeyword unreserved_keywords[] = {
PG_KEYWORD("reverse", K_REVERSE, UNRESERVED_KEYWORD)
PG_KEYWORD("row_count", K_ROW_COUNT, UNRESERVED_KEYWORD)
PG_KEYWORD("rowtype", K_ROWTYPE, UNRESERVED_KEYWORD)
PG_KEYWORD("schema", K_SCHEMA, UNRESERVED_KEYWORD)
PG_KEYWORD("schema_name", K_SCHEMA_NAME, UNRESERVED_KEYWORD)
PG_KEYWORD("scroll", K_SCROLL, UNRESERVED_KEYWORD)
PG_KEYWORD("slice", K_SLICE, UNRESERVED_KEYWORD)
PG_KEYWORD("sqlstate", K_SQLSTATE, UNRESERVED_KEYWORD)
PG_KEYWORD("stacked", K_STACKED, UNRESERVED_KEYWORD)
PG_KEYWORD("table", K_TABLE, UNRESERVED_KEYWORD)
PG_KEYWORD("table_name", K_TABLE_NAME, UNRESERVED_KEYWORD)
PG_KEYWORD("type", K_TYPE, UNRESERVED_KEYWORD)
PG_KEYWORD("use_column", K_USE_COLUMN, UNRESERVED_KEYWORD)
PG_KEYWORD("use_variable", K_USE_VARIABLE, UNRESERVED_KEYWORD)
......
......@@ -128,7 +128,12 @@ enum
PLPGSQL_GETDIAG_ERROR_DETAIL,
PLPGSQL_GETDIAG_ERROR_HINT,
PLPGSQL_GETDIAG_RETURNED_SQLSTATE,
PLPGSQL_GETDIAG_MESSAGE_TEXT
PLPGSQL_GETDIAG_COLUMN_NAME,
PLPGSQL_GETDIAG_CONSTRAINT_NAME,
PLPGSQL_GETDIAG_DATATYPE_NAME,
PLPGSQL_GETDIAG_MESSAGE_TEXT,
PLPGSQL_GETDIAG_TABLE_NAME,
PLPGSQL_GETDIAG_SCHEMA_NAME
};
/* --------
......@@ -140,7 +145,12 @@ enum
PLPGSQL_RAISEOPTION_ERRCODE,
PLPGSQL_RAISEOPTION_MESSAGE,
PLPGSQL_RAISEOPTION_DETAIL,
PLPGSQL_RAISEOPTION_HINT
PLPGSQL_RAISEOPTION_HINT,
PLPGSQL_RAISEOPTION_COLUMN,
PLPGSQL_RAISEOPTION_CONSTRAINT,
PLPGSQL_RAISEOPTION_DATATYPE,
PLPGSQL_RAISEOPTION_TABLE,
PLPGSQL_RAISEOPTION_SCHEMA
};
/* --------
......
......@@ -3974,6 +3974,40 @@ select raise_test();
NOTICE: 22012
ERROR: substitute message
drop function raise_test();
-- test passing column_name, constraint_name, datatype_name, table_name
-- and schema_name error fields
create or replace function stacked_diagnostics_test() returns void as $$
declare _column_name text;
_constraint_name text;
_datatype_name text;
_table_name text;
_schema_name text;
begin
raise exception using
column = '>>some column name<<',
constraint = '>>some constraint name<<',
datatype = '>>some datatype name<<',
table = '>>some table name<<',
schema = '>>some schema name<<';
exception when others then
get stacked diagnostics
_column_name = column_name,
_constraint_name = constraint_name,
_datatype_name = pg_datatype_name,
_table_name = table_name,
_schema_name = schema_name;
raise notice 'column %, constraint %, type %, table %, schema %',
_column_name, _constraint_name, _datatype_name, _table_name, _schema_name;
end;
$$ language plpgsql;
select stacked_diagnostics_test();
NOTICE: column >>some column name<<, constraint >>some constraint name<<, type >>some datatype name<<, table >>some table name<<, schema >>some schema name<<
stacked_diagnostics_test
--------------------------
(1 row)
drop function stacked_diagnostics_test();
-- test CASE statement
create or replace function case_test(bigint) returns text as $$
declare a int = 10;
......
......@@ -3262,6 +3262,38 @@ select raise_test();
drop function raise_test();
-- test passing column_name, constraint_name, datatype_name, table_name
-- and schema_name error fields
create or replace function stacked_diagnostics_test() returns void as $$
declare _column_name text;
_constraint_name text;
_datatype_name text;
_table_name text;
_schema_name text;
begin
raise exception using
column = '>>some column name<<',
constraint = '>>some constraint name<<',
datatype = '>>some datatype name<<',
table = '>>some table name<<',
schema = '>>some schema name<<';
exception when others then
get stacked diagnostics
_column_name = column_name,
_constraint_name = constraint_name,
_datatype_name = pg_datatype_name,
_table_name = table_name,
_schema_name = schema_name;
raise notice 'column %, constraint %, type %, table %, schema %',
_column_name, _constraint_name, _datatype_name, _table_name, _schema_name;
end;
$$ language plpgsql;
select stacked_diagnostics_test();
drop function stacked_diagnostics_test();
-- test CASE statement
create or replace function case_test(bigint) returns text as $$
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册