Bug #21028 DBD::mysql does not handle multiple data sets in stored procedures
Submitted: 13 Jul 2006 8:35 Modified: 23 Dec 2006 20:50
Reporter: Giuseppe Maxia Email Updates:
Status: Closed Impact on me:
None 
Category:Connectors: DBD::mysql ( Perl ) Severity:S2 (Serious)
Version:3.0002_5 and later OS:Linux (Linux)
Assigned to: Alexey Stroganov CPU Architecture:Any

[13 Jul 2006 8:35] Giuseppe Maxia
Description:
in version 3.0002_4, DBD::mysql handled multiple data sets from a stored procedure call. All versions after that don't have this feature any longer.

I am talking about procedures of this sort:

create procedtre testproc()
deterministic
begin
    select a, b, c    from t1;
    select a, b       from t1;
    select a, b, c, d from t1;
end

The test case provided passes with DBD::mysql 3.0002_4 and fails with any othe version. The test provided with DBD::mysql (t/80procs.t) does not catch this problem because it will only create a multi-set procedure but *does not call it*. 

How to repeat:
#!/usr/bin/perl
use strict;
use warnings;

use DBI;
use Test::More;
use Data::Dumper;
use English qw( -no_match_vars );
our $VERSION = 0.01;

my $CONF =  $ENV{MYCONF} || "$ENV{HOME}/.my.cnf";

my $dbh;
eval {
    #
    # change the connection statements
    # to suit your purposes
    $dbh = DBI->connect('dbi:mysql:test'
        #. ";mysql_emulated_prepare=1"
        . ";mysql_read_default_file=$CONF",
        undef,
        undef,
        {RaiseError => 1, PrintError => 0} )
        or die "can't connect : $DBI::errstr\n";

};
if ($EVAL_ERROR) {
     plan (skip_all => ' -- no connection available');
}
else {
    plan ( tests => 10 );
}

my $drop_proc = qq{
    drop procedure if exists test_multi_sets
};
my $create_proc = qq{
    create procedure test_multi_sets ()
    deterministic
    begin
        select user() as first_col;
        select user() as first_col, now() as second_col;
        select user() as first_col, now() as second_col, schema() as third_col;
    end
};

eval { $dbh->do($drop_proc) };
ok( ! $EVAL_ERROR, 'drop procedure' );

eval { $dbh->do($create_proc) };
ok( ! $EVAL_ERROR , 'create procedure');

my $sth;

eval { $sth = $dbh->prepare(qq{call test_multi_sets() }) } ;
ok( $sth , 'preparing statement handler');

eval { $sth->execute() };
ok( ! $EVAL_ERROR, 'executing sth - 1st time ' );
diag $EVAL_ERROR if $EVAL_ERROR;

my $dataset;

eval { $dataset = $sth->fetchrow_arrayref();  } ;
ok( $dataset && @$dataset == 1 , 'fetching first dataset');

my $more_results;

eval { $more_results =  $sth->more_results() };
ok( $more_results, 'more results available (1st time) ' ) ;

eval { $dataset = $sth->fetchrow_arrayref();  } ;
ok( $dataset && @$dataset == 2 , 'fetching second dataset');

eval { $more_results =  $sth->more_results() };
ok( $more_results, 'more results available (2nd time) ' ) ;

eval { $dataset = $sth->fetchrow_arrayref();  } ;
ok( $dataset && @$dataset == 3 , 'fetching third dataset');

eval { $more_results =  $sth->more_results() };
ok( ! $more_results, 'no more results available' ) ;

Suggested fix:
Patch the other versions with the code that worked for 3.0002_4.
Include this test in the test suite.
[13 Jul 2006 19:25] Valeriy Kravchuk
Thank you for a bug report. Verified with a similar test case:

openxs@suse:~/dbs/5.0> cat 21028.pl
#!/usr/bin/perl
use strict;
use warnings;

use DBI;
use Test::More;
use Data::Dumper;
use English qw( -no_match_vars );
our $VERSION = 0.01;

my $CONF =  $ENV{MYCONF} || "$ENV{HOME}/.my.cnf";
my $emulate = 1;
my $dbh;
eval {
    #
    # change the connection statements
    # to suit your purposes
    $dbh =
      DBI->connect("dbi:mysql:test:127.0.0.1;mysql_emulated_prepare=$emulate",
        'root',
        '',
        {RaiseError => 1, PrintError => 0} )
        or die "can't connect : $DBI::errstr\n";

};
if ($EVAL_ERROR) {
     plan (skip_all => ' -- no connection available');
}
else {
    plan ( tests => 10 );
}

print "\nEmulation of ps: $emulate, version: $DBD::mysql::VERSION\n";

my $drop_proc = qq{
    drop procedure if exists test_multi_sets
};
my $create_proc = qq{
    create procedure test_multi_sets ()
    deterministic
    begin
        select user() as first_col;
        select user() as first_col, now() as second_col;
        select user() as first_col, now() as second_col, schema() as third_col;
    end
};

eval { $dbh->do($drop_proc) };
ok( ! $EVAL_ERROR, 'drop procedure' );

eval { $dbh->do($create_proc) };
ok( ! $EVAL_ERROR , 'create procedure');

my $sth;

eval { $sth = $dbh->prepare(qq{call test_multi_sets() }) } ;
ok( $sth , 'preparing statement handler');

eval { $sth->execute() };
ok( ! $EVAL_ERROR, 'executing sth - 1st time ' );
diag $EVAL_ERROR if $EVAL_ERROR;

my $dataset;

eval { $dataset = $sth->fetchrow_arrayref();  } ;
ok( $dataset && @$dataset == 1 , 'fetching first dataset');

my $more_results;

eval { $more_results =  $sth->more_results() };
ok( $more_results, 'more results available (1st time) ' ) ;

eval { $dataset = $sth->fetchrow_arrayref();  } ;
ok( $dataset && @$dataset == 2 , 'fetching second dataset');

eval { $more_results =  $sth->more_results() };
ok( $more_results, 'more results available (2nd time) ' ) ;

eval { $dataset = $sth->fetchrow_arrayref();  } ;
ok( $dataset && @$dataset == 3 , 'fetching third dataset');

eval { $more_results =  $sth->more_results() };
ok( ! $more_results, 'no more results available' ) ;

I've got the following results:

openxs@suse:~/dbs/5.0> perl -w 21028.pl
1..10

Emulation of ps: 0, version: 3.0006_1
ok 1 - drop procedure
ok 2 - create procedure
ok 3 - preparing statement handler
ok 4 - executing sth - 1st time
ok 5 - fetching first dataset
ok 6 - more results available (1st time)
not ok 7 - fetching second dataset
#     Failed test (21028.pl at line 74)
ok 8 - more results available (2nd time)
not ok 9 - fetching third dataset
#     Failed test (21028.pl at line 80)
ok 10 - no more results available
# Looks like you failed 2 tests of 10.
openxs@suse:~/dbs/5.0> vi 21028.pl
openxs@suse:~/dbs/5.0> perl -w 21028.pl
1..10

Emulation of ps: 1, version: 3.0006_1
ok 1 - drop procedure
ok 2 - create procedure
ok 3 - preparing statement handler
ok 4 - executing sth - 1st time
ok 5 - fetching first dataset
ok 6 - more results available (1st time)
not ok 7 - fetching second dataset
#     Failed test (21028.pl at line 74)
ok 8 - more results available (2nd time)
not ok 9 - fetching third dataset
#     Failed test (21028.pl at line 80)
ok 10 - no more results available
# Looks like you failed 2 tests of 10.
[23 Dec 2006 20:50] Patrick Galbraith
This patch is approved and has fixed the problem. In  version 4.0.0 on cpan subversion tree for DBD::mysql