Subject: | Uncaught error "cs_convert failed (to_numeric(%))" under certain circumstances |
Environment:
perl version: 5.12.4
DBI version: 1.616
DBD::Sybase version: 1.14
Steps to recreate:
Show quoted text
1> Create a table with a NUMERIC field (not an integer, tinyint, etc).
Show quoted text2> Set $dbh->{PrintError} to 0 and $dbh->{HandleError} and $dbh->
{syb_err_handler} to appropriate values.
Show quoted text3> Generate a prepared statement with the numeric field as one of the
where clause selection criteria, e.g. SELECT * FROM test_table WHERE
id=?
Show quoted text4> execute this prepared statement with a string value, e.g. $sth-
Show quoted text>execute('WILL FAIL')
This causes an error 'cs_convert failed (to_numeric(WILL FAIL)) at ...'
to be printed to STDERR. This does not occur with other data types that
I have been able to find, though my search has been far from exhaustive.
I believe this should trigger the error handler, and prevent the
prepared statement from being executed. Instead the statement is
executed using a '0' for the bound value, which would be a silent error
if this were to occur within an unmonitored application, such as a web
server.
I've tried using $dbh->{HandleSetError} as well as
DBD::Sybase::syb_set_cslib_cb; neither catch the error.
Sample code is attached. Please let me know if you need any further
information in order to be able to reproduce or troubleshoot this issue.
Thank you very much for all the work you do; we've been using ctLib, et
al for years and are working to convert to DBD::Sybase now.
David
Subject: | dbitest.pl |
#!/home/lewisd/dev/utils/mbxperl -I /home/lewisd/code/
use strict;
use Data::Dumper;
use Carp;
use DBI;
my $dbh = DBI->connect('DBI:Sybase:server=test;database=test', 'sa', '');
$dbh->{HandleError} = \&dbi_error_handler;
$dbh->{PrintError} = 0;
$dbh->{syb_err_handler} = \&sybase_error_handler;
my $create_table = qq{
CREATE TABLE test(
OrderID NUMERIC(5, 0) IDENTITY NOT NULL,
Name VARCHAR(10) NULL
)
};
$dbh->do($create_table);
$dbh->do(qq{INSERT INTO test(Name) VALUES('my name')});
#my $sql = qq{SELECT COUNT(*) FROM master..sysprocesses WHERE spid >= ?};
my $sql = qq{SELECT COUNT(*) FROM test WHERE OrderID >= ?};
my $sth = $dbh->prepare($sql);
# This works as expected.
my $value = 7;
$sth->execute($value);
my $array_ref = $sth->fetchall_arrayref({});
$sth->finish();
print "sql: $sql\nvalue: $value\n", Dumper($array_ref), "\n\n";
# This fails, but the error is uncaught.
# Additionally, the prepared statement is then executed in Sybase, which returns unwanted and invalid results.
# Effectively, it appears to pass in a '0' where the bound value placeholder is located.
$value = 'fail!!';
$sth->execute($value);
$array_ref = $sth->fetchall_arrayref({});
$sth->finish();
print "sql: $sql\nvalue: $value\n", Dumper($array_ref), "\n\n";
$sth = undef;
$dbh->do(qq{DROP TABLE test});
sub dbi_error_handler {
confess(shift);
print STDERR "\n\n";
return undef;
}
sub sybase_error_handler {
my ($error_code, $severity_level, $state, $line, $server, $procedure, $message, $sql, $error_type) = @_;
chomp($message);
my $log_stamp = &get_stamp();
print STDERR "In sybase_error_handler:\n";
print STDERR qq{$log_stamp $server - Error:
SevLvl: $severity_level
Number: $error_code
State: $state
Procedure: $procedure
Error Type: $error_type
Line: $line
MSG: $message
SQL: $sql
};
print STDERR Carp::longmess("\n\nTRACE INFO ON PID $$:\n"), "\n\n";
return 0;
}