Skip to content

Commit 0a9e6b4

Browse files
committed
Partial fix for asynchronous multi result sets
Only initial $sth->execute() call is asynchronous. Due to limitation of MySQL client $sth->more_results() call is blocking.
1 parent 45e8bd8 commit 0a9e6b4

File tree

2 files changed

+65
-9
lines changed

2 files changed

+65
-9
lines changed

dbdimp.c

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4089,6 +4089,19 @@ bool mariadb_st_more_results(SV* sth, imp_sth_t* imp_sth)
40894089
if (!SvROK(sth) || SvTYPE(SvRV(sth)) != SVt_PVHV)
40904090
croak("Expected hash array");
40914091

4092+
if (imp_sth->use_server_side_prepare)
4093+
{
4094+
mariadb_dr_do_error(sth, CR_NOT_IMPLEMENTED, "Processing of multiple result set is not possible with server side prepare", "HY000");
4095+
return FALSE;
4096+
}
4097+
4098+
if (imp_dbh->async_query_in_flight && imp_dbh->async_query_in_flight != imp_sth)
4099+
{
4100+
mariadb_dr_do_error(sth, CR_UNKNOWN_ERROR, "Gathering async_query_in_flight results for the wrong handle", "HY000");
4101+
return FALSE;
4102+
}
4103+
imp_dbh->async_query_in_flight = NULL;
4104+
40924105
if (!imp_dbh->pmysql && !mariadb_db_reconnect(sth, NULL))
40934106
{
40944107
mariadb_dr_do_error(sth, CR_SERVER_GONE_ERROR, "MySQL server has gone away", "HY000");
@@ -4104,12 +4117,6 @@ bool mariadb_st_more_results(SV* sth, imp_sth_t* imp_sth)
41044117
return FALSE;
41054118
}
41064119

4107-
if (imp_sth->use_server_side_prepare)
4108-
{
4109-
mariadb_dr_do_error(sth, CR_NOT_IMPLEMENTED, "Processing of multiple result set is not possible with server side prepare", "HY000");
4110-
return FALSE;
4111-
}
4112-
41134120
/*
41144121
* Free cached array attributes
41154122
*/
@@ -4203,7 +4210,6 @@ bool mariadb_st_more_results(SV* sth, imp_sth_t* imp_sth)
42034210
imp_sth->row_num = mysql_affected_rows(imp_dbh->pmysql);
42044211

42054212
imp_dbh->insertid = imp_sth->insertid = mysql_insert_id(imp_dbh->pmysql);
4206-
return TRUE;
42074213
}
42084214
else
42094215
{
@@ -4217,6 +4223,10 @@ bool mariadb_st_more_results(SV* sth, imp_sth_t* imp_sth)
42174223

42184224
DBIc_ACTIVE_on(imp_sth);
42194225
}
4226+
4227+
if (imp_sth->is_async && mysql_more_results(imp_dbh->pmysql))
4228+
imp_dbh->async_query_in_flight = imp_sth;
4229+
42204230
imp_dbh->pmysql->net.last_errno= 0;
42214231
return TRUE;
42224232
}
@@ -6475,7 +6485,7 @@ my_ulonglong mariadb_db_async_result(SV* h, MYSQL_RES** resp)
64756485
D_imp_xxh(h);
64766486
imp_dbh_t* dbh;
64776487
MYSQL* svsock = NULL;
6478-
MYSQL_RES* _res;
6488+
MYSQL_RES* _res = NULL;
64796489
my_ulonglong retval = 0;
64806490
unsigned int num_fields;
64816491
int htype;
@@ -6517,6 +6527,12 @@ my_ulonglong mariadb_db_async_result(SV* h, MYSQL_RES** resp)
65176527
return -1;
65186528
}
65196529

6530+
if (*resp)
6531+
{
6532+
mysql_free_result(*resp);
6533+
*resp = NULL;
6534+
}
6535+
65206536
if (!mysql_read_query_result(svsock))
65216537
{
65226538
*resp= mysql_store_result(svsock);
@@ -6561,7 +6577,15 @@ my_ulonglong mariadb_db_async_result(SV* h, MYSQL_RES** resp)
65616577
mysql_free_result(*resp);
65626578
*resp = NULL;
65636579
}
6580+
6581+
if (mysql_more_results(svsock))
6582+
dbh->async_query_in_flight = imp_xxh;
65646583
} else {
6584+
#if MYSQL_VERSION_ID < 50025
6585+
/* Cover a protocol design error: error packet does not contain the server status.
6586+
* Luckily, an error always aborts execution of a statement, so it is safe to turn off the flag. */
6587+
svsock->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
6588+
#endif
65656589
mariadb_dr_do_error(h, mysql_errno(svsock), mysql_error(svsock),
65666590
mysql_sqlstate(svsock));
65676591
return (my_ulonglong)-1;

t/88async-multi-stmts.t

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ require 'lib.pl';
1010

1111
my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password,
1212
{ RaiseError => 0, PrintError => 0, AutoCommit => 0, mariadb_multi_statements => 1 });
13-
plan tests => 45;
13+
plan tests => 65;
1414

1515
$dbh->do(<<SQL);
1616
CREATE TEMPORARY TABLE async_test (
@@ -88,8 +88,40 @@ is($sth0->last_insert_id(), 1);
8888
is($sth2->last_insert_id(), 4);
8989
is($dbh->last_insert_id(undef, undef, undef, undef), 5);
9090

91+
my $sth3 = $dbh->prepare('INSERT INTO async_test VALUES(6); INSERT INTO async_test VALUES(7); SYNTAX ERROR; INSERT INTO async_test VALUES(8)', { mariadb_async => 1 });
92+
93+
ok $sth3 or die $dbh->err;
94+
95+
ok $sth3->execute();
96+
97+
is($sth0->last_insert_id(), 1);
98+
is($sth2->last_insert_id(), 4);
99+
is($dbh->last_insert_id(undef, undef, undef, undef), 5);
100+
101+
ok $sth3->mariadb_async_result();
102+
103+
is($sth0->last_insert_id(), 1);
104+
is($sth2->last_insert_id(), 4);
105+
is($sth3->last_insert_id(), 6);
106+
is($dbh->last_insert_id(undef, undef, undef, undef), 6);
107+
108+
ok $sth3->more_results();
109+
110+
is($sth0->last_insert_id(), 1);
111+
is($sth2->last_insert_id(), 4);
112+
is($sth3->last_insert_id(), 7);
113+
is($dbh->last_insert_id(undef, undef, undef, undef), 7);
114+
115+
ok !$sth3->more_results();
116+
117+
is($sth0->last_insert_id(), 1);
118+
is($sth2->last_insert_id(), 4);
119+
is($sth3->last_insert_id(), 7);
120+
is($dbh->last_insert_id(undef, undef, undef, undef), 7);
121+
91122
undef $sth0;
92123
undef $sth1;
93124
undef $sth2;
125+
undef $sth3;
94126

95127
$dbh->disconnect;

0 commit comments

Comments
 (0)