Skip to content

Commit 45cfd24

Browse files
author
Damien Churchill
committed
mssql: add support for a user supplied msghandler
As things stand, it is impossible to gain access to messages emitted from the server from a stored proc. Add support in _mssql for providing your own msghandler (which gets executed from pymssql's msghandler).
1 parent a113930 commit 45cfd24

File tree

2 files changed

+42
-20
lines changed

2 files changed

+42
-20
lines changed

_mssql.pxd

+4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ cdef class MSSQLConnection:
3030
cdef tuple column_names
3131
cdef tuple column_types
3232

33+
cdef object msghandler
34+
3335
cpdef cancel(self)
3436
cdef void clear_metadata(self)
3537
cdef object convert_db_value(self, BYTE *, int, int)
@@ -45,6 +47,8 @@ cdef class MSSQLConnection:
4547
cdef get_result(self)
4648
cdef get_row(self, int)
4749

50+
cpdef set_msghandler(self, object handler)
51+
4852
cdef class MSSQLRowIterator:
4953
cdef MSSQLConnection conn
5054

_mssql.pyx

+38-20
Original file line numberDiff line numberDiff line change
@@ -252,38 +252,46 @@ cdef int msg_handler(DBPROCESS *dbproc, DBINT msgno, int msgstate,
252252
cdef char *mssql_lastmsgsrv
253253
cdef char *mssql_lastmsgproc
254254
cdef int _min_error_severity = min_error_severity
255+
cdef MSSQLConnection conn = None
255256

256257
IF PYMSSQL_DEBUG == 1:
257258
fprintf(stderr, "\n+++ msg_handler(dbproc = %p, msgno = %d, " \
258259
"msgstate = %d, severity = %d, msgtext = '%s', " \
259260
"srvname = '%s', procname = '%s', line = %d)\n",
260-
<void *>dbproc, msgno, msgstate, severity, msgtext, srvname,
261+
dbproc, msgno, msgstate, severity, msgtext, srvname,
261262
procname, line);
262263
fprintf(stderr, "+++ previous max severity = %d\n\n",
263264
_mssql_last_msg_severity);
264265

266+
for cnx in connection_object_list:
267+
if (<MSSQLConnection>cnx).dbproc != dbproc:
268+
continue
269+
270+
conn = <MSSQLConnection>cnx
271+
break
272+
273+
if conn is not None and conn.msghandler is not None:
274+
conn.msghandler(msgstate, severity, srvname, procname, line, msgtext)
275+
265276
if severity < _min_error_severity:
266277
return INT_CANCEL
267278

268-
mssql_lastmsgstr = _mssql_last_msg_str
269-
mssql_lastmsgsrv = _mssql_last_msg_srv
270-
mssql_lastmsgproc = _mssql_last_msg_proc
271-
mssql_lastmsgno = &_mssql_last_msg_no
272-
mssql_lastmsgseverity = &_mssql_last_msg_severity
273-
mssql_lastmsgstate = &_mssql_last_msg_state
274-
mssql_lastmsgline = &_mssql_last_msg_line
275-
276-
for conn in connection_object_list:
277-
if dbproc != (<MSSQLConnection>conn).dbproc:
278-
continue
279-
mssql_lastmsgstr = (<MSSQLConnection>conn).last_msg_str
280-
mssql_lastmsgsrv = (<MSSQLConnection>conn).last_msg_srv
281-
mssql_lastmsgproc = (<MSSQLConnection>conn).last_msg_proc
282-
mssql_lastmsgno = &(<MSSQLConnection>conn).last_msg_no
283-
mssql_lastmsgseverity = &(<MSSQLConnection>conn).last_msg_severity
284-
mssql_lastmsgstate = &(<MSSQLConnection>conn).last_msg_state
285-
mssql_lastmsgline = &(<MSSQLConnection>conn).last_msg_line
286-
break
279+
if conn is not None:
280+
mssql_lastmsgstr = conn.last_msg_str
281+
mssql_lastmsgsrv = conn.last_msg_srv
282+
mssql_lastmsgproc = conn.last_msg_proc
283+
mssql_lastmsgno = &conn.last_msg_no
284+
mssql_lastmsgseverity = &conn.last_msg_severity
285+
mssql_lastmsgstate = &conn.last_msg_state
286+
mssql_lastmsgline = &conn.last_msg_line
287+
else:
288+
mssql_lastmsgstr = _mssql_last_msg_str
289+
mssql_lastmsgsrv = _mssql_last_msg_srv
290+
mssql_lastmsgproc = _mssql_last_msg_proc
291+
mssql_lastmsgno = &_mssql_last_msg_no
292+
mssql_lastmsgseverity = &_mssql_last_msg_severity
293+
mssql_lastmsgstate = &_mssql_last_msg_state
294+
mssql_lastmsgline = &_mssql_last_msg_line
287295

288296
# Calculate the maximum severity of all messages in a row
289297
# Fill the remaining fields as this is going to raise the exception
@@ -561,6 +569,16 @@ cdef class MSSQLConnection:
561569
clr_err(self)
562570
return MSSQLRowIterator(self)
563571

572+
cpdef set_msghandler(self, object handler):
573+
"""
574+
set_msghandler(handler) -- set the msghandler for the connection
575+
576+
This function allows setting a msghandler for the connection to
577+
allow a client to gain access to the messages returned from the
578+
server.
579+
"""
580+
self.msghandler = handler
581+
564582
cpdef cancel(self):
565583
"""
566584
cancel() -- cancel all pending results.

0 commit comments

Comments
 (0)