Steve Hay wrote:

Steve,

I'm really sorry I didn't respond to this and your subsequent emails. I have been involved with our falcon project which is top priority right now, as well as selling a home and moving across country so much of my free time has been non-existent.

Tim emailed me some of your emails, and I would like to catch up on what people have been kindly trying to help improve the driver. I think what I want to do is give svn access to people who want to give patches and utilise the community of people who want to be involved. As Tim says, better to be a cat-herder than a bottleneck ;)

Do you have a CPAN user ID? Please sent it to me if you like, and I can make you a co-maintainer which will give you the ability to commit fixes to the source.

Also, if I seem unresponsive, please feel free to email me directly. In addition to this mailing list, I have 30 other folders just within MySQL to puruse daily, and unfortunately, I miss some things.

I will look at all the patches and add them to the next release which I hope to make this week.

Kind regards,

Patrick

Hi Patrick,

Patrick Galbraith wrote:

NOTICE: (as I said in the last release) Very soon, perhaps in a release or so, I intend to stabilise the dev release and make that the production release. This means that server
side prepared statements will be turned on by default.

[...]

As the community, one think you can do if you are interested in helping
is to turn on server side prepare statements in 3.0006, or try the
development driver, 3.0006_1 to see if there are any problems. I've
tested the code as much as I can, but I know nothing tests code like
1000s of developers thinking of unique ways of using the driver that I
never could have imagined. If you find a bug, please report it to me,


I've been trying out some of my code with 3.0006_1 and I've found a problem with the server prepare statement code: when passing the undefined value to bind_param() to insert a NULL into an INT or DOUBLE column, bind_param() issues a warning about "Use of uninitialized value in subroutine entry".

It didn't use to do this, and doesn't do it now if server prepare is disabled. The attached dbi.pl program demonstrates this: the output is

Use of uninitialized value in subroutine entry at dbi.pl line 27.

If you switch to emulated prepare then the warning doesn't appear.

The warning comes from the calls to SvIV() and SvNV() in the switch statement within dbd_bind_ph(): these functions warn when their argument is undefined.

The attached patch (aginst 3.0006_1) fixes this by moving the switch statement inside the if (SvOK() ...) { } block a few lines higher up.

Cheers,
- Steve


------------------------------------------------
Radan Computational Ltd.

The information contained in this message and any files transmitted with it are confidential and intended for the addressee(s) only. If you have received this message in error or there are any problems, please notify the sender immediately. The unauthorized use, disclosure, copying or alteration of this message is strictly forbidden. Note that any views or opinions presented in this email are solely those of the author and do not necessarily represent those of Radan Computational Ltd. The recipient(s) of this message should check it and any attached files for viruses: Radan Computational will accept no liability for any damage caused by any virus transmitted by this email.

------------------------------------------------------------------------

use strict;
use warnings;
use DBI qw(:sql_types);
my $tmp_dbh = DBI->connect(
 'dbi:mysql:database=mysql', 'root', undef,
 { AutoCommit => 1, PrintError => 0, RaiseError => 1 }
);
$tmp_dbh->do('CREATE DATABASE IF NOT EXISTS test');
$tmp_dbh->disconnect();
my $dsn = 'dbi:mysql:database=test;mysql_server_prepare=1';    # warns
#my $dsn = 'dbi:mysql:database=test;mysql_emulated_prepare=1'; # doesn't warn
my $dbh = DBI->connect(
 $dsn, 'root', undef,
 { AutoCommit => 1, PrintError => 0, RaiseError => 1 }
);
$dbh->do('DROP TABLE IF EXISTS foo');
$dbh->do(qq{CREATE TABLE foo (
 id  INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
 num INT
) ENGINE=InnoDB});
$dbh->do("INSERT INTO foo VALUES(NULL, 1)");
my $rows = $dbh->selectall_arrayref('SELECT * FROM foo');
printf "ROW 1: id = %s, num = %s\n",
 $rows->[0][0], (defined $rows->[0][1] ? $rows->[0][1] : 'NULL');
my $sql = 'UPDATE foo SET num = ? WHERE id = ?';
my $sth = $dbh->prepare($sql);
$sth->bind_param(1, undef, SQL_INTEGER);
$sth->bind_param(2, 1, SQL_INTEGER);
my $num_rows = $sth->execute();
print "UPDATE affected $num_rows rows\n";
$rows = $dbh->selectall_arrayref('SELECT * FROM foo');
printf "ROW 1: id = %s, num = %s\n",
 $rows->[0][0], (defined $rows->[0][1] ? $rows->[0][1] : 'NULL');
$dbh->disconnect();
------------------------------------------------------------------------

--- DBD-mysql-3.0006_1/dbdimp.c.orig    2006-06-14 10:15:15.833207900 +0100
+++ DBD-mysql-3.0006_1/dbdimp.c 2006-06-14 10:17:30.820174600 +0100
@@ -3961,77 +3961,77 @@
    if (imp_sth->use_server_side_prepare)
    {
      if (SvOK(imp_sth->params[idx].value) && imp_sth->params[idx].value)
+      {
        buffer_is_null= 0;
+
+        switch(sql_type) {
+          case SQL_NUMERIC:
+          case SQL_INTEGER:
+          case SQL_SMALLINT:
+          case SQL_BIGINT:
+          case SQL_TINYINT:
+            /* INT */
+          if (!SvIOK(imp_sth->params[idx].value) && dbis->debug >= 2)
+            PerlIO_printf(DBILOGFP, "\t\tTRY TO BIND AN INT NUMBER\n");
+
+          buffer_type= MYSQL_TYPE_LONG;
+          imp_sth->fbind[idx].numeric_val.lval= 
SvIV(imp_sth->params[idx].value);
+          buffer=(void*)&(imp_sth->fbind[idx].numeric_val.lval);
+          if (dbis->debug >= 2)
+            PerlIO_printf(DBILOGFP,
+                          "   SCALAR type %d ->%ld<- IS A INT NUMBER\n",
+                          sql_type, (long) (*buffer));
+            break;
+
+          case SQL_DOUBLE:
+          case SQL_DECIMAL:
+          case SQL_FLOAT:
+          case SQL_REAL:
+            if (!SvNOK(imp_sth->params[idx].value) && dbis->debug >= 2)
+              PerlIO_printf(DBILOGFP, "\t\tTRY TO BIND A FLOAT NUMBER\n");
+
+              buffer_type= MYSQL_TYPE_DOUBLE;
+              imp_sth->fbind[idx].numeric_val.dval= 
SvNV(imp_sth->params[idx].value);
+              buffer=(char*)&(imp_sth->fbind[idx].numeric_val.dval);
+
+              if (dbis->debug >= 2)
+                PerlIO_printf(DBILOGFP,
+                            "   SCALAR type %d ->%f<- IS A FLOAT NUMBER\n",
+                            sql_type, (double)(*buffer));
+            break;
+
+          case SQL_CHAR:
+          case SQL_VARCHAR:
+          case SQL_DATE:
+          case SQL_TIME:
+          case SQL_TIMESTAMP:
+          case SQL_LONGVARCHAR:
+          case SQL_BINARY:
+          case SQL_VARBINARY:
+          case SQL_LONGVARBINARY:
+            buffer_type= MYSQL_TYPE_STRING;
+            break;
+
+          default:
+            buffer_type= MYSQL_TYPE_STRING;
+            break;
+        }
+
+        if (buffer_type == MYSQL_TYPE_STRING)
+        {
+          buffer= SvPV(imp_sth->params[idx].value, slen);
+          buffer_length= slen;
+          if (dbis->debug >= 2)
+            PerlIO_printf(DBILOGFP,
+                          "   SCALAR type %d ->%s<- IS A STRING\n",
+                          sql_type, buffer);
+        }
+      }
      else
      {
        buffer= NULL;
        buffer_is_null= 1;
-      }
-
-      switch(sql_type) {
-        case SQL_NUMERIC:
-        case SQL_INTEGER:
-        case SQL_SMALLINT:
-        case SQL_BIGINT:
-        case SQL_TINYINT:
-          /* INT */
-        if (!SvIOK(imp_sth->params[idx].value) && dbis->debug >= 2)
-          PerlIO_printf(DBILOGFP, "\t\tTRY TO BIND AN INT NUMBER\n");
-
-        buffer_type= MYSQL_TYPE_LONG;
-        imp_sth->fbind[idx].numeric_val.lval= SvIV(imp_sth->params[idx].value);
-        buffer=(void*)&(imp_sth->fbind[idx].numeric_val.lval);
-        if (dbis->debug >= 2)
-          PerlIO_printf(DBILOGFP,
-                        "   SCALAR type %d ->%ld<- IS A INT NUMBER\n",
-                        sql_type, (long) (*buffer));
-          break;
-
-        case SQL_DOUBLE:
-        case SQL_DECIMAL:
-        case SQL_FLOAT:
-        case SQL_REAL:
-          if (!SvNOK(imp_sth->params[idx].value) && dbis->debug >= 2)
-            PerlIO_printf(DBILOGFP, "\t\tTRY TO BIND A FLOAT NUMBER\n");
-
-            buffer_type= MYSQL_TYPE_DOUBLE;
-            imp_sth->fbind[idx].numeric_val.dval= 
SvNV(imp_sth->params[idx].value);
-            buffer=(char*)&(imp_sth->fbind[idx].numeric_val.dval);
-
-            if (dbis->debug >= 2)
-              PerlIO_printf(DBILOGFP,
-                          "   SCALAR type %d ->%f<- IS A FLOAT NUMBER\n",
-                          sql_type, (double)(*buffer));
-          break;
-
-        case SQL_CHAR:
-        case SQL_VARCHAR:
-        case SQL_DATE:
-        case SQL_TIME:
-        case SQL_TIMESTAMP:
-        case SQL_LONGVARCHAR:
-        case SQL_BINARY:
-        case SQL_VARBINARY:
-        case SQL_LONGVARBINARY:
-          buffer_type= MYSQL_TYPE_STRING;
-          break;
-
-        default:
-          buffer_type= MYSQL_TYPE_STRING;
-          break;
-      }
-
-      if (buffer_is_null)
        buffer_type= MYSQL_TYPE_NULL;
-
-      if (buffer_type == MYSQL_TYPE_STRING)
-      {
-        buffer= SvPV(imp_sth->params[idx].value, slen);
-        buffer_length= slen;
-        if (dbis->debug >= 2)
-          PerlIO_printf(DBILOGFP,
-                        "   SCALAR type %d ->%s<- IS A STRING\n",
-                        sql_type, buffer);
      }

      /* Type of column was changed. Force to rebind */

Reply via email to