diff options
author | Michael Paquier <michael@paquier.xyz> | 2023-02-28 08:04:13 +0900 |
---|---|---|
committer | Michael Paquier <michael@paquier.xyz> | 2023-02-28 08:04:13 +0900 |
commit | b8da37b3ada2e547983538b3e49f8079f85ce120 (patch) | |
tree | d3ecf7af84a5b492e7a2b62b79df0398f3c8bccd /src/backend/utils/adt/misc.c | |
parent | 728560db7d868b3ded9a8675742083ab89bcff7c (diff) | |
download | postgresql-b8da37b3ada2e547983538b3e49f8079f85ce120.tar.gz postgresql-b8da37b3ada2e547983538b3e49f8079f85ce120.zip |
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
Diffstat (limited to 'src/backend/utils/adt/misc.c')
-rw-r--r-- | src/backend/utils/adt/misc.c | 44 |
1 files changed, 36 insertions, 8 deletions
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 */ |