[freetds] Problem with message handler

James K. Lowden jklowden at freetds.org
Fri Sep 13 21:57:58 EDT 2013


On Fri, 13 Sep 2013 06:51:53 +0000
Chris Kings-Lynne <Chris.Kings-Lynne at navitas.com> wrote:

> I'm trying to fix the PHP pdo_dblib driver.  The issue is it never
> returns the actual database error message.  It always says "Check SQL
> server messages".  I've identified the problem in the message handler
> code here:
> 
> https://github.com/php/php-src/blob/master/ext/pdo_dblib/pdo_dblib.c#L140

Hmm, they did leave room for improvement, eh?  The handler is called
with msgno, severity, text, server name, procedure name, and line
number, but the function keeps only the text.  

It's also possible to get more than one message, but the function
unilaterally discards any it finds.  

Disregarding messages with serverity 0 isn't very general.  People
have been known to use the T-SQL PRINT statement, but they're uniformly
suppressed.  

I know, there are messages no one really wants to see.  I've handled
that in libraries I've written by maintaining a do-not-print list of
message numbers.  That way the application programmer has control over
which messages the handler handles.  

> The problem is that the msgno always comes through as the correct
> underlying sql error number (eg. 208), instead of the magic one
> that's being expected (20018). 

I think there may be some confusion on this point.  What you're calling
the "correct" msgno is attached to a *message* from the server.  It's
not necessarily an error.  It may be helpful to think of them as
runtime errors, because in principle they can be caused by things under
the user's control.  Usually the connection remains viable even if the
query fails.  Messages are handled by the message handler.  

The numbers your referred to in dblib.c are db-lib *errors*.  These are
caused by using db-lib incorrectly, and originate from the library,
not the server.  They are logic errors made by the programmer or
environmental issues (such as network failures) that the user has no
control over.  Depending on how badly things went awry, the connection
may be broken and/or the data corrupted.  Errors are handled by the
error handler.  

There's a special class of server message that represents an error
condition, where the server is experiencing heartburn.  Table
corruption, disk failure, or maybe the DBA killed the spid that was
executing the user's query.  These kinds of errors have high serverity
(where "high" is over 10 IIRC).  In such cases, the server will send
its message per usual, and db-lib will call the message handler, per
usual.  Then, just to make sure you got the message (as it were) it
calls the error handler too, with your friend and mine SYBEMSG.  

I ususally suppress SYBEMSG, because I make very sure to have printed
the message that preceded it.  

It's like the secretary leaving a "while you were out" message slip on
your desk.  We used to have people whose job it was to answer phones
and take messages.  The phone was attached to the wall by a wire, so
you couldn't just carry it around.  Oh, never mind.  We had offices,
too.  

--jkl


More information about the FreeTDS mailing list