From b8da37b3ada2e547983538b3e49f8079f85ce120 Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Tue, 28 Feb 2023 08:04:13 +0900 Subject: Rework pg_input_error_message(), now renamed pg_input_error_info() pg_input_error_info() is now a SQL function able to return a row with more than just the error message generated for incorrect data type inputs when these are able to handle soft failures, returning more contents of ErrorData, as of: - The error message (same as before). - The error detail, if set. - The error hint, if set. - SQL error code. All the regression tests that relied on pg_input_error_message() are updated to reflect the effects of the rename. Per discussion with Tom Lane and Andrew Dunstan. Author: Nathan Bossart Discussion: https://postgr.es/m/139a68e1-bd1f-a9a7-b5fe-0be9845c6311@dunslane.net --- src/backend/utils/adt/misc.c | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) (limited to 'src/backend/utils/adt/misc.c') diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c index f95256efd3d..5d78d6dc060 100644 --- a/src/backend/utils/adt/misc.c +++ b/src/backend/utils/adt/misc.c @@ -660,32 +660,60 @@ pg_input_is_valid(PG_FUNCTION_ARGS) } /* - * pg_input_error_message - test whether string is valid input for datatype. + * pg_input_error_info - test whether string is valid input for datatype. * - * Returns NULL if OK, else the primary message string from the error. + * Returns NULL if OK, else the primary message, detail message, hint message + * and sql error code from the error. * * This will only work usefully if the datatype's input function has been * updated to return "soft" errors via errsave/ereturn. */ Datum -pg_input_error_message(PG_FUNCTION_ARGS) +pg_input_error_info(PG_FUNCTION_ARGS) { text *txt = PG_GETARG_TEXT_PP(0); text *typname = PG_GETARG_TEXT_PP(1); ErrorSaveContext escontext = {T_ErrorSaveContext}; + TupleDesc tupdesc; + Datum values[4]; + bool isnull[4]; + + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); /* Enable details_wanted */ escontext.details_wanted = true; if (pg_input_is_valid_common(fcinfo, txt, typname, &escontext)) - PG_RETURN_NULL(); + memset(isnull, true, sizeof(isnull)); + else + { + char *sqlstate; + + Assert(escontext.error_occurred); + Assert(escontext.error_data != NULL); + Assert(escontext.error_data->message != NULL); + + memset(isnull, false, sizeof(isnull)); - Assert(escontext.error_occurred); - Assert(escontext.error_data != NULL); - Assert(escontext.error_data->message != NULL); + values[0] = CStringGetTextDatum(escontext.error_data->message); + + if (escontext.error_data->detail != NULL) + values[1] = CStringGetTextDatum(escontext.error_data->detail); + else + isnull[1] = true; + + if (escontext.error_data->hint != NULL) + values[2] = CStringGetTextDatum(escontext.error_data->hint); + else + isnull[2] = true; + + sqlstate = unpack_sql_state(escontext.error_data->sqlerrcode); + values[3] = CStringGetTextDatum(sqlstate); + } - PG_RETURN_TEXT_P(cstring_to_text(escontext.error_data->message)); + return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, isnull)); } /* Common subroutine for the above */ -- cgit v1.2.3