--- dbdimp.c.orig 2008-04-28 19:36:17.000000000 -0400
+++ dbdimp.c 2008-07-24 00:17:33.000000000 -0400
@@ -2668,7 +2668,7 @@
/* No more pending result set(s)*/
if (DBIc_TRACE_LEVEL(imp_xxh) >= 2)
PerlIO_printf(DBILOGFP,
- "\n <- dbs_st_more_rows no more results\n");
+ "\n <- dbs_st_more_results no more results\n");
return 0;
}
@@ -2699,6 +2699,8 @@
next_result_return_code= mysql_next_result(svsock);
+ imp_sth->warning_count = mysql_warning_count(imp_dbh->pmysql);
+
/*
mysql_next_result returns
0 if there are more results
@@ -2721,10 +2723,13 @@
do_error(sth, mysql_errno(svsock), mysql_error(svsock),
mysql_sqlstate(svsock));
+ imp_sth->row_num= mysql_affected_rows(imp_dbh->pmysql);
+
if (imp_sth->result == NULL)
{
/* No "real" rowset*/
- return 0;
+ imp_sth->insertid= mysql_insert_id(imp_dbh->pmysql);
+ return 1;
}
else
{
@@ -3137,7 +3142,13 @@
if (imp_sth->row_num+1 != (my_ulonglong)-1)
{
if (!imp_sth->result)
+ {
imp_sth->insertid= mysql_insert_id(imp_dbh->pmysql);
+#if MYSQL_VERSION_ID >= MULTIPLE_RESULT_SET_VERSION
+ if (mysql_more_results(imp_dbh->pmysql))
+ DBIc_ACTIVE_on(imp_sth);
+#endif
+ }
else
{
/** Store the result in the current statement handle */
@@ -3674,7 +3685,7 @@
We don't close the cursor till DESTROY.
The application may re execute it.
*/
- if (imp_sth && imp_sth->result)
+ if (imp_sth && DBIc_ACTIVE(imp_sth))
{
/*
Clean-up previous result set(s) for sth to prevent
--- mysql.xs.orig 2008-07-24 00:44:01.000000000 -0400
+++ mysql.xs 2008-07-24 02:17:53.000000000 -0400
@@ -234,6 +234,9 @@
int retval;
struct imp_sth_ph_st* params= NULL;
MYSQL_RES* result= NULL;
+#if MYSQL_VERSION_ID >= MULTIPLE_RESULT_SET_VERSION
+ int next_result_rc;
+#endif
#if MYSQL_VERSION_ID >= SERVER_PREPARE_VERSION
STRLEN slen;
char *str_ptr, *statement_ptr, *buffer;
@@ -247,7 +250,16 @@
MYSQL_STMT *stmt= NULL;
MYSQL_BIND *bind= NULL;
imp_sth_phb_t *fbind= NULL;
-
+#endif
+#if MYSQL_VERSION_ID >= MULTIPLE_RESULT_SET_VERSION
+ while (mysql_next_result(imp_dbh->pmysql)==0)
+ {
+ MYSQL_RES* r = mysql_use_result(imp_dbh->pmysql);
+ if (r)
+ mysql_free_result(r);
+ }
+#endif
+#if MYSQL_VERSION_ID >= SERVER_PREPARE_VERSION
/*
* Globaly enabled using of server side prepared statement
* for dbh->do() statements. It is possible to force driver
@@ -492,6 +504,28 @@
mysql_free_result(result);
result= 0;
}
+#if MYSQL_VERSION_ID >= MULTIPLE_RESULT_SET_VERSION
+ if (retval != -2) /* -2 means error */
+ {
+ /* more results? -1 = no, >0 = error, 0 = yes (keep looping) */
+ while ((next_result_rc= mysql_next_result(imp_dbh->pmysql)) == 0)
+ {
+ result = mysql_use_result(imp_dbh->pmysql);
+ if (result)
+ mysql_free_result(result);
+ }
+ if (next_result_rc > 0)
+ {
+ if (dbis->debug >= 2)
+ PerlIO_printf(DBILOGFP, "\t<- do() ERROR: %s\n",
+ mysql_error(imp_dbh->pmysql));
+
+ do_error(dbh, mysql_errno(imp_dbh->pmysql),
+ mysql_error(imp_dbh->pmysql), mysql_sqlstate(imp_dbh->pmysql));
+ retval= -2;
+ }
+ }
+#endif
/* remember that dbd_st_execute must return <= -2 for error */
if (retval == 0) /* ok with no rows affected */
XST_mPV(0, "0E0"); /* (true but zero) */
--- t/76multi_statement.t.orig 2008-05-11 10:56:13.000000000 -0400
+++ t/76multi_statement.t 2008-07-24 02:10:11.000000000 -0400
@@ -19,21 +19,55 @@
if ($@) {
plan skip_all => "ERROR: $@. Can't continue test";
}
-plan tests => 7;
+plan tests => 27;
ok (defined $dbh, "Connected to database with multi statement support");
$dbh->{mysql_server_prepare}= 0;
SKIP: {
- skip "Server doesn't support multi statements", 6
+ skip "Server doesn't support multi statements", 26
if $dbh->get_info($GetInfoType{SQL_DBMS_VER}) lt "4.1";
ok($dbh->do("DROP TABLE IF EXISTS $table"), "clean up");
ok($dbh->do("CREATE TABLE $table (a INT)"), "create table");
- ok($dbh->do("INSERT INTO $table VALUES (1); INSERT INTO $table VALUES (2);"));
+ ok($dbh->do("INSERT INTO $table VALUES (1); INSERT INTO $table VALUES (2);"), "2 inserts");
+
+ # Check that a second do() doesn't fail with an 'Out of sync' error
+ ok($dbh->do("INSERT INTO $table VALUES (3); INSERT INTO $table VALUES (4);"), "2 more inserts");
+
+ # Check that more_results works for non-SELECT results too
+ my $sth;
+ ok($sth = $dbh->prepare("UPDATE $table SET a=5 WHERE a=1; UPDATE $table SET a='6-' WHERE a<4"));
+ ok($sth->execute(), "Execute updates");
+ is($sth->rows, 1, "First update affected 1 row");
+ is($sth->{mysql_warning_count}, 0, "First update had no warnings");
+ ok($sth->{Active}, "Statement handle is Active");
+ ok($sth->more_results());
+ is($sth->rows, 2, "Second update affected 2 rows");
+ is($sth->{mysql_warning_count}, 2, "Second update had 2 warnings");
+ ok(not $sth->more_results());
+ ok($sth->finish());
+
+ # Now run it again without calling more_results().
+ ok($sth->execute(), "Execute updates again");
+ ok($sth->finish());
+
+ # Check that do() doesn't fail with an 'Out of sync' error
+ is($dbh->do("DELETE FROM $table"), 4, "Delete all rows");
+
+ # Test that do() reports errors from all result sets
+ $dbh->{RaiseError} = $dbh->{PrintError} = 0;
+ ok(!$dbh->do("INSERT INTO $table VALUES (1); INSERT INTO bad_$table VALUES (2);"), "do() reports errors");
+
+ # Test that execute() reports errors from only the first result set
+ ok($sth = $dbh->prepare("UPDATE $table SET a=2; UPDATE bad_$table SET a=3"));
+ ok($sth->execute(), "Execute updates");
+ ok(!$sth->err(), "Err was not set after execute");
+ ok(!$sth->more_results());
+ ok($sth->err(), "Err was set after more_results");
$dbh->disconnect();