Adding more information to errors

"Martin J. Evans" <[email protected]>
Newsgroups gmane.comp.lang.perl.modules.dbi.sybase.devel
Message-ID <[email protected]>
I've recently been asked why DBD::ODBC does not tell you which bound 
parameter or bound column is in error when an insert/select specifies a 
type which the driver cannot convert to e.g., column is varchar(10) and 
bind column as an integer and the content cannot be converted to an 
integer or you bind a string parameter 'fred' to an integer column; 
there are other examples more complex. When you've only got a few 
parameters/columns it is not difficult but when you've got tens of them 
it is a different matter. The thing is many (most?) ODBC drivers can 
tell you which bound column/parameter is in error via 
SQLGetDiagField(SQL_DIAG_COLUMN_NUMBER).

set_err only allows a driver to add:

$rv = $h->set_err($err, $errstr, $state, $method, $rv);

native error code, error message, state, method and alternative return 
value.

ODBC provides a number of other fields available per error - see 
http://msdn.microsoft.com/en-us/library/windows/desktop/ms710181%28v=vs.85%29.aspx

Not all of them are that useful but a few like SQL_DIAG_COLUMN_NUMBER 
are and SQL_DIAG_ROW_NUMBER is useful when doing execute_for_fetch as it 
indicates the row in error. In the latter case I had to write special 
code to handle that when I implemented execute_for_fetch as there was no 
way in DBI to store it.

I can add methods or attributes to DBD::ODBC to allow you to retrieve 
the additional fields for an error but it is problematic because which 
error are we talking about if there are multiple ones for one ODBC call 
- I think I'd end up simply adding Perl wrappers for the actual ODBC 
calls below and I doubt anyone would use them. Basically in ODBC when an 
error occurs the ODBC 3 way of doing things is:

assuming the last operation was on statement
recno = 1;
do {
    SQLGetDiagRec(this_is_a_statement_handle, sth, recno, &state, 
&native_error, &msg_text, msg_text_buf_len,
&length_of_returned_msg_text);
   # these values are passed to set_err
   # DBD::ODBC does not currently do the following except in 
execute_for_fetch special case
   # and it has nothing to do with set_err right now:
   for (each additional field of interest) {
      SQLGetDiagField(...);
   }
   # obviously there is logic to differentiate errors and warnings and 
info here
   set_err(...);
   recno++;
} while we got an error

I'm looking for ideas of how best to do this. An obvious choice would be 
to add a hash to the end of set_err where a DBD could add whatever 
additional keys are meaningful and perhaps we could define some standard 
ones - but that is just an option and I'm not sure what happens if there 
are multiple errors (other than when you've got an error handler).

Any comments? What do other DBDs have access to that does not fit into 
set_err? Even if people don't think there is any need to add anything to 
DBI, do any other DBDs have anything to do this?

Martin
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.