diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2016-03-25 16:54:52 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2016-03-25 16:54:52 -0400 |
commit | cd37bb78599dcf24cd22a124ce9174b5e2a76880 (patch) | |
tree | f04472f34be85e8a2c7f458c708d8eaaacfcb8dd /src/pl/tcl/pltcl.c | |
parent | fb8d2a7f57d87102f0a95025fbf1cad9c341739b (diff) |
Improve PL/Tcl errorCode facility by providing decoded name for SQLSTATE.
We don't really want to encourage people to write numeric SQLSTATEs in
programs; that's unreadable and error-prone. Copy plpgsql's infrastructure
for converting between SQLSTATEs and exception names shown in Appendix A,
and modify examples in tests and documentation to do it that way.
Diffstat (limited to 'src/pl/tcl/pltcl.c')
-rw-r--r-- | src/pl/tcl/pltcl.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c index b1d66e31a6e..6ee4153ae62 100644 --- a/src/pl/tcl/pltcl.c +++ b/src/pl/tcl/pltcl.c @@ -189,6 +189,20 @@ static FunctionCallInfo pltcl_current_fcinfo = NULL; static pltcl_proc_desc *pltcl_current_prodesc = NULL; /********************************************************************** + * Lookup table for SQLSTATE condition names + **********************************************************************/ +typedef struct +{ + const char *label; + int sqlerrstate; +} TclExceptionNameMap; + +static const TclExceptionNameMap exception_name_map[] = { +#include "pltclerrcodes.h" /* pgrminclude ignore */ + {NULL, 0} +}; + +/********************************************************************** * Forward declarations **********************************************************************/ void _PG_init(void); @@ -213,6 +227,7 @@ static pltcl_proc_desc *compile_pltcl_function(Oid fn_oid, Oid tgreloid, static int pltcl_elog(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static void pltcl_construct_errorCode(Tcl_Interp *interp, ErrorData *edata); +static const char *pltcl_get_condition_name(int sqlstate); static int pltcl_quote(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int pltcl_argisnull(ClientData cdata, Tcl_Interp *interp, @@ -1682,6 +1697,10 @@ pltcl_construct_errorCode(Tcl_Interp *interp, ErrorData *edata) Tcl_ListObjAppendElement(interp, obj, Tcl_NewStringObj(unpack_sql_state(edata->sqlerrcode), -1)); Tcl_ListObjAppendElement(interp, obj, + Tcl_NewStringObj("condition", -1)); + Tcl_ListObjAppendElement(interp, obj, + Tcl_NewStringObj(pltcl_get_condition_name(edata->sqlerrcode), -1)); + Tcl_ListObjAppendElement(interp, obj, Tcl_NewStringObj("message", -1)); UTF_BEGIN; Tcl_ListObjAppendElement(interp, obj, @@ -1807,6 +1826,23 @@ pltcl_construct_errorCode(Tcl_Interp *interp, ErrorData *edata) /********************************************************************** + * pltcl_get_condition_name() - find name for SQLSTATE + **********************************************************************/ +static const char * +pltcl_get_condition_name(int sqlstate) +{ + int i; + + for (i = 0; exception_name_map[i].label != NULL; i++) + { + if (exception_name_map[i].sqlerrstate == sqlstate) + return exception_name_map[i].label; + } + return "unrecognized_sqlstate"; +} + + +/********************************************************************** * pltcl_quote() - quote literal strings that are to * be used in SPI_execute query strings **********************************************************************/ |