Bug #16173 Failure to execute prepared statement with negative numbers on 4.0.x servers
Submitted: 4 Jan 2006 6:17 Modified: 28 Jan 2006 15:04
Reporter: Luoqi Chen Email Updates:
Status: Can't repeat Impact on me:
None 
Category:Connectors: DBD::mysql ( Perl ) Severity:S2 (Serious)
Version:3.0002 OS:FreeBSD (FreeBSD/Linux)
Assigned to: CPU Architecture:Any

[4 Jan 2006 6:17] Luoqi Chen
Description:
When using perl DBD 3.0002 with a 4.0.x server (or any server without server prepare support), execution of a prepared statement will skip any negative number when constructing the SQL query. For example,

$sth = $dbh->prepare('INSERT INTO t (n) VALUES (?)');
$sth->execute(-1);

will generate this query on the wire,
INSERT INTO t (n) VALUES ()

This is traced down to an incorrect cast from sth to dbh in function mysql_st_internal_execute() that results in a random value to be passed as bind_type_guessing parameter to parse_params(), combined with incorrect handling of negative number when bind_type_guessing == 1.

The attached patch fixes the first problem (incorrect cast).

How to repeat:
See the example in description.

Suggested fix:
--- dbdimp.c.orig       2005-09-23 17:15:45.000000000 -0700
+++ dbdimp.c    2006-01-03 21:23:13.664306880 -0800
@@ -402,7 +402,7 @@
                           STRLEN *slen_ptr,
                           imp_sth_ph_t* params,
                           int num_params,
-                          bool bind_type_guessing)
+                          int bind_type_guessing)
 {

   bool seen_neg, seen_dec;
@@ -2310,7 +2310,8 @@
                           int use_mysql_use_result
                          )
 {
-  D_imp_dbh(sth);
+  D_imp_sth(sth);
+  D_imp_dbh_from_sth;
   STRLEN slen;
   char *sbuf = SvPV(statement, slen);
   char *salloc = parse_params(svsock,
[28 Jan 2006 15:04] Valeriy Kravchuk
Thank you for a problem report. Sorry, but I was not able to repeat the problem you described on latest 4.0.27:

openxs@suse:~/dbs/4.0> bin/mysqld_safe --log &
[1] 23604
openxs@suse:~/dbs/4.0> Starting mysqld daemon with databases from /home/openxs/d
bs/4.0/var

openxs@suse:~/dbs/4.0> bin/mysql -uroot test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1 to server version: 4.0.27-log

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> show create table t;
+-------+-------------------------------------------------------------+
| Table | Create Table                                                |
+-------+-------------------------------------------------------------+
| t     | CREATE TABLE `t` (
  `n` int(11) default NULL
) TYPE=MyISAM |
+-------+-------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> exit
Bye
openxs@suse:~/dbs/4.0> cat ~/work/16173.pl
#!/usr/bin/perl

use DBI;
my $DSN='DBI:mysql:test:suse';
my $DBUSER='root';
my $DBPASSWD='';

my $dbh=DBI->connect($DSN, $DBUSER, $DBPASSWD) or die print "$!\n";
my $sql='INSERT INTO t (n) VALUES (?)';
my $sth=$dbh->prepare($sql);
$sth->execute(-1);

print "$!\n";

exit;
openxs@suse:~/dbs/4.0> perl ~/work/16173.pl

openxs@suse:~/dbs/4.0> cat var/suse.log
/home/openxs/dbs/4.0/libexec/mysqld, Version: 4.0.27-log, started with:
Tcp port: 3306  Unix socket: /tmp/mysql.sock
Time                 Id Command    Argument
060126 18:27:25       1 Connect     root@localhost on test
                      1 Query       show databases
                      1 Query       show tables
                      1 Field List  t
                      1 Field List  testaa
                      1 Field List  testad
060126 18:27:28       1 Query       show create table t
060126 18:27:29       1 Quit
060126 18:27:37       2 Connect     root@localhost on test
                      2 Query       SET AUTOCOMMIT=1
                      2 Query       INSERT INTO t (n) VALUES ('-1')
                      2 Quit

As you can see, query was written to the general query log appropriately.

openxs@suse:~/dbs/4.0> perl -v

This is perl, v5.8.6 built for i586-linux-thread-multi

Copyright 1987-2004, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using `man perl' or `perldoc perl'.  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

openxs@suse:~/dbs/4.0> uname -a
Linux suse 2.6.11.4-20a-default #1 Wed Mar 23 21:52:37 UTC 2005 i686 i686 i386 GNU/Linux

DBD::mysql 3.002 was built on this same machine in a default way agains 4.0.27 libraries.