@@ -17,6 +17,7 @@ void reportException(PyObject *pErrType,
1717 PyObject * pErrValue ,
1818 PyObject * pErrTraceback );
1919
20+ void reportMulticornException (PyObject * pErrValue );
2021
2122PGDLLEXPORT void
2223errorCheck ()
@@ -28,7 +29,22 @@ errorCheck()
2829 PyErr_Fetch (& pErrType , & pErrValue , & pErrTraceback );
2930 if (pErrType )
3031 {
31- reportException (pErrType , pErrValue , pErrTraceback );
32+ // if the error value has a property _is_multicorn_exception and a boolean value True, then we don't report the
33+ // error as a generic exception with a stack trace -- instead we just take the message, code(severity), hint,
34+ // and detail, and log it to Postgres. These exceptions are generated in utils.py to intercept ERROR/FATAL log
35+ // messages. So, first detect whether that's the case, and call a new reporting function...
36+ PyObject * is_multicorn_exception = PyObject_GetAttrString (pErrValue , "_is_multicorn_exception" );
37+ if (is_multicorn_exception != NULL && PyObject_IsTrue (is_multicorn_exception ))
38+ {
39+ Py_DECREF (is_multicorn_exception );
40+ Py_DECREF (pErrType );
41+ Py_DECREF (pErrTraceback );
42+ reportMulticornException (pErrValue );
43+ }
44+ else
45+ {
46+ reportException (pErrType , pErrValue , pErrTraceback );
47+ }
3248 }
3349}
3450
@@ -92,3 +108,64 @@ reportException(PyObject *pErrType, PyObject *pErrValue, PyObject *pErrTraceback
92108 errfinish (0 );
93109#endif
94110}
111+
112+ void reportMulticornException (PyObject * pErrValue )
113+ {
114+ int severity ;
115+ PyObject * message = PyObject_GetAttrString (pErrValue , "message" );
116+ PyObject * hint = PyObject_GetAttrString (pErrValue , "hint" );
117+ PyObject * detail = PyObject_GetAttrString (pErrValue , "detail" );
118+ PyObject * code = PyObject_GetAttrString (pErrValue , "code" );
119+ int level = PyLong_AsLong (code );
120+
121+ // Matches up with REPORT_CODES in utils.py
122+ switch (level )
123+ {
124+ case 3 :
125+ severity = ERROR ;
126+ break ;
127+ default :
128+ case 4 :
129+ severity = FATAL ;
130+ break ;
131+ }
132+
133+ PG_TRY ();
134+ {
135+
136+ #if PG_VERSION_NUM >= 130000
137+ if (errstart (severity , TEXTDOMAIN ))
138+ #else
139+ if (errstart (severity , __FILE__ , __LINE__ , PG_FUNCNAME_MACRO , TEXTDOMAIN ))
140+ #endif
141+ {
142+ errmsg ("%s" , PyString_AsString (message ));
143+ if (hint != NULL && hint != Py_None )
144+ {
145+ char * hintstr = PyString_AsString (hint );
146+ errhint ("%s" , hintstr );
147+ }
148+ if (detail != NULL && detail != Py_None )
149+ {
150+ char * detailstr = PyString_AsString (detail );
151+ errdetail ("%s" , detailstr );
152+ }
153+ #if PG_VERSION_NUM >= 130000
154+ errfinish (__FILE__ , __LINE__ , PG_FUNCNAME_MACRO );
155+ #else
156+ errfinish (0 );
157+ #endif
158+ }
159+
160+ }
161+ PG_CATCH ();
162+ {
163+ Py_DECREF (message );
164+ Py_DECREF (hint );
165+ Py_DECREF (detail );
166+ Py_DECREF (code );
167+ Py_DECREF (pErrValue );
168+ PG_RE_THROW ();
169+ }
170+ PG_END_TRY ();
171+ }
0 commit comments