On 19/10/2010 18:03, Roode, Eric wrote:
On Tuesday, October 19, 2010 3:59 AM, Martin J. Evans wrote:

All drivers I've tried this with report 2 things. The 23000 error
for the insert of a null into a column which does not allow nulls
(the tds_error packet) then a 01000 informational (tds_info) which
states the statement has been terminated.

However, it does not get around the fact that SQLExecute is
returning SQL_SUCCESS_WITH_INFO with the broken driver. DBD::ODBC
uses the SQLExecute return to determine if the execute was
successful or not (as per the ODBC docs) and not the state of any
error it sees when recovering details of the errors and
informationals.

I suppose this could be changed but it would need additional logic
everywhere "if (SQL_SUCCEEDED(ret))" is called and some way of
recording the states it has seen since the last ODBC call. I'm not
keen on doing that and not only because the driver in this case is
broken.
I agree; it hardly seems worthwhile.  This is what I put in place
as a workaround.  Does it look reasonable?

  $retval = $sth->execute(...);
  $sqlstate = $handle->state;
  if (   (!defined $retval)
         || (defined $sqlstate&&   length $sqlstate
             &&   $sqlstate ne '00000'&&   $sqlstate ne 'S1000'
             &&   substr($sqlstate,0,2) ne '01')
        )
     {
          ...handle error condition


-- Eric


Yes.

I'd move that length test to later, just before the substr as it does not matter until just before the substr. I think you might be mixing ODBC 2 (e.g. the S1000) and 3 states - you should only get ODBC 3 states via DBD::ODBC. I'd need to check that and I cannot easily right now.

I think you might be able to do this in a more straight forward way using odbc_err_handler but I've not thought it through right now.

Martin

Reply via email to