@@ -3712,7 +3712,7 @@ AV *mariadb_db_data_sources(SV *dbh, imp_dbh_t *imp_dbh, SV *attr)
3712
3712
return av ;
3713
3713
}
3714
3714
3715
- static bool mariadb_st_free_result_sets (SV * sth , imp_sth_t * imp_sth );
3715
+ static bool mariadb_st_free_result_sets (SV * sth , imp_sth_t * imp_sth , bool free_last );
3716
3716
3717
3717
/*
3718
3718
**************************************************************************
@@ -3774,7 +3774,6 @@ mariadb_st_prepare_sv(
3774
3774
imp_sth -> use_server_side_prepare = imp_dbh -> use_server_side_prepare ;
3775
3775
imp_sth -> disable_fallback_for_server_prepare = imp_dbh -> disable_fallback_for_server_prepare ;
3776
3776
3777
- imp_sth -> fetch_done = FALSE;
3778
3777
imp_sth -> done_desc = FALSE;
3779
3778
imp_sth -> result = NULL ;
3780
3779
imp_sth -> currow = 0 ;
@@ -3845,7 +3844,7 @@ mariadb_st_prepare_sv(
3845
3844
Clean-up previous result set(s) for sth to prevent
3846
3845
'Commands out of sync' error
3847
3846
*/
3848
- if (!mariadb_st_free_result_sets (sth , imp_sth ))
3847
+ if (!mariadb_st_free_result_sets (sth , imp_sth , TRUE ))
3849
3848
return 0 ;
3850
3849
3851
3850
if (imp_sth -> use_server_side_prepare )
@@ -3989,11 +3988,12 @@ mariadb_st_prepare_sv(
3989
3988
*
3990
3989
* Inputs: sth - Statement handle
3991
3990
* imp_sth - driver's private statement handle
3991
+ * free_last - free also the last result set
3992
3992
*
3993
3993
* Returns: TRUE ok
3994
3994
* FALSE error; mariadb_dr_do_error will be called
3995
3995
*************************************************************************/
3996
- static bool mariadb_st_free_result_sets (SV * sth , imp_sth_t * imp_sth )
3996
+ static bool mariadb_st_free_result_sets (SV * sth , imp_sth_t * imp_sth , bool free_last )
3997
3997
{
3998
3998
dTHX ;
3999
3999
D_imp_dbh_from_sth ;
@@ -4031,7 +4031,7 @@ static bool mariadb_st_free_result_sets(SV *sth, imp_sth_t *imp_sth)
4031
4031
imp_dbh -> insertid = imp_sth -> insertid = mysql_insert_id (imp_dbh -> pmysql );
4032
4032
}
4033
4033
}
4034
- if (imp_sth -> result )
4034
+ if (imp_sth -> result && ( mysql_more_results ( imp_dbh -> pmysql ) || free_last ) )
4035
4035
{
4036
4036
mysql_free_result (imp_sth -> result );
4037
4037
imp_sth -> result = NULL ;
@@ -4102,6 +4102,8 @@ bool mariadb_st_more_results(SV* sth, imp_sth_t* imp_sth)
4102
4102
}
4103
4103
imp_dbh -> async_query_in_flight = NULL ;
4104
4104
4105
+ DBIc_ACTIVE_off (imp_sth );
4106
+
4105
4107
if (!imp_dbh -> pmysql && !mariadb_db_reconnect (sth , NULL ))
4106
4108
{
4107
4109
mariadb_dr_do_error (sth , CR_SERVER_GONE_ERROR , "MySQL server has gone away" , "HY000" );
@@ -4163,9 +4165,6 @@ bool mariadb_st_more_results(SV* sth, imp_sth_t* imp_sth)
4163
4165
(void )hv_deletes ((HV * )SvRV (sth ), "mariadb_type_name" , G_DISCARD );
4164
4166
(void )hv_deletes ((HV * )SvRV (sth ), "mariadb_warning_count" , G_DISCARD );
4165
4167
4166
- if (DBIc_ACTIVE (imp_sth ))
4167
- DBIc_ACTIVE_off (imp_sth );
4168
-
4169
4168
next_result_return_code = mysql_next_result (imp_dbh -> pmysql );
4170
4169
4171
4170
imp_sth -> warning_count = mysql_warning_count (imp_dbh -> pmysql );
@@ -4210,6 +4209,9 @@ bool mariadb_st_more_results(SV* sth, imp_sth_t* imp_sth)
4210
4209
imp_sth -> row_num = mysql_affected_rows (imp_dbh -> pmysql );
4211
4210
4212
4211
imp_dbh -> insertid = imp_sth -> insertid = mysql_insert_id (imp_dbh -> pmysql );
4212
+
4213
+ if (mysql_more_results (imp_dbh -> pmysql ))
4214
+ DBIc_ACTIVE_on (imp_sth );
4213
4215
}
4214
4216
else
4215
4217
{
@@ -4221,7 +4223,8 @@ bool mariadb_st_more_results(SV* sth, imp_sth_t* imp_sth)
4221
4223
sv_2mortal (newSVuv (mysql_num_fields (imp_sth -> result )))
4222
4224
);
4223
4225
4224
- DBIc_ACTIVE_on (imp_sth );
4226
+ if (imp_sth -> row_num )
4227
+ DBIc_ACTIVE_on (imp_sth );
4225
4228
}
4226
4229
4227
4230
if (imp_sth -> is_async && mysql_more_results (imp_dbh -> pmysql ))
@@ -4619,7 +4622,7 @@ IV mariadb_st_execute_iv(SV* sth, imp_sth_t* imp_sth)
4619
4622
Clean-up previous result set(s) for sth to prevent
4620
4623
'Commands out of sync' error
4621
4624
*/
4622
- if (!mariadb_st_free_result_sets (sth , imp_sth ))
4625
+ if (!mariadb_st_free_result_sets (sth , imp_sth , TRUE ))
4623
4626
return -2 ;
4624
4627
4625
4628
if (use_server_side_prepare )
@@ -4694,10 +4697,10 @@ IV mariadb_st_execute_iv(SV* sth, imp_sth_t* imp_sth)
4694
4697
/** Store the result in the current statement handle */
4695
4698
num_fields = mysql_num_fields (imp_sth -> result );
4696
4699
DBIc_NUM_FIELDS (imp_sth ) = (num_fields <= INT_MAX ) ? num_fields : INT_MAX ;
4697
- DBIc_ACTIVE_on (imp_sth );
4700
+ if (imp_sth -> row_num )
4701
+ DBIc_ACTIVE_on (imp_sth );
4698
4702
if (!use_server_side_prepare )
4699
4703
imp_sth -> done_desc = FALSE;
4700
- imp_sth -> fetch_done = FALSE;
4701
4704
}
4702
4705
}
4703
4706
@@ -4740,6 +4743,9 @@ static int mariadb_st_describe(SV* sth, imp_sth_t* imp_sth)
4740
4743
if (DBIc_TRACE_LEVEL (imp_xxh ) >= 2 )
4741
4744
PerlIO_printf (DBIc_LOGPIO (imp_xxh ), "\t--> mariadb_st_describe\n" );
4742
4745
4746
+ if (imp_sth -> done_desc )
4747
+ return 1 ;
4748
+
4743
4749
if (imp_sth -> use_server_side_prepare )
4744
4750
{
4745
4751
int i ;
@@ -4752,9 +4758,6 @@ static int mariadb_st_describe(SV* sth, imp_sth_t* imp_sth)
4752
4758
PerlIO_printf (DBIc_LOGPIO (imp_xxh ), "\t\tmariadb_st_describe() num_fields %d\n" ,
4753
4759
num_fields );
4754
4760
4755
- if (imp_sth -> done_desc )
4756
- return 1 ;
4757
-
4758
4761
if (num_fields <= 0 || !imp_sth -> result )
4759
4762
{
4760
4763
/* no metadata */
@@ -4916,30 +4919,22 @@ mariadb_st_fetch(SV *sth, imp_sth_t* imp_sth)
4916
4919
return Nullav ;
4917
4920
}
4918
4921
4919
- if (imp_dbh -> async_query_in_flight ) {
4920
- if (mariadb_db_async_result (sth , & imp_sth -> result ) == (my_ulonglong )- 1 )
4921
- return Nullav ;
4922
+ if (imp_dbh -> async_query_in_flight )
4923
+ {
4924
+ if (!DBIc_ACTIVE (imp_sth ))
4925
+ return Nullav ;
4926
+ if (mariadb_db_async_result (sth , & imp_sth -> result ) == (my_ulonglong )- 1 )
4927
+ return Nullav ;
4922
4928
}
4923
-
4924
- if (imp_sth -> use_server_side_prepare )
4929
+ else
4925
4930
{
4926
- if (!DBIc_ACTIVE ( imp_sth ) )
4931
+ if (!imp_sth -> result )
4927
4932
{
4928
- mariadb_dr_do_error (sth , CR_UNKNOWN_ERROR , "no statement executing " , "HY000" );
4933
+ mariadb_dr_do_error (sth , CR_UNKNOWN_ERROR , "fetch() without execute() " , "HY000" );
4929
4934
return Nullav ;
4930
4935
}
4931
-
4932
- if (imp_sth -> fetch_done )
4933
- {
4934
- mariadb_dr_do_error (sth , CR_UNKNOWN_ERROR , "fetch() but fetch already done" , "HY000" );
4936
+ if (!DBIc_ACTIVE (imp_sth ))
4935
4937
return Nullav ;
4936
- }
4937
-
4938
- if (!imp_sth -> done_desc )
4939
- {
4940
- if (!mariadb_st_describe (sth , imp_sth ))
4941
- return Nullav ;
4942
- }
4943
4938
}
4944
4939
4945
4940
ChopBlanks = DBIc_is (imp_sth , DBIcf_ChopBlanks ) ? TRUE : FALSE;
@@ -4949,19 +4944,16 @@ mariadb_st_fetch(SV *sth, imp_sth_t* imp_sth)
4949
4944
"\t\tmariadb_st_fetch for %p, chopblanks %d\n" ,
4950
4945
sth , ChopBlanks ? 1 : 0 );
4951
4946
4952
- if (!imp_sth -> result )
4953
- {
4954
- mariadb_dr_do_error (sth , CR_UNKNOWN_ERROR , "fetch() without execute()" , "HY000" );
4955
- return Nullav ;
4956
- }
4957
-
4958
4947
/* fix from 2.9008 */
4959
4948
imp_dbh -> pmysql -> net .last_errno = 0 ;
4960
4949
4961
4950
if (imp_sth -> use_server_side_prepare )
4962
4951
{
4952
+ if (!mariadb_st_describe (sth , imp_sth ))
4953
+ return Nullav ;
4954
+
4963
4955
if (DBIc_TRACE_LEVEL (imp_xxh ) >= 2 )
4964
- PerlIO_printf (DBIc_LOGPIO (imp_xxh ), "\t\tmariadb_st_fetch calling mysql_fetch \n" );
4956
+ PerlIO_printf (DBIc_LOGPIO (imp_xxh ), "\t\tmariadb_st_fetch calling mysql_stmt_fetch \n" );
4965
4957
4966
4958
if ((rc = mysql_stmt_fetch (imp_sth -> stmt )))
4967
4959
{
@@ -4975,7 +4967,6 @@ mariadb_st_fetch(SV *sth, imp_sth_t* imp_sth)
4975
4967
4976
4968
if (rc == MYSQL_NO_DATA )
4977
4969
{
4978
- imp_sth -> fetch_done = TRUE;
4979
4970
if (DBIc_TRACE_LEVEL (imp_xxh ) >= 2 )
4980
4971
PerlIO_printf (DBIc_LOGPIO (imp_xxh ), "\t\tmariadb_st_fetch no data\n" );
4981
4972
}
@@ -4986,12 +4977,17 @@ mariadb_st_fetch(SV *sth, imp_sth_t* imp_sth)
4986
4977
mysql_stmt_sqlstate (imp_sth -> stmt ));
4987
4978
}
4988
4979
4980
+ DBIc_ACTIVE_off (imp_sth );
4981
+
4989
4982
return Nullav ;
4990
4983
}
4991
4984
4992
4985
process :
4993
4986
imp_sth -> currow ++ ;
4994
4987
4988
+ if (imp_sth -> currow >= imp_sth -> row_num )
4989
+ DBIc_ACTIVE_off (imp_sth );
4990
+
4995
4991
av = DBIc_DBISTATE (imp_sth )-> get_fbav (imp_sth );
4996
4992
num_fields = mysql_stmt_field_count (imp_sth -> stmt );
4997
4993
if (DBIc_TRACE_LEVEL (imp_xxh ) >= 2 )
@@ -5245,8 +5241,8 @@ mariadb_st_fetch(SV *sth, imp_sth_t* imp_sth)
5245
5241
SVfARG (sv_2mortal (my_ulonglong2sv (mysql_num_rows (imp_sth -> result )))));
5246
5242
PerlIO_printf (DBIc_LOGPIO (imp_xxh ), "\tmysql_affected_rows=%" SVf "\n" ,
5247
5243
SVfARG (sv_2mortal (my_ulonglong2sv (mysql_affected_rows (imp_dbh -> pmysql )))));
5248
- PerlIO_printf (DBIc_LOGPIO (imp_xxh ), "\tmariadb_st_fetch for %p, currow= %d \n" ,
5249
- sth ,imp_sth -> currow );
5244
+ PerlIO_printf (DBIc_LOGPIO (imp_xxh ), "\tmariadb_st_fetch for %p, currow=%" SVf " \n" ,
5245
+ sth , SVfARG ( sv_2mortal ( my_ulonglong2sv ( imp_sth -> currow ))) );
5250
5246
}
5251
5247
5252
5248
if (!(cols = mysql_fetch_row (imp_sth -> result )))
@@ -5259,9 +5255,14 @@ mariadb_st_fetch(SV *sth, imp_sth_t* imp_sth)
5259
5255
mariadb_dr_do_error (sth , mysql_errno (imp_dbh -> pmysql ),
5260
5256
mysql_error (imp_dbh -> pmysql ),
5261
5257
mysql_sqlstate (imp_dbh -> pmysql ));
5258
+ if (!mysql_more_results (imp_dbh -> pmysql ))
5259
+ DBIc_ACTIVE_off (imp_sth );
5262
5260
return Nullav ;
5263
5261
}
5264
5262
5263
+ if (imp_sth -> currow >= imp_sth -> row_num && !mysql_more_results (imp_dbh -> pmysql ))
5264
+ DBIc_ACTIVE_off (imp_sth );
5265
+
5265
5266
num_fields = mysql_num_fields (imp_sth -> result );
5266
5267
fields = mysql_fetch_fields (imp_sth -> result );
5267
5268
lengths = mysql_fetch_lengths (imp_sth -> result );
@@ -5393,32 +5394,22 @@ int mariadb_st_finish(SV* sth, imp_sth_t* imp_sth) {
5393
5394
}
5394
5395
5395
5396
if (imp_sth -> use_server_side_prepare && imp_sth -> stmt )
5396
- {
5397
- /*
5398
- We have to fetch all data from stmt
5399
- There is may be useful for 2 cases:
5400
- 1. st_finish when we have undef statement
5401
- 2. call st_execute again when we have some unfetched data in stmt
5402
- */
5403
- if (DBIc_ACTIVE (imp_sth ) && mariadb_st_describe (sth , imp_sth ) && !imp_sth -> fetch_done )
5404
- mysql_stmt_free_result (imp_sth -> stmt );
5405
- }
5397
+ mysql_stmt_free_result (imp_sth -> stmt );
5398
+
5399
+ /*
5400
+ Clean-up previous result set(s) for sth to prevent
5401
+ 'Commands out of sync' error
5402
+ */
5403
+ if (!mariadb_st_free_result_sets (sth , imp_sth , FALSE))
5404
+ return 0 ;
5406
5405
5407
5406
/*
5408
5407
Cancel further fetches from this cursor.
5409
5408
We don't close the cursor till DESTROY.
5410
5409
The application may re execute it.
5411
5410
*/
5412
- if (imp_sth && DBIc_ACTIVE (imp_sth ))
5413
- {
5414
- /*
5415
- Clean-up previous result set(s) for sth to prevent
5416
- 'Commands out of sync' error
5417
- */
5418
- if (!mariadb_st_free_result_sets (sth , imp_sth ))
5419
- return 0 ;
5420
- }
5421
5411
DBIc_ACTIVE_off (imp_sth );
5412
+
5422
5413
if (DBIc_TRACE_LEVEL (imp_xxh ) >= 2 )
5423
5414
{
5424
5415
PerlIO_printf (DBIc_LOGPIO (imp_xxh ), "\n<-- mariadb_st_finish\n" );
@@ -5450,6 +5441,16 @@ void mariadb_st_destroy(SV *sth, imp_sth_t *imp_sth) {
5450
5441
int num_params ;
5451
5442
int num_fields ;
5452
5443
5444
+ if (!PL_dirty )
5445
+ {
5446
+ /* During global destruction, DBI objects are destroyed in random order
5447
+ * and therefore imp_dbh may be already freed. So do not access it. */
5448
+ mariadb_st_finish (sth , imp_sth );
5449
+ mariadb_st_free_result_sets (sth , imp_sth , TRUE);
5450
+ }
5451
+
5452
+ DBIc_ACTIVE_off (imp_sth );
5453
+
5453
5454
if (imp_sth -> statement )
5454
5455
Safefree (imp_sth -> statement );
5455
5456
@@ -5486,8 +5487,6 @@ void mariadb_st_destroy(SV *sth, imp_sth_t *imp_sth) {
5486
5487
imp_sth -> stmt = NULL ;
5487
5488
}
5488
5489
5489
- /* mariadb_st_finish has already been called by .xs code if needed. */
5490
-
5491
5490
/* Free values allocated by mariadb_st_bind_ph */
5492
5491
if (imp_sth -> params )
5493
5492
{
@@ -6520,6 +6519,12 @@ my_ulonglong mariadb_db_async_result(SV* h, MYSQL_RES** resp)
6520
6519
}
6521
6520
dbh -> async_query_in_flight = NULL ;
6522
6521
6522
+ if (htype == DBIt_ST )
6523
+ {
6524
+ D_imp_sth (h );
6525
+ DBIc_ACTIVE_off (imp_sth );
6526
+ }
6527
+
6523
6528
svsock = dbh -> pmysql ;
6524
6529
if (!svsock )
6525
6530
{
@@ -6561,13 +6566,13 @@ my_ulonglong mariadb_db_async_result(SV* h, MYSQL_RES** resp)
6561
6566
6562
6567
if (! * resp ) {
6563
6568
imp_sth -> insertid = dbh -> insertid ;
6564
- if (! mysql_more_results (svsock ))
6565
- DBIc_ACTIVE_off (imp_sth );
6569
+ if ( mysql_more_results (svsock ))
6570
+ DBIc_ACTIVE_on (imp_sth );
6566
6571
} else {
6567
6572
num_fields = mysql_num_fields (imp_sth -> result );
6568
6573
DBIc_NUM_FIELDS (imp_sth ) = (num_fields <= INT_MAX ) ? num_fields : INT_MAX ;
6569
- imp_sth -> done_desc = FALSE;
6570
- imp_sth -> fetch_done = FALSE ;
6574
+ if ( imp_sth -> row_num )
6575
+ DBIc_ACTIVE_on ( imp_sth ) ;
6571
6576
}
6572
6577
imp_sth -> warning_count = mysql_warning_count (imp_dbh -> pmysql );
6573
6578
}
0 commit comments