diff -Nru libdbd-mariadb-perl-1.11/Changes libdbd-mariadb-perl-1.21/Changes --- libdbd-mariadb-perl-1.11/Changes 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/Changes 2019-02-27 11:04:38.000000000 +0000 @@ -1,3 +1,22 @@ +1.21 2019-02-27 + - Fix skipping test t/14destruct.t + - Revert "MySQL bug #93276 is fixed in 8.0.15" + (https://github.com/gooddata/DBD-MariaDB/issues/137) + +1.20 2019-02-22 + - Fix compilation on Windows + - Fix tests for MariaDB 10.2.20+, 10.3.12+ and 10.4.1+ + - Fix processing of unfetched multi result sets + - Cover a protocol design error for multi result statements + - Fix $dbh->last_insert_id for async calls and multi result statements + - Add more robust solution to prevent deinitializing OpenSSL functions + (https://github.com/gooddata/DBD-MariaDB/issues/119) + - Set $sth->{Active} to off after fetching all data + (https://github.com/jhthorsen/mojo-mysql/pull/47#issuecomment-448095164) + - Fix $sth->rows for async, multi results and when error occurred + - Fix disconnect_all() method to work also during global destruction phase + - Address MySQL bug #93276 which is fixed in 8.0.15 + 1.11 2019-01-02 - Fix breakage of Net::SSLeay / OpenSSL library after DBI disconnect (https://github.com/gooddata/DBD-MariaDB/issues/119) diff -Nru libdbd-mariadb-perl-1.11/dbdimp.c libdbd-mariadb-perl-1.21/dbdimp.c --- libdbd-mariadb-perl-1.11/dbdimp.c 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/dbdimp.c 2019-02-27 11:04:38.000000000 +0000 @@ -2291,6 +2291,8 @@ imp_dbh->async_query_in_flight = NULL; + mariadb_list_add(imp_drh->active_imp_dbhs, imp_dbh->list_entry, imp_dbh); + return TRUE; } @@ -2336,8 +2338,7 @@ char* user; char* password; char* mysql_socket; - I32 i; - bool found_taken_pmysql; + struct mariadb_list_entry *entry; D_imp_xxh(dbh); D_imp_drh_from_dbh; @@ -2347,34 +2348,29 @@ { if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) PerlIO_printf(DBIc_LOGPIO(imp_xxh), "mariadb_db_my_login skip connect\n"); + /* tell our parent we've adopted an active child */ ++DBIc_ACTIVE_KIDS(DBIc_PARENT_COM(imp_dbh)); - found_taken_pmysql = FALSE; - if (imp_drh->taken_pmysqls) + + for (entry = imp_drh->taken_pmysqls; entry; entry = entry->next) { - for (i = AvFILL(imp_drh->taken_pmysqls); i >= 0; --i) + if ((MYSQL *)entry->data == imp_dbh->pmysql) { - svp = av_fetch(imp_drh->taken_pmysqls, i, FALSE); - if (!svp || !*svp) - continue; - SvGETMAGIC(*svp); - if (!SvIOK(*svp)) - continue; - if (imp_dbh->pmysql == INT2PTR(MYSQL *, SvIVX(*svp))) - { - found_taken_pmysql = TRUE; - av_delete(imp_drh->taken_pmysqls, i, G_DISCARD); - break; - } + /* Remove MYSQL* entry from taken list */ + mariadb_list_remove(imp_drh->taken_pmysqls, entry); + + /* Add imp_dbh entry into active_imp_dbhs list */ + mariadb_list_add(imp_drh->active_imp_dbhs, imp_dbh->list_entry, imp_dbh); + + return TRUE; } } - if (!found_taken_pmysql) - { - imp_dbh->pmysql = NULL; - mariadb_dr_do_error(dbh, CR_CONNECTION_ERROR, "Connection error: dbi_imp_data is not valid", "HY000"); - return FALSE; - } - return TRUE; + + /* This imp_dbh data belongs to different connection, so destructor should not touch it */ + imp_dbh->list_entry = NULL; + imp_dbh->pmysql = NULL; + mariadb_dr_do_error(dbh, CR_CONNECTION_ERROR, "Connection error: dbi_imp_data is not valid", "HY000"); + return FALSE; } if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) PerlIO_printf(DBIc_LOGPIO(imp_xxh), @@ -2445,12 +2441,15 @@ dTHX; D_imp_dbh(dbh); D_imp_drh_from_dbh; + struct mariadb_list_entry *entry; PERL_UNUSED_ARG(imp_xxh); PERL_UNUSED_ARG(foo); - if (!imp_drh->taken_pmysqls) - imp_drh->taken_pmysqls = newAV(); - av_push(imp_drh->taken_pmysqls, newSViv(PTR2IV(imp_dbh->pmysql))); + /* Add MYSQL* into taken list */ + mariadb_list_add(imp_drh->taken_pmysqls, entry, imp_dbh->pmysql); + + /* MYSQL* was taken from imp_dbh so remove it also from active_imp_dbhs list */ + mariadb_list_remove(imp_drh->active_imp_dbhs, imp_dbh->list_entry); return &PL_sv_no; } @@ -2551,9 +2550,9 @@ bool disable_fallback_for_server_prepare = FALSE; MYSQL_STMT *stmt = NULL; MYSQL_BIND *bind = NULL; - MYSQL_RES *res; STRLEN blen; unsigned long int num_params; + unsigned int error; ASYNC_CHECK_RETURN(dbh, -2); @@ -2642,11 +2641,39 @@ imp_dbh->async_query_in_flight = imp_dbh; } - while (mysql_next_result(imp_dbh->pmysql) == 0) + while ((next_result_rc = mysql_next_result(imp_dbh->pmysql)) == 0) + { + result = mysql_store_result(imp_dbh->pmysql); + if (!result) + { + if (mysql_errno(imp_dbh->pmysql)) + { + mariadb_dr_do_error(dbh, mysql_errno(imp_dbh->pmysql), mysql_error(imp_dbh->pmysql), mysql_sqlstate(imp_dbh->pmysql)); + return -2; + } + imp_dbh->insertid = mysql_insert_id(imp_dbh->pmysql); + } + if (result) + { + mysql_free_result(result); + result = NULL; + } + } + + if (next_result_rc > 0) { - res = mysql_use_result(imp_dbh->pmysql); - if (res) - mysql_free_result(res); +#if MYSQL_VERSION_ID < 50025 + /* Cover a protocol design error: error packet does not contain the server status. + * Luckily, an error always aborts execution of a statement, so it is safe to turn off the flag. */ + imp_dbh->pmysql->server_status &= ~SERVER_MORE_RESULTS_EXISTS; +#endif + /* This is error for previous unfetched result ret. So do not report server errors to caller which is expecting new result set. */ + error = mysql_errno(imp_dbh->pmysql); + if (error == CR_COMMANDS_OUT_OF_SYNC || error == CR_OUT_OF_MEMORY || error == CR_SERVER_GONE_ERROR || error == CR_SERVER_LOST || error == CR_UNKNOWN_ERROR) + { + mariadb_dr_do_error(dbh, mysql_errno(imp_dbh->pmysql), mysql_error(imp_dbh->pmysql), mysql_sqlstate(imp_dbh->pmysql)); + return -2; + } } if (use_server_side_prepare) @@ -2804,7 +2831,12 @@ /* 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); + result = mysql_store_result(imp_dbh->pmysql); + if (mysql_errno(imp_dbh->pmysql)) + { + next_result_rc = 1; + break; + } if (!result) /* Next statement without result set, new insert id */ imp_dbh->insertid = mysql_insert_id(imp_dbh->pmysql); if (result) @@ -2814,6 +2846,12 @@ if (next_result_rc > 0) { +#if MYSQL_VERSION_ID < 50025 + /* Cover a protocol design error: error packet does not contain the server status. + * Luckily, an error always aborts execution of a statement, so it is safe to turn off the flag. */ + imp_dbh->pmysql->server_status &= ~SERVER_MORE_RESULTS_EXISTS; +#endif + if (DBIc_DBISTATE(imp_dbh)->debug >= 2) PerlIO_printf(DBIc_LOGPIO(imp_dbh), "\t<- do() ERROR: %s\n", mysql_error(imp_dbh->pmysql)); @@ -2912,7 +2950,7 @@ * These bugs were fixed in MariaDB Connector/C 3.0.5, see: https://jira.mariadb.org/browse/CONC-336 * But remains in MariaDB Embedded server, see: https://jira.mariadb.org/browse/MDEV-16578 */ -#ifndef HAVE_BROKEN_INIT +#if !defined(HAVE_BROKEN_INIT) && (defined(HAVE_DEINITIALIZE_SSL) || !defined(HAVE_PROBLEM_WITH_OPENSSL)) if (imp_drh->non_embedded_started) { mysql_server_end(); @@ -2923,6 +2961,9 @@ { mysql_server_end(); imp_drh->embedded_started = FALSE; +#if !defined(HAVE_DEINITIALIZE_SSL) && defined(HAVE_PROBLEM_WITH_OPENSSL) + warn("DBD::MariaDB disconnect: Client library deinitialized OpenSSL library functions and module Net::SSLeay is now broken"); +#endif } if (imp_drh->embedded_args) { @@ -2937,23 +2978,8 @@ } } -/* - *************************************************************************** - * - * Name: mariadb_db_disconnect - * - * Purpose: Disconnect a database handle from its database - * - * Input: dbh - database handle being disconnected - * imp_dbh - drivers private database handle data - * - * Returns: 1 for success (always) - * - **************************************************************************/ - -int mariadb_db_disconnect(SV* dbh, imp_dbh_t* imp_dbh) +static void mariadb_db_close_mysql(pTHX_ imp_drh_t *imp_drh, imp_dbh_t *imp_dbh) { - dTHX; AV *av; I32 i; MAGIC *mg; @@ -2961,15 +2987,14 @@ SV *sv; SV *sth; imp_sth_t *imp_sth; - D_imp_xxh(dbh); - D_imp_drh_from_dbh; - /* We assume that disconnect will always work */ - /* since most errors imply already disconnected. */ + if (DBIc_TRACE_LEVEL(imp_dbh) >= 2) + PerlIO_printf(DBIc_LOGPIO(imp_dbh), "\tmariadb_db_close_mysql: imp_dbh=%p pmysql=%p\n", imp_dbh, imp_dbh->pmysql); + DBIc_ACTIVE_off(imp_dbh); - if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) - PerlIO_printf(DBIc_LOGPIO(imp_xxh), "imp_dbh->pmysql: %p\n", - imp_dbh->pmysql); + + if (imp_dbh->list_entry) + mariadb_list_remove(imp_drh->active_imp_dbhs, imp_dbh->list_entry); if (imp_dbh->pmysql) { @@ -3003,14 +3028,39 @@ * CVE 2017-3302 do not do it. So do it manually to prevent crash. */ if (imp_sth->stmt && imp_sth->stmt->mysql) { - if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) - PerlIO_printf(DBIc_LOGPIO(imp_xxh), "Applying CVE 2017-3302 workaround for sth=0x%p\n", imp_sth); + if (DBIc_TRACE_LEVEL(imp_dbh) >= 2) + PerlIO_printf(DBIc_LOGPIO(imp_dbh), "Applying CVE 2017-3302 workaround for sth=%p\n", imp_sth); imp_sth->stmt->mysql = NULL; } } } } } +} + +/* + *************************************************************************** + * + * Name: mariadb_db_disconnect + * + * Purpose: Disconnect a database handle from its database + * + * Input: dbh - database handle being disconnected + * imp_dbh - drivers private database handle data + * + * Returns: 1 for success (always) + * + **************************************************************************/ + +int mariadb_db_disconnect(SV* dbh, imp_dbh_t* imp_dbh) +{ + dTHX; + D_imp_drh_from_dbh; + PERL_UNUSED_ARG(dbh); + + /* We assume that disconnect will always work */ + /* since most errors imply already disconnected. */ + mariadb_db_close_mysql(aTHX_ imp_drh, imp_dbh); /* We don't free imp_dbh since a reference still exists */ /* The DESTROY method is the only one to 'free' memory. */ @@ -3033,57 +3083,18 @@ int mariadb_dr_discon_all (SV *drh, imp_drh_t *imp_drh) { dTHX; - dSP; int ret; - SV **svp; - AV *av; - I32 i; + struct mariadb_list_entry *entry; PERL_UNUSED_ARG(drh); - if (imp_drh->taken_pmysqls) + while ((entry = imp_drh->taken_pmysqls)) { - for (i = AvFILL(imp_drh->taken_pmysqls); i >= 0; --i) - { - svp = av_fetch(imp_drh->taken_pmysqls, i, FALSE); - if (!svp || !*svp) - continue; - SvGETMAGIC(*svp); - if (!SvIOK(*svp)) - continue; - mariadb_dr_close_mysql(aTHX_ imp_drh, INT2PTR(MYSQL *, SvIVX(*svp))); - } - av_undef(imp_drh->taken_pmysqls); - imp_drh->taken_pmysqls = NULL; + mariadb_dr_close_mysql(aTHX_ imp_drh, (MYSQL *)entry->data); + mariadb_list_remove(imp_drh->taken_pmysqls, entry); } - svp = hv_fetchs((HV*)DBIc_MY_H(imp_drh), "ChildHandles", FALSE); - if (svp && *svp) - { - SvGETMAGIC(*svp); - if (SvROK(*svp) && SvTYPE(SvRV(*svp)) == SVt_PVAV) - { - av = (AV *)SvRV(*svp); - for (i = AvFILL(av); i >= 0; --i) - { - svp = av_fetch(av, i, FALSE); - if (!svp || !*svp || !sv_isobject(*svp)) - continue; - - ENTER; - SAVETMPS; - - PUSHMARK(SP); - EXTEND(SP, 1); - PUSHs(sv_2mortal(newSVsv(*svp))); - PUTBACK; - - call_method("disconnect", G_VOID|G_DISCARD|G_EVAL|G_KEEPERR); - - FREETMPS; - LEAVE; - } - } - } + while (imp_drh->active_imp_dbhs) + mariadb_db_close_mysql(aTHX_ imp_drh, (imp_dbh_t *)imp_drh->active_imp_dbhs->data); ret = 1; @@ -3105,6 +3116,7 @@ #ifndef HAVE_EMBEDDED if (imp_drh->non_embedded_started) { + #if defined(HAVE_DEINITIALIZE_SSL) || !defined(HAVE_PROBLEM_WITH_OPENSSL) #ifndef HAVE_BROKEN_INIT warn("DBD::MariaDB disconnect_all: Client library was not properly deinitialized (possible bug in driver)"); ret = 0; @@ -3113,6 +3125,7 @@ imp_drh->non_embedded_started = FALSE; imp_drh->non_embedded_finished = TRUE; #endif + #endif } #endif @@ -3668,7 +3681,7 @@ return av; } -static int mariadb_st_free_result_sets (SV * sth, imp_sth_t * imp_sth); +static bool mariadb_st_free_result_sets(SV *sth, imp_sth_t *imp_sth, bool free_last); /* ************************************************************************** @@ -3730,10 +3743,10 @@ imp_sth->use_server_side_prepare = imp_dbh->use_server_side_prepare; imp_sth->disable_fallback_for_server_prepare = imp_dbh->disable_fallback_for_server_prepare; - imp_sth->fetch_done = FALSE; imp_sth->done_desc = FALSE; imp_sth->result = NULL; imp_sth->currow = 0; + imp_sth->row_num = (my_ulonglong)-1; if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) PerlIO_printf(DBIc_LOGPIO(imp_xxh), @@ -3800,7 +3813,8 @@ Clean-up previous result set(s) for sth to prevent 'Commands out of sync' error */ - mariadb_st_free_result_sets(sth, imp_sth); + if (!mariadb_st_free_result_sets(sth, imp_sth, TRUE)) + return 0; if (imp_sth->use_server_side_prepare) { @@ -3943,19 +3957,22 @@ * * Inputs: sth - Statement handle * imp_sth - driver's private statement handle + * free_last - free also the last result set * - * Returns: 1 ok - * 0 error + * Returns: TRUE ok + * FALSE error; mariadb_dr_do_error will be called *************************************************************************/ -static int mariadb_st_free_result_sets (SV * sth, imp_sth_t * imp_sth) +static bool mariadb_st_free_result_sets(SV *sth, imp_sth_t *imp_sth, bool free_last) { dTHX; D_imp_dbh_from_sth; D_imp_xxh(sth); int next_result_rc= -1; + unsigned int error; + /* No connection, nothing to clean, no error */ if (!imp_dbh->pmysql) - return 0; + return TRUE; if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\t>- mariadb_st_free_result_sets\n"); @@ -3967,10 +3984,10 @@ if (next_result_rc == 0) { - if (!(imp_sth->result = mysql_use_result(imp_dbh->pmysql))) + if (!(imp_sth->result = mysql_store_result(imp_dbh->pmysql))) { /* Check for possible error */ - if (mysql_field_count(imp_dbh->pmysql)) + if (mysql_errno(imp_dbh->pmysql)) { if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\t<- mariadb_st_free_result_sets ERROR: %s\n", @@ -3978,11 +3995,12 @@ mariadb_dr_do_error(sth, mysql_errno(imp_dbh->pmysql), mysql_error(imp_dbh->pmysql), mysql_sqlstate(imp_dbh->pmysql)); - return 0; + return FALSE; } + imp_dbh->insertid = imp_sth->insertid = mysql_insert_id(imp_dbh->pmysql); } } - if (imp_sth->result) + if (imp_sth->result && (mysql_more_results(imp_dbh->pmysql) || free_last)) { mysql_free_result(imp_sth->result); imp_sth->result=NULL; @@ -3991,18 +4009,29 @@ if (next_result_rc > 0) { +#if MYSQL_VERSION_ID < 50025 + /* Cover a protocol design error: error packet does not contain the server status. + * Luckily, an error always aborts execution of a statement, so it is safe to turn off the flag. */ + imp_dbh->pmysql->server_status &= ~SERVER_MORE_RESULTS_EXISTS; +#endif + if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\t<- mariadb_st_free_result_sets: Error while processing multi-result set: %s\n", mysql_error(imp_dbh->pmysql)); - mariadb_dr_do_error(sth, mysql_errno(imp_dbh->pmysql), mysql_error(imp_dbh->pmysql), - mysql_sqlstate(imp_dbh->pmysql)); + /* This is error for previous unfetched result ret. So do not report server errors to caller which is expecting new result set. */ + error = mysql_errno(imp_dbh->pmysql); + if (error == CR_COMMANDS_OUT_OF_SYNC || error == CR_OUT_OF_MEMORY || error == CR_SERVER_GONE_ERROR || error == CR_SERVER_LOST || error == CR_UNKNOWN_ERROR) + { + mariadb_dr_do_error(sth, mysql_errno(imp_dbh->pmysql), mysql_error(imp_dbh->pmysql), mysql_sqlstate(imp_dbh->pmysql)); + return FALSE; + } } if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\t<- mariadb_st_free_result_sets\n"); - return 1; + return TRUE; } @@ -4029,6 +4058,21 @@ if (!SvROK(sth) || SvTYPE(SvRV(sth)) != SVt_PVHV) croak("Expected hash array"); + if (imp_sth->use_server_side_prepare) + { + mariadb_dr_do_error(sth, CR_NOT_IMPLEMENTED, "Processing of multiple result set is not possible with server side prepare", "HY000"); + return FALSE; + } + + if (imp_dbh->async_query_in_flight && imp_dbh->async_query_in_flight != imp_sth) + { + mariadb_dr_do_error(sth, CR_UNKNOWN_ERROR, "Gathering async_query_in_flight results for the wrong handle", "HY000"); + return FALSE; + } + imp_dbh->async_query_in_flight = NULL; + + DBIc_ACTIVE_off(imp_sth); + if (!imp_dbh->pmysql && !mariadb_db_reconnect(sth, NULL)) { mariadb_dr_do_error(sth, CR_SERVER_GONE_ERROR, "MySQL server has gone away", "HY000"); @@ -4044,12 +4088,6 @@ return FALSE; } - if (imp_sth->use_server_side_prepare) - { - mariadb_dr_do_error(sth, CR_NOT_IMPLEMENTED, "Processing of multiple result set is not possible with server side prepare", "HY000"); - return FALSE; - } - /* * Free cached array attributes */ @@ -4068,8 +4106,33 @@ imp_sth->result= NULL; } - if (DBIc_ACTIVE(imp_sth)) - DBIc_ACTIVE_off(imp_sth); + imp_sth->done_desc = FALSE; + imp_sth->currow = 0; + imp_sth->row_num = (my_ulonglong)-1; + + /* clear NUM_OF_FIELDS attribute */ + DBIc_DBISTATE(imp_sth)->set_attr_k(sth, sv_2mortal(newSVpvs("NUM_OF_FIELDS")), 0, sv_2mortal(newSViv(0))); + + /* delete cached handle attributes */ + /* XXX should be driven by a list to ease maintenance */ + (void)hv_deletes((HV*)SvRV(sth), "NAME", G_DISCARD); + (void)hv_deletes((HV*)SvRV(sth), "NULLABLE", G_DISCARD); + (void)hv_deletes((HV*)SvRV(sth), "NUM_OF_FIELDS", G_DISCARD); + (void)hv_deletes((HV*)SvRV(sth), "PRECISION", G_DISCARD); + (void)hv_deletes((HV*)SvRV(sth), "SCALE", G_DISCARD); + (void)hv_deletes((HV*)SvRV(sth), "TYPE", G_DISCARD); + (void)hv_deletes((HV*)SvRV(sth), "mariadb_insertid", G_DISCARD); + (void)hv_deletes((HV*)SvRV(sth), "mariadb_is_auto_increment", G_DISCARD); + (void)hv_deletes((HV*)SvRV(sth), "mariadb_is_blob", G_DISCARD); + (void)hv_deletes((HV*)SvRV(sth), "mariadb_is_key", G_DISCARD); + (void)hv_deletes((HV*)SvRV(sth), "mariadb_is_num", G_DISCARD); + (void)hv_deletes((HV*)SvRV(sth), "mariadb_is_pri_key", G_DISCARD); + (void)hv_deletes((HV*)SvRV(sth), "mariadb_length", G_DISCARD); + (void)hv_deletes((HV*)SvRV(sth), "mariadb_max_length", G_DISCARD); + (void)hv_deletes((HV*)SvRV(sth), "mariadb_table", G_DISCARD); + (void)hv_deletes((HV*)SvRV(sth), "mariadb_type", G_DISCARD); + (void)hv_deletes((HV*)SvRV(sth), "mariadb_type_name", G_DISCARD); + (void)hv_deletes((HV*)SvRV(sth), "mariadb_warning_count", G_DISCARD); next_result_return_code= mysql_next_result(imp_dbh->pmysql); @@ -4083,6 +4146,11 @@ */ if (next_result_return_code > 0) { +#if MYSQL_VERSION_ID < 50025 + /* Cover a protocol design error: error packet does not contain the server status. + * Luckily, an error always aborts execution of a statement, so it is safe to turn off the flag. */ + imp_dbh->pmysql->server_status &= ~SERVER_MORE_RESULTS_EXISTS; +#endif mariadb_dr_do_error(sth, mysql_errno(imp_dbh->pmysql), mysql_error(imp_dbh->pmysql), mysql_sqlstate(imp_dbh->pmysql)); @@ -4105,52 +4173,32 @@ return FALSE; } - imp_sth->row_num= mysql_affected_rows(imp_dbh->pmysql); - if (imp_sth->result == NULL) { + imp_sth->row_num = mysql_affected_rows(imp_dbh->pmysql); + imp_dbh->insertid = imp_sth->insertid = mysql_insert_id(imp_dbh->pmysql); - /* No "real" rowset*/ - DBIS->set_attr_k(sth, sv_2mortal(newSVpvs("NUM_OF_FIELDS")), 0, - sv_2mortal(newSViv(0))); - return TRUE; + + if (mysql_more_results(imp_dbh->pmysql)) + DBIc_ACTIVE_on(imp_sth); } else { /* We have a new rowset */ - imp_sth->currow=0; - - - /* delete cached handle attributes */ - /* XXX should be driven by a list to ease maintenance */ - (void)hv_deletes((HV*)SvRV(sth), "NAME", G_DISCARD); - (void)hv_deletes((HV*)SvRV(sth), "NULLABLE", G_DISCARD); - (void)hv_deletes((HV*)SvRV(sth), "NUM_OF_FIELDS", G_DISCARD); - (void)hv_deletes((HV*)SvRV(sth), "PRECISION", G_DISCARD); - (void)hv_deletes((HV*)SvRV(sth), "SCALE", G_DISCARD); - (void)hv_deletes((HV*)SvRV(sth), "TYPE", G_DISCARD); - (void)hv_deletes((HV*)SvRV(sth), "mariadb_insertid", G_DISCARD); - (void)hv_deletes((HV*)SvRV(sth), "mariadb_is_auto_increment", G_DISCARD); - (void)hv_deletes((HV*)SvRV(sth), "mariadb_is_blob", G_DISCARD); - (void)hv_deletes((HV*)SvRV(sth), "mariadb_is_key", G_DISCARD); - (void)hv_deletes((HV*)SvRV(sth), "mariadb_is_num", G_DISCARD); - (void)hv_deletes((HV*)SvRV(sth), "mariadb_is_pri_key", G_DISCARD); - (void)hv_deletes((HV*)SvRV(sth), "mariadb_length", G_DISCARD); - (void)hv_deletes((HV*)SvRV(sth), "mariadb_max_length", G_DISCARD); - (void)hv_deletes((HV*)SvRV(sth), "mariadb_table", G_DISCARD); - (void)hv_deletes((HV*)SvRV(sth), "mariadb_type", G_DISCARD); - (void)hv_deletes((HV*)SvRV(sth), "mariadb_type_name", G_DISCARD); - (void)hv_deletes((HV*)SvRV(sth), "mariadb_warning_count", G_DISCARD); + imp_sth->row_num = mysql_num_rows(imp_sth->result); /* Adjust NUM_OF_FIELDS - which also adjusts the row buffer size */ DBIc_DBISTATE(imp_sth)->set_attr_k(sth, sv_2mortal(newSVpvs("NUM_OF_FIELDS")), 0, sv_2mortal(newSVuv(mysql_num_fields(imp_sth->result))) ); - DBIc_ACTIVE_on(imp_sth); - - imp_sth->done_desc = FALSE; + if (imp_sth->row_num) + DBIc_ACTIVE_on(imp_sth); } + + if (imp_sth->is_async && mysql_more_results(imp_dbh->pmysql)) + imp_dbh->async_query_in_flight = imp_sth; + imp_dbh->pmysql->net.last_errno= 0; return TRUE; } @@ -4270,6 +4318,11 @@ (!mariadb_db_reconnect(h, NULL) || (mysql_real_query(*svsock, sbuf, slen)))) { +#if MYSQL_VERSION_ID < 50025 + /* Cover a protocol design error: error packet does not contain the server status. + * Luckily, an error always aborts execution of a statement, so it is safe to turn off the flag. */ + (*svsock)->server_status &= ~SERVER_MORE_RESULTS_EXISTS; +#endif rows = -1; } else { /** Store the result from the Query */ @@ -4538,7 +4591,10 @@ Clean-up previous result set(s) for sth to prevent 'Commands out of sync' error */ - mariadb_st_free_result_sets (sth, imp_sth); + if (!mariadb_st_free_result_sets(sth, imp_sth, TRUE)) + return -2; + + imp_sth->currow = 0; if (use_server_side_prepare) { @@ -4612,10 +4668,10 @@ /** Store the result in the current statement handle */ num_fields = mysql_num_fields(imp_sth->result); DBIc_NUM_FIELDS(imp_sth) = (num_fields <= INT_MAX) ? num_fields : INT_MAX; - DBIc_ACTIVE_on(imp_sth); + if (imp_sth->row_num) + DBIc_ACTIVE_on(imp_sth); if (!use_server_side_prepare) imp_sth->done_desc = FALSE; - imp_sth->fetch_done = FALSE; } } @@ -4658,6 +4714,9 @@ if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\t--> mariadb_st_describe\n"); + if (imp_sth->done_desc) + return 1; + if (imp_sth->use_server_side_prepare) { int i; @@ -4670,9 +4729,6 @@ PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\t\tmariadb_st_describe() num_fields %d\n", num_fields); - if (imp_sth->done_desc) - return 1; - if (num_fields <= 0 || !imp_sth->result) { /* no metadata */ @@ -4829,32 +4885,27 @@ PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\t-> mariadb_st_fetch\n"); if (!imp_dbh->pmysql) + { + mariadb_dr_do_error(sth, CR_SERVER_GONE_ERROR, "MySQL server has gone away", "HY000"); return Nullav; - - if(imp_dbh->async_query_in_flight) { - if (mariadb_db_async_result(sth, &imp_sth->result) == (my_ulonglong)-1) - return Nullav; } - if (imp_sth->use_server_side_prepare) + if (imp_dbh->async_query_in_flight) { - if (!DBIc_ACTIVE(imp_sth) ) - { - mariadb_dr_do_error(sth, CR_UNKNOWN_ERROR, "no statement executing", "HY000"); + if (!DBIc_ACTIVE(imp_sth)) return Nullav; - } - - if (imp_sth->fetch_done) - { - mariadb_dr_do_error(sth, CR_UNKNOWN_ERROR, "fetch() but fetch already done", "HY000"); + if (mariadb_db_async_result(sth, &imp_sth->result) == (my_ulonglong)-1) return Nullav; - } - - if (!imp_sth->done_desc) + } + else + { + if (!imp_sth->result) { - if (!mariadb_st_describe(sth, imp_sth)) - return Nullav; + mariadb_dr_do_error(sth, CR_UNKNOWN_ERROR, "fetch() without execute()", "HY000"); + return Nullav; } + if (!DBIc_ACTIVE(imp_sth)) + return Nullav; } ChopBlanks = DBIc_is(imp_sth, DBIcf_ChopBlanks) ? TRUE : FALSE; @@ -4864,19 +4915,16 @@ "\t\tmariadb_st_fetch for %p, chopblanks %d\n", sth, ChopBlanks ? 1 : 0); - if (!imp_sth->result) - { - mariadb_dr_do_error(sth, CR_UNKNOWN_ERROR, "fetch() without execute()", "HY000"); - return Nullav; - } - /* fix from 2.9008 */ imp_dbh->pmysql->net.last_errno = 0; if (imp_sth->use_server_side_prepare) { + if (!mariadb_st_describe(sth, imp_sth)) + return Nullav; + if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) - PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\t\tmariadb_st_fetch calling mysql_fetch\n"); + PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\t\tmariadb_st_fetch calling mysql_stmt_fetch\n"); if ((rc= mysql_stmt_fetch(imp_sth->stmt))) { @@ -4890,9 +4938,6 @@ if (rc == MYSQL_NO_DATA) { - /* Update row_num to affected_rows value */ - imp_sth->row_num= mysql_stmt_affected_rows(imp_sth->stmt); - imp_sth->fetch_done = TRUE; if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\t\tmariadb_st_fetch no data\n"); } @@ -4903,12 +4948,17 @@ mysql_stmt_sqlstate(imp_sth->stmt)); } + DBIc_ACTIVE_off(imp_sth); + return Nullav; } process: imp_sth->currow++; + if (imp_sth->currow >= imp_sth->row_num) + DBIc_ACTIVE_off(imp_sth); + av= DBIc_DBISTATE(imp_sth)->get_fbav(imp_sth); num_fields=mysql_stmt_field_count(imp_sth->stmt); if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) @@ -5162,8 +5212,8 @@ SVfARG(sv_2mortal(my_ulonglong2sv(mysql_num_rows(imp_sth->result))))); PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\tmysql_affected_rows=%" SVf "\n", SVfARG(sv_2mortal(my_ulonglong2sv(mysql_affected_rows(imp_dbh->pmysql))))); - PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\tmariadb_st_fetch for %p, currow= %d\n", - sth,imp_sth->currow); + PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\tmariadb_st_fetch for %p, currow=%" SVf "\n", + sth, SVfARG(sv_2mortal(my_ulonglong2sv(imp_sth->currow)))); } if (!(cols= mysql_fetch_row(imp_sth->result))) @@ -5176,9 +5226,14 @@ mariadb_dr_do_error(sth, mysql_errno(imp_dbh->pmysql), mysql_error(imp_dbh->pmysql), mysql_sqlstate(imp_dbh->pmysql)); + if (!mysql_more_results(imp_dbh->pmysql)) + DBIc_ACTIVE_off(imp_sth); return Nullav; } + if (imp_sth->currow >= imp_sth->row_num && !mysql_more_results(imp_dbh->pmysql)) + DBIc_ACTIVE_off(imp_sth); + num_fields= mysql_num_fields(imp_sth->result); fields= mysql_fetch_fields(imp_sth->result); lengths= mysql_fetch_lengths(imp_sth->result); @@ -5310,31 +5365,22 @@ } if (imp_sth->use_server_side_prepare && imp_sth->stmt) - { - /* - We have to fetch all data from stmt - There is may be useful for 2 cases: - 1. st_finish when we have undef statement - 2. call st_execute again when we have some unfetched data in stmt - */ - if (DBIc_ACTIVE(imp_sth) && mariadb_st_describe(sth, imp_sth) && !imp_sth->fetch_done) - mysql_stmt_free_result(imp_sth->stmt); - } + mysql_stmt_free_result(imp_sth->stmt); + + /* + Clean-up previous result set(s) for sth to prevent + 'Commands out of sync' error + */ + if (!mariadb_st_free_result_sets(sth, imp_sth, FALSE)) + return 0; /* Cancel further fetches from this cursor. We don't close the cursor till DESTROY. The application may re execute it. */ - if (imp_sth && DBIc_ACTIVE(imp_sth)) - { - /* - Clean-up previous result set(s) for sth to prevent - 'Commands out of sync' error - */ - mariadb_st_free_result_sets(sth, imp_sth); - } DBIc_ACTIVE_off(imp_sth); + if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) { PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\n<-- mariadb_st_finish\n"); @@ -5366,6 +5412,16 @@ int num_params; int num_fields; + if (!PL_dirty) + { + /* During global destruction, DBI objects are destroyed in random order + * and therefore imp_dbh may be already freed. So do not access it. */ + mariadb_st_finish(sth, imp_sth); + mariadb_st_free_result_sets(sth, imp_sth, TRUE); + } + + DBIc_ACTIVE_off(imp_sth); + if (imp_sth->statement) Safefree(imp_sth->statement); @@ -5402,8 +5458,6 @@ imp_sth->stmt= NULL; } - /* mariadb_st_finish has already been called by .xs code if needed. */ - /* Free values allocated by mariadb_st_bind_ph */ if (imp_sth->params) { @@ -6401,7 +6455,7 @@ D_imp_xxh(h); imp_dbh_t* dbh; MYSQL* svsock = NULL; - MYSQL_RES* _res; + MYSQL_RES* _res = NULL; my_ulonglong retval = 0; unsigned int num_fields; int htype; @@ -6436,9 +6490,25 @@ } dbh->async_query_in_flight = NULL; + if (htype == DBIt_ST) + { + D_imp_sth(h); + DBIc_ACTIVE_off(imp_sth); + } + svsock= dbh->pmysql; if (!svsock) + { + mariadb_dr_do_error(h, CR_SERVER_GONE_ERROR, "MySQL server has gone away", "HY000"); return -1; + } + + if (*resp) + { + mysql_free_result(*resp); + *resp = NULL; + } + if (!mysql_read_query_result(svsock)) { *resp= mysql_store_result(svsock); @@ -6450,35 +6520,48 @@ } if (!*resp) retval= mysql_affected_rows(svsock); - else { + else retval= mysql_num_rows(*resp); - if(resp == &_res) { - mysql_free_result(*resp); - *resp= NULL; - } - } + + /* Some MySQL client versions return correct value from mysql_insert_id() + * function only after non-SELECT operation. So store insert id into dbh + * cache and later read it only from cache. */ + if (!*resp) + dbh->insertid = mysql_insert_id(svsock); + if(htype == DBIt_ST) { D_imp_sth(h); D_imp_dbh_from_sth; - if (retval != (my_ulonglong)-1) { + imp_sth->row_num = retval; + if(! *resp) { - /* Some MySQL client versions return correct value from mysql_insert_id() - * function only after non-SELECT operation. So store insert id into dbh - * cache and later read it only from cache. */ - imp_dbh->insertid = imp_sth->insertid = mysql_insert_id(svsock); - if(! mysql_more_results(svsock)) - DBIc_ACTIVE_off(imp_sth); + imp_sth->insertid = dbh->insertid; + if (mysql_more_results(svsock)) + DBIc_ACTIVE_on(imp_sth); } else { num_fields = mysql_num_fields(imp_sth->result); DBIc_NUM_FIELDS(imp_sth) = (num_fields <= INT_MAX) ? num_fields : INT_MAX; - imp_sth->done_desc = FALSE; - imp_sth->fetch_done = FALSE; + if (imp_sth->row_num) + DBIc_ACTIVE_on(imp_sth); } - } imp_sth->warning_count = mysql_warning_count(imp_dbh->pmysql); } + + if (*resp && resp == &_res) + { + mysql_free_result(*resp); + *resp = NULL; + } + + if (mysql_more_results(svsock)) + dbh->async_query_in_flight = imp_xxh; } else { +#if MYSQL_VERSION_ID < 50025 + /* Cover a protocol design error: error packet does not contain the server status. + * Luckily, an error always aborts execution of a statement, so it is safe to turn off the flag. */ + svsock->server_status &= ~SERVER_MORE_RESULTS_EXISTS; +#endif mariadb_dr_do_error(h, mysql_errno(svsock), mysql_error(svsock), mysql_sqlstate(svsock)); return (my_ulonglong)-1; diff -Nru libdbd-mariadb-perl-1.11/dbdimp.h libdbd-mariadb-perl-1.21/dbdimp.h --- libdbd-mariadb-perl-1.11/dbdimp.h 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/dbdimp.h 2019-02-27 11:04:38.000000000 +0000 @@ -17,17 +17,27 @@ /* * Header files we use */ -#include /* installed by the DBI module */ + +/* + * On WIN32 windows.h and winsock.h need to be included before mysql.h + * Otherwise SOCKET type which is needed for mysql.h is not defined + */ +#ifdef _WIN32 +#include +#include +#endif + #include /* Comes with MySQL-devel */ #include /* Comes MySQL */ - #include /* Comes with MySQL-devel */ -#include /* For uint32_t */ #ifndef MYSQL_VERSION_ID #include /* Comes with MySQL-devel */ #endif +#include /* installed by the DBI module */ +#include /* For uint32_t */ + #if !defined(MARIADB_BASE_VERSION) && defined(MARIADB_PACKAGE_VERSION) #define MARIADB_BASE_VERSION #endif @@ -407,6 +417,35 @@ }; /* purposes only */ +/* Double linked list */ +struct mariadb_list_entry { + void *data; + struct mariadb_list_entry *prev; + struct mariadb_list_entry *next; +}; +#define mariadb_list_add(list, entry, ptr) \ + STMT_START { \ + Newz(0, (entry), 1, struct mariadb_list_entry); \ + (entry)->data = (ptr); \ + (entry)->prev = NULL; \ + (entry)->next = (list); \ + if ((list)) \ + (list)->prev = (entry); \ + (list) = (entry); \ + } STMT_END +#define mariadb_list_remove(list, entry) \ + STMT_START { \ + if ((entry)->prev) \ + (entry)->prev->next = (entry)->next; \ + if ((entry)->next) \ + (entry)->next->prev = (entry)->prev; \ + if ((list) == (entry)) \ + (list) = (entry)->next; \ + Safefree((entry)); \ + (entry) = NULL; \ + } STMT_END + + /* * This is our part of the driver handle. We receive the handle as * an "SV*", say "drh", and receive a pointer to the structure below @@ -419,6 +458,9 @@ */ struct imp_drh_st { dbih_drc_t com; /* MUST be first element in structure */ + + struct mariadb_list_entry *active_imp_dbhs; /* List of imp_dbh structures with active MYSQL* */ + struct mariadb_list_entry *taken_pmysqls; /* List of active MYSQL* from take_imp_data() */ unsigned long int instances; bool non_embedded_started; #if !defined(HAVE_EMBEDDED) && defined(HAVE_BROKEN_INIT) @@ -427,7 +469,6 @@ bool embedded_started; SV *embedded_args; SV *embedded_groups; - AV *taken_pmysqls; /* List of active MYSQL* structures from take_imp_data() */ }; @@ -444,6 +485,7 @@ struct imp_dbh_st { dbih_dbc_t com; /* MUST be first element in structure */ + struct mariadb_list_entry *list_entry; /* Entry of imp_drh->active_imp_dbhs list */ MYSQL *pmysql; bool connected; /* Set to true after DBI->connect finished */ bool auto_reconnect; @@ -543,8 +585,7 @@ bool disable_fallback_for_server_prepare; MYSQL_RES* result; /* result */ - int currow; /* number of current row */ - bool fetch_done; /* mark that fetch done */ + my_ulonglong currow; /* number of current row */ my_ulonglong row_num; /* total number of rows */ bool done_desc; /* have we described this sth yet ? */ diff -Nru libdbd-mariadb-perl-1.11/debian/changelog libdbd-mariadb-perl-1.21/debian/changelog --- libdbd-mariadb-perl-1.11/debian/changelog 2019-10-19 08:03:18.000000000 +0000 +++ libdbd-mariadb-perl-1.21/debian/changelog 2020-11-11 16:03:38.000000000 +0000 @@ -1,3 +1,52 @@ +libdbd-mariadb-perl (1.21-1ubuntu2) hirsute; urgency=medium + + * Adjust test case expectation that works with either 8.0.22+ or prior + mysql versions. https://github.com/gooddata/DBD-MariaDB/issues/160 + + -- Dimitri John Ledkov Wed, 11 Nov 2020 16:03:38 +0000 + +libdbd-mariadb-perl (1.21-1ubuntu1) hirsute; urgency=low + + * Merge from Debian unstable. Remaining changes: + * Changes required for the MySQL 8.0 transition: + - Avoid IDENTIFIED BY on GRANT. + - GRANT SESSION_VARIABLES_ADMIN as required by MySQL >= 8.0.14. + + -- Dimitri John Ledkov Tue, 10 Nov 2020 14:07:21 +0000 + +libdbd-mariadb-perl (1.21-1) unstable; urgency=medium + + * Team upload. + * Import upstream version 1.21. + * Drop mariadb-10.3.12-message.patch which was taken from an upstream + pull request. + * Update years of packaging copyright. + * Update Build-Depends for cross builds. + * Set upstream metadata fields: Bug-Submit. + + -- gregor herrmann Sat, 21 Dec 2019 20:21:37 +0100 + +libdbd-mariadb-perl (1.11-4) unstable; urgency=medium + + * Team upload. + * Update autopkgtest setup. Only override smoke test instead of + duplicating whole test stack. + Replace ADTTMP with AUTOPKGTEST_TMP. + Update debian/tests/control to match the one generated by autodp8. + * Mark autopkgtest pkg-perl-autopkgtest-build-deps-{mysql,mariadb} as flaky. + Sometimes mysql/mariadb have issues on ci.debian.net, like running out of + memory, which shouldn't make this package's tests fail. + Cf. #942093 + * Annotate test-only build dependencies with . + * Declare compliance with Debian Policy 4.4.1. + * Bump debhelper-compat to 12. + * debian/watch: use uscan version 4. + * Remove obsolete fields Name, Contact from debian/upstream/metadata. + * Add lintian override (autopkgtests). + * Fix typo in old changelog entry. + + -- gregor herrmann Sat, 12 Oct 2019 23:50:58 +0200 + libdbd-mariadb-perl (1.11-3ubuntu2) focal; urgency=medium * No-change rebuild for the perl update. @@ -69,7 +118,7 @@ [ gregor herrmann ] * debian/tests/control: mark mysql test as skippable as there is no mysql in testing. - This mirrors Paul Gever's merge request for libdbd-mysql-perl. + This mirrors Paul Gevers' merge request for libdbd-mysql-perl. * debian/tests/control: drop "needs-recommends" restriction. Deprecated, and the package has no Recommends anyway. * Update years of packaging copyright. @@ -98,3 +147,4 @@ - set utf8 in db creation to enable more tests -- Xavier Guimard Thu, 23 Aug 2018 20:54:16 +0200 + diff -Nru libdbd-mariadb-perl-1.11/debian/compat libdbd-mariadb-perl-1.21/debian/compat --- libdbd-mariadb-perl-1.11/debian/compat 2019-01-17 17:33:11.000000000 +0000 +++ libdbd-mariadb-perl-1.21/debian/compat 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -11 diff -Nru libdbd-mariadb-perl-1.11/debian/control libdbd-mariadb-perl-1.21/debian/control --- libdbd-mariadb-perl-1.11/debian/control 2019-07-30 12:31:28.000000000 +0000 +++ libdbd-mariadb-perl-1.21/debian/control 2019-12-21 22:21:22.000000000 +0000 @@ -3,18 +3,20 @@ XSBC-Original-Maintainer: Debian Perl Group Uploaders: Xavier Guimard Section: perl +Testsuite: autopkgtest-pkg-perl Priority: optional -Build-Depends: debhelper (>= 11), +Build-Depends: debhelper-compat (= 12), default-libmysqlclient-dev (>= 1.0.5), - default-mysql-server, + default-mysql-server , libdbi-perl (>= 1.642), libdevel-checklib-perl (>= 1.12), - libnet-ssleay-perl, + libnet-ssleay-perl , libssl-dev, - libtest-deep-perl, - perl, - procps -Standards-Version: 4.3.0 + libtest-deep-perl , + perl-xs-dev, + perl:native, + procps +Standards-Version: 4.4.1 Vcs-Browser: https://salsa.debian.org/perl-team/modules/packages/libdbd-mariadb-perl Vcs-Git: https://salsa.debian.org/perl-team/modules/packages/libdbd-mariadb-perl.git Homepage: https://metacpan.org/release/DBD-MariaDB diff -Nru libdbd-mariadb-perl-1.11/debian/copyright libdbd-mariadb-perl-1.21/debian/copyright --- libdbd-mariadb-perl-1.11/debian/copyright 2019-01-17 17:33:11.000000000 +0000 +++ libdbd-mariadb-perl-1.21/debian/copyright 2019-12-21 22:21:22.000000000 +0000 @@ -23,7 +23,7 @@ 1997, Scott Hanson 1999-2007, Raphael Hertzog 2000, Guillaume Morin - 2006-2018, gregor herrmann + 2006-2019, gregor herrmann 2008, Roberto C. Sanchez 2009, Gunnar Wolf 2009, Tim Retout diff -Nru libdbd-mariadb-perl-1.11/debian/patches/fix-mysql-8.0.22.patch libdbd-mariadb-perl-1.21/debian/patches/fix-mysql-8.0.22.patch --- libdbd-mariadb-perl-1.11/debian/patches/fix-mysql-8.0.22.patch 1970-01-01 00:00:00.000000000 +0000 +++ libdbd-mariadb-perl-1.21/debian/patches/fix-mysql-8.0.22.patch 2020-11-11 16:03:38.000000000 +0000 @@ -0,0 +1,14 @@ +Description: Adjust test case expectation that works with either 8.0.22+ or prior mysql versions. +Bug: https://github.com/gooddata/DBD-MariaDB/issues/160 +Author: Dimitri John Ledkov + +--- libdbd-mariadb-perl-1.21.orig/t/rt122541-decimals.t ++++ libdbd-mariadb-perl-1.21/t/rt122541-decimals.t +@@ -14,6 +14,6 @@ plan tests => 2; + + for my $mariadb_server_prepare (0, 1) { + $dbh->{mariadb_server_prepare} = $mariadb_server_prepare; +- is $dbh->selectrow_arrayref('SELECT round(degrees(0.00043) * 69, 2)')->[0], '1.70', ++ like $dbh->selectrow_arrayref('SELECT round(degrees(0.00043) * 69, 2)')->[0], qr/1.70?/, + 'floats with fixed-length of decimals returns correct value for mariadb_server_prepare=' . $mariadb_server_prepare; + } diff -Nru libdbd-mariadb-perl-1.11/debian/patches/mariadb-10.3.12-message.patch libdbd-mariadb-perl-1.21/debian/patches/mariadb-10.3.12-message.patch --- libdbd-mariadb-perl-1.11/debian/patches/mariadb-10.3.12-message.patch 2019-01-17 17:33:11.000000000 +0000 +++ libdbd-mariadb-perl-1.21/debian/patches/mariadb-10.3.12-message.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -From aab664921d377888c666ad4675722ae88e7d58af Mon Sep 17 00:00:00 2001 -From: Pali -Date: Thu, 17 Jan 2019 09:47:06 +0100 -Subject: [PATCH 1/2] Fix warning message in test t/55utf8.t for MariaDB - 10.2.20+, 10.3.12+ and 10.4.1+ - -Bug: https://github.com/gooddata/DBD-MariaDB/issues/121 -Bug-Debian: https://bugs.debian.org/919071 ---- - t/55utf8.t | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/t/55utf8.t b/t/55utf8.t -index cbea705..bf12869 100644 ---- a/t/55utf8.t -+++ b/t/55utf8.t -@@ -80,7 +80,7 @@ ok $sth->finish; - - cmp_ok($dbh->{mariadb_warning_count}, '==', 1, 'got warning for INSERT') or do { diag("SHOW WARNINGS:"); diag($_->[2]) foreach $dbh->selectall_array("SHOW WARNINGS", { mariadb_server_prepare => 0 }); }; - my (undef, undef, $warning) = $dbh->selectrow_array("SHOW WARNINGS", { mariadb_server_prepare => 0 }); --like($warning, qr/^(?:Incorrect string value: '\\xC4\\x80dam'|Data truncated) for column 'ascii' at row 1$/, 'warning is correct'); -+like($warning, qr/^(?:Incorrect string value: '\\xC4\\x80dam'|Data truncated) for column (?:'ascii'|`.*`\.`.*`\.`ascii`) at row 1$/, 'warning is correct'); - - # AsBinary() is deprecated as of MySQL 5.7.6, use ST_AsBinary() instead - my $asbinary = $dbh->{mariadb_serverversion} >= 50706 ? 'ST_AsBinary' : 'AsBinary'; - diff -Nru libdbd-mariadb-perl-1.11/debian/patches/series libdbd-mariadb-perl-1.21/debian/patches/series --- libdbd-mariadb-perl-1.11/debian/patches/series 2019-01-17 17:33:11.000000000 +0000 +++ libdbd-mariadb-perl-1.21/debian/patches/series 2020-11-11 16:03:38.000000000 +0000 @@ -1 +1 @@ -mariadb-10.3.12-message.patch +fix-mysql-8.0.22.patch diff -Nru libdbd-mariadb-perl-1.11/debian/source/lintian-overrides libdbd-mariadb-perl-1.21/debian/source/lintian-overrides --- libdbd-mariadb-perl-1.11/debian/source/lintian-overrides 1970-01-01 00:00:00.000000000 +0000 +++ libdbd-mariadb-perl-1.21/debian/source/lintian-overrides 2019-12-21 19:21:37.000000000 +0000 @@ -0,0 +1,3 @@ +# pkg-perl specific lintian check +# in this case we indeed use an explicit test control file +libdbd-mariadb-perl source: nonteam-testsuite-header autopkgtest, autopkgtest-pkg-perl diff -Nru libdbd-mariadb-perl-1.11/debian/tests/control libdbd-mariadb-perl-1.21/debian/tests/control --- libdbd-mariadb-perl-1.11/debian/tests/control 2019-01-17 17:33:11.000000000 +0000 +++ libdbd-mariadb-perl-1.21/debian/tests/control 2019-12-21 22:21:23.000000000 +0000 @@ -1,16 +1,9 @@ -Test-Command: /usr/share/pkg-perl-autopkgtest/runner runtime-deps -Depends: @, pkg-perl-autopkgtest -Features: test-name=pkg-perl-autopkgtest-runtime-deps - -Test-Command: /usr/share/pkg-perl-autopkgtest/runner runtime-deps-and-recommends -Depends: @, pkg-perl-autopkgtest -Features: test-name=pkg-perl-autopkgtest-runtime-deps-and-recommends - -Test-Command: /usr/share/pkg-perl-autopkgtest/runner build-deps +Test-Command: /usr/share/pkg-perl-autopkgtest/build-deps.d/smoke Depends: @, default-libmysqlclient-dev, libdbi-perl, libdevel-checklib-perl (>= 1.12), libnet-ssleay-perl, libssl-dev, libtest-deep-perl, perl, procps, mariadb-server, pkg-perl-autopkgtest +Restrictions: skippable, flaky Features: test-name=pkg-perl-autopkgtest-build-deps-mariadb -Test-Command: /usr/share/pkg-perl-autopkgtest/runner build-deps +Test-Command: /usr/share/pkg-perl-autopkgtest/build-deps.d/smoke Depends: @, default-libmysqlclient-dev, libdbi-perl, libdevel-checklib-perl (>= 1.12), libnet-ssleay-perl, libssl-dev, libtest-deep-perl, perl, procps, mysql-server (>= 5.7), pkg-perl-autopkgtest -Restrictions: skip-not-installable +Restrictions: skippable, skip-not-installable, flaky Features: test-name=pkg-perl-autopkgtest-build-deps-mysql diff -Nru libdbd-mariadb-perl-1.11/debian/tests/pkg-perl/SKIP libdbd-mariadb-perl-1.21/debian/tests/pkg-perl/SKIP --- libdbd-mariadb-perl-1.11/debian/tests/pkg-perl/SKIP 1970-01-01 00:00:00.000000000 +0000 +++ libdbd-mariadb-perl-1.21/debian/tests/pkg-perl/SKIP 2019-12-21 19:21:37.000000000 +0000 @@ -0,0 +1,2 @@ +# skip default smoke run +smoke diff -Nru libdbd-mariadb-perl-1.11/debian/tests/pkg-perl/smoke-cleanup libdbd-mariadb-perl-1.21/debian/tests/pkg-perl/smoke-cleanup --- libdbd-mariadb-perl-1.11/debian/tests/pkg-perl/smoke-cleanup 2019-01-17 17:33:11.000000000 +0000 +++ libdbd-mariadb-perl-1.21/debian/tests/pkg-perl/smoke-cleanup 2019-12-21 22:21:23.000000000 +0000 @@ -1,6 +1,6 @@ #!/bin/sh -[ -z "$ADTTMP" ] || cd $TDIR +[ -z "$AUTOPKGTEST_TMP" ] || cd $TDIR /usr/bin/mysqladmin --user=root --socket=${MYSQL_UNIX_PORT} shutdown 2>&1 || \ [ ! -s "${MYSQL_PIDFILE}" ] || /bin/kill $(cat "${MYSQL_PIDFILE}") || true diff -Nru libdbd-mariadb-perl-1.11/debian/tests/pkg-perl/smoke-setup libdbd-mariadb-perl-1.21/debian/tests/pkg-perl/smoke-setup --- libdbd-mariadb-perl-1.11/debian/tests/pkg-perl/smoke-setup 2019-07-30 12:31:28.000000000 +0000 +++ libdbd-mariadb-perl-1.21/debian/tests/pkg-perl/smoke-setup 2019-12-21 22:21:23.000000000 +0000 @@ -2,7 +2,7 @@ set -e -[ -z "$ADTTMP" ] || cd $TDIR +[ -z "$AUTOPKGTEST_TMP" ] || cd $TDIR rm -rf ${MYSQL_DIR} diff -Nru libdbd-mariadb-perl-1.11/debian/upstream/metadata libdbd-mariadb-perl-1.21/debian/upstream/metadata --- libdbd-mariadb-perl-1.11/debian/upstream/metadata 2019-01-17 17:33:11.000000000 +0000 +++ libdbd-mariadb-perl-1.21/debian/upstream/metadata 2019-12-21 22:21:23.000000000 +0000 @@ -1,7 +1,5 @@ ---- Archive: CPAN Bug-Database: https://github.com/gooddata/DBD-MariaDB/issues -Contact: Pali -Name: DBD-MariaDB Repository: https://github.com/gooddata/DBD-MariaDB.git Repository-Browse: https://github.com/gooddata/DBD-MariaDB +Bug-Submit: https://github.com/gooddata/DBD-MariaDB/issues/new diff -Nru libdbd-mariadb-perl-1.11/debian/watch libdbd-mariadb-perl-1.21/debian/watch --- libdbd-mariadb-perl-1.11/debian/watch 2019-01-17 17:33:11.000000000 +0000 +++ libdbd-mariadb-perl-1.21/debian/watch 2019-12-21 22:21:22.000000000 +0000 @@ -1,2 +1,2 @@ -version=3 -https://metacpan.org/release/DBD-MariaDB .*/DBD-MariaDB-v?(\d[\d.-]*)\.(?:tar(?:\.gz|\.bz2)?|tgz|zip)$ +version=4 +https://metacpan.org/release/DBD-MariaDB .*/DBD-MariaDB-v?@ANY_VERSION@@ARCHIVE_EXT@$ diff -Nru libdbd-mariadb-perl-1.11/lib/DBD/MariaDB.pm libdbd-mariadb-perl-1.21/lib/DBD/MariaDB.pm --- libdbd-mariadb-perl-1.11/lib/DBD/MariaDB.pm 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/lib/DBD/MariaDB.pm 2019-02-27 11:04:38.000000000 +0000 @@ -10,7 +10,7 @@ use DynaLoader(); our @ISA = qw(DynaLoader); -our $VERSION = '1.11'; +our $VERSION = '1.21'; bootstrap DBD::MariaDB $VERSION; diff -Nru libdbd-mariadb-perl-1.11/lib/DBD/MariaDB.pod libdbd-mariadb-perl-1.21/lib/DBD/MariaDB.pod --- libdbd-mariadb-perl-1.11/lib/DBD/MariaDB.pod 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/lib/DBD/MariaDB.pod 2019-02-27 11:04:38.000000000 +0000 @@ -19,7 +19,6 @@ while (my $ref = $sth->fetchrow_hashref()) { print "Found a row: id = $ref->{'id'}, fn = $ref->{'first_name'}\n"; } - $sth->finish(); =head1 EXAMPLE @@ -55,7 +54,6 @@ while (my $ref = $sth->fetchrow_hashref()) { print "Found a row: id = $ref->{'id'}, name = $ref->{'name'}\n"; } - $sth->finish(); # Disconnect from the database. $dbh->disconnect(); diff -Nru libdbd-mariadb-perl-1.11/Makefile.PL libdbd-mariadb-perl-1.21/Makefile.PL --- libdbd-mariadb-perl-1.11/Makefile.PL 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/Makefile.PL 2019-02-27 11:04:38.000000000 +0000 @@ -16,6 +16,12 @@ my $TESTDB = "test"; +# On WIN32 windows.h and winsock.h need to be included before mysql.h +# Otherwise SOCKET type which is needed for mysql.h is not defined +my @mysql_headers; +push @mysql_headers, 'windows.h', 'winsock.h' if $^O eq 'MSWin32'; +push @mysql_headers, 'mysql.h'; + our $opt = { "help" => \&Usage, }; my ($test_host, $test_port, $test_socket); @@ -68,7 +74,7 @@ if ($opt->{'mysql_config'} ne 'skip') { $opt->{'mysql_config'} = Win32::GetShortPathName($opt->{'mysql_config'}) if $^O eq 'MSWin32'; - if (! defined `$opt->{'mysql_config'} 2>&1`) + if (!CanExecute($opt->{'mysql_config'})) { die <<"MSG"; @@ -80,11 +86,11 @@ } else { - if (defined `mariadb_config 2>&1`) + if (CanExecute("mariadb_config")) { $opt->{'mysql_config'} = "mariadb_config"; } - elsif (defined `mysql_config 2>&1`) + elsif (CanExecute("mysql_config")) { $opt->{'mysql_config'} = "mysql_config"; } @@ -223,7 +229,7 @@ LIBS => (join ' ', @libdirs, $main_lib, @libs), ccflags => (join ' ', $opt->{cflags}, ($Config{usedl} ? $Config{cccdlflags} : ())), ldflags => (join ' ', @libdirs, @ldflags, ($Config{usedl} ? $Config{lddlflags} : ())), - header => 'mysql.h', + header => \@mysql_headers, not_execute => 1, ); @@ -233,7 +239,7 @@ LIBS => (join ' ', @libdirs, $main_lib), ccflags => $opt->{cflags}, ldflags => (join ' ', @libdirs, @libs, @ldflags), - header => 'mysql.h', + header => \@mysql_headers, function => "\n#ifndef MYSQL_VERSION_ID\n#include \n#endif\nreturn (MYSQL_VERSION_ID >= 40108) ? 0 : 1;\n", ) or die <<"MSG"; @@ -248,7 +254,7 @@ LIBS => (join ' ', @libdirs, $main_lib), ccflags => $opt->{cflags}, ldflags => (join ' ', @libdirs, @libs, @ldflags), - header => 'mysql.h', + header => \@mysql_headers, function => 'return mysql_embedded() ? 0 : 1;', ); @@ -258,7 +264,7 @@ LIBS => (join ' ', @libdirs, $main_lib), ccflags => $opt->{cflags}, ldflags => (join ' ', @libdirs, @libs, @ldflags), - header => 'mysql.h', + header => \@mysql_headers, function => 'unsigned int get_charset_number(const char *cs_name, unsigned int cs_flags); mysql_server_init(-1, 0, 0); get_charset_number("utf8", 32); return 0;', ); @@ -266,7 +272,7 @@ LIBS => (join ' ', @libdirs, $main_lib), ccflags => $opt->{cflags}, ldflags => (join ' ', @libdirs, @libs, @ldflags), - header => 'mysql.h', + header => \@mysql_headers, function => 'MYSQL mysql; char buf[1024]; mysql_server_init(-1, 0, 0); mysql_init(&mysql); mysql_get_option(&mysql, 0, &buf); return 0;', ); @@ -274,10 +280,137 @@ LIBS => (join ' ', @libdirs, $main_lib), ccflags => $opt->{cflags}, ldflags => (join ' ', @libdirs, @libs, @ldflags), - header => 'mysql.h', + header => \@mysql_headers, function => 'mariadb_deinitialize_ssl = 0; return 0;', ); +# Check if mysql_server_end() deinitialize OpenSSL library functions +# See: https://github.com/gooddata/DBD-MariaDB/issues/119 +my $have_problem_with_openssl = !check_lib( + LIBS => (join ' ', @libdirs, $main_lib), + ccflags => $opt->{cflags}, + ldflags => (join ' ', @libdirs, @libs, @ldflags, $Config{perllibs}), + header => \@mysql_headers, + function => << 'EOF' + +#ifndef _WIN32 + #ifndef _GNU_SOURCE + #define _GNU_SOURCE + #endif + #include + #ifndef RTLD_DEFAULT + #define RTLD_DEFAULT ((void *)0) + #endif +#endif + +int (*OPENSSL_init_ssl_func)(unsigned long long, const void *); +void (*SSL_load_error_strings_func)(void); +int (*SSL_library_init_func)(void); +void *(*SSL_CTX_new_func)(const void *method); +void (*SSL_CTX_free_func)(void *ctx); +const void *(*TLS_method_func)(void); +const void *method1; +const void *method2; +void *ctx1; +void *ctx2; + +#ifdef _WIN32 + + BOOL (WINAPI *EnumProcessModules_func)(HANDLE, HMODULE *, DWORD, LPDWORD); + HMODULE psapi_lib; + DWORD size, i; + HMODULE *modules; + + modules = NULL; + psapi_lib = LoadLibraryA("Psapi.dll"); + if (psapi_lib) { + EnumProcessModules_func = (BOOL (WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD))GetProcAddress(psapi_lib, "EnumProcessModules"); + if (EnumProcessModules_func) { + if (EnumProcessModules_func((HANDLE)-1, NULL, 0, &size)) { + modules = (HMODULE *)GlobalAlloc(GPTR, size); + if (modules && !EnumProcessModules_func((HANDLE)-1, modules, size, &size)) + modules = NULL; + } + } + } + + #define SYMBOL(var, type, sym) do { \ + var = (type)GetProcAddress(GetModuleHandle(NULL), sym); \ + if (!var) { \ + if (!modules) \ + return 1; \ + for (i = 0; i < size/sizeof(*modules); ++i) { \ + var = (type)GetProcAddress(modules[i], sym); \ + if (var) \ + break; \ + } \ + } \ + } while (0) + +#else + + #define SYMBOL(var, type, sym) do { var = (type)dlsym(RTLD_DEFAULT, sym); } while (0) + +#endif + +SYMBOL(OPENSSL_init_ssl_func, int (*)(unsigned long long, const void *), "OPENSSL_init_ssl"); +SYMBOL(SSL_library_init_func, int (*)(void), "SSL_library_init"); +if (!OPENSSL_init_ssl_func && !SSL_library_init_func) + return 0; +SYMBOL(SSL_load_error_strings_func, void (*)(void), "SSL_load_error_strings"); +if (!OPENSSL_init_ssl_func && !SSL_load_error_strings_func) + return 0; +SYMBOL(SSL_CTX_new_func, void *(*)(const void *), "SSL_CTX_new"); +if (!SSL_CTX_new_func) + return 0; +SYMBOL(SSL_CTX_free_func, void (*)(void *), "SSL_CTX_free"); +if (!SSL_CTX_free_func) + return 0; + +SYMBOL(TLS_method_func, const void *(*)(void), "TLS_method"); +if (!TLS_method_func) + SYMBOL(TLS_method_func, const void *(*)(void), "TLSv1_2_method"); +if (!TLS_method_func) + SYMBOL(TLS_method_func, const void *(*)(void), "TLSv1_1_method"); +if (!TLS_method_func) + SYMBOL(TLS_method_func, const void *(*)(void), "TLSv1_method"); +if (!TLS_method_func) + return 0; + +if (OPENSSL_init_ssl_func) { + OPENSSL_init_ssl_func(0, (void *)0); +} else { + SSL_library_init_func(); + SSL_load_error_strings_func(); +} + +method1 = TLS_method_func(); +if (!method1) + return 1; +ctx1 = SSL_CTX_new_func(method1); +if (!ctx1) + return 1; + +mysql_server_init(-1, 0, 0); +mysql_server_end(); + +method2 = TLS_method_func(); +if (!method2) + return 1; +ctx2 = SSL_CTX_new_func(method2); +if (!ctx2) + return 1; + +SSL_CTX_free_func(ctx1); +SSL_CTX_free_func(ctx2); + +return 0; + +EOF +); + +print "Client library deinitialize OpenSSL library functions: " . ($have_problem_with_openssl ? "yes" : "no") . "\n\n"; + my $fileName = File::Spec->catfile("t", "MariaDB.mtest"); (open(FILE, ">$fileName") && (print FILE ("{ local " . Data::Dumper->Dump([$opt], ["opt"]) . @@ -307,6 +440,7 @@ $cflags .= " -DHAVE_GET_CHARSET_NUMBER" if $have_get_charset_number; $cflags .= " -DHAVE_GET_OPTION" if $have_get_option; $cflags .= " -DHAVE_DEINITIALIZE_SSL" if $have_deinitialize_ssl; +$cflags .= " -DHAVE_PROBLEM_WITH_OPENSSL" if $have_problem_with_openssl; my %o = ( 'NAME' => 'DBD::MariaDB', 'INC' => $cflags, 'dist' => { 'SUFFIX' => ".gz", @@ -416,7 +550,7 @@ prereqs => { test => { recommends => { - 'Net::SSLeay' => 0, + 'Net::SSLeay' => '1.43', 'Proc::ProcessTable' => 0, 'TAP::Harness' => '3.31', 'CPAN::Meta::YAML' => 0, @@ -525,13 +659,23 @@ } +sub CanExecute { + my ($command) = @_; + return MM->maybe_command($command) if File::Spec->file_name_is_absolute($command); + foreach my $dir (File::Spec->path) { + return 1 if MM->maybe_command(File::Spec->catfile($dir, $command)); + } + return 0; +} + + my %ParsedCache; sub ParseMySQLConfig { my ($opt, $param) = @_; return $ParsedCache{$param} if exists $ParsedCache{$param}; return undef unless $opt->{'mysql_config'} and $opt->{'mysql_config'} ne 'skip'; my $output = `$opt->{'mysql_config'} --$param 2>&1`; - if (defined $output and $output !~ /Options:|Usage:|unrecognized option/) { + if ($? == 0 and defined $output and $output !~ /Options:|Usage:|unrecognized option/) { $output =~ s/\s+$//s; $output =~ s/^\s+//s; $ParsedCache{$param} = $output; @@ -611,7 +755,7 @@ LIBS => (join ' ', @libdirs, $main_lib), ldflags => (join ' ', @libdirs, $ldflags, $Config{lddlflags}), ccflags => (join ' ', $opt->{cflags}, $Config{cccdlflags}), - header => 'mysql.h', + header => \@mysql_headers, function => $function, not_execute => 1, ) or next; @@ -621,7 +765,7 @@ LIBS => (join ' ', @libdirs, $main_lib), ldflags => (join ' ', @libdirs, $ldflags), ccflags => $opt->{cflags}, - header => 'mysql.h', + header => \@mysql_headers, function => $function, ) or next; $str .= ' ' . $add_ldflags if defined $add_ldflags; diff -Nru libdbd-mariadb-perl-1.11/MANIFEST libdbd-mariadb-perl-1.21/MANIFEST --- libdbd-mariadb-perl-1.11/MANIFEST 2019-01-02 15:34:06.000000000 +0000 +++ libdbd-mariadb-perl-1.21/MANIFEST 2019-02-27 11:05:31.000000000 +0000 @@ -19,6 +19,7 @@ t/11data_sources.t t/12embedded.t t/13disconnect.t +t/14destruct.t t/15reconnect.t t/16dbi-get_info.t t/20createdrop.t diff -Nru libdbd-mariadb-perl-1.11/MANIFEST.SKIP libdbd-mariadb-perl-1.21/MANIFEST.SKIP --- libdbd-mariadb-perl-1.11/MANIFEST.SKIP 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/MANIFEST.SKIP 2019-02-27 11:04:38.000000000 +0000 @@ -1,18 +1,21 @@ -\B\.git\b -^blib\/ -pm_to_blib -\~$ -^Makefile(\.old)?$ -.gitignore -^DBD-MariaDB-\d -\.bak$ -\.tmp$ -\.o$ -t/MariaDB.mtest -^MYMETA -MariaDB.c -MariaDB.xsi -MariaDB.bs -appveyor.yml -.mailmap -.travis.yml +^.*\.exe$ +^.*\.o$ +^DBD-MariaDB-.*\.tar\.gz$ +^MYMETA\.json$ +^MYMETA\.yml$ +^Makefile$ +^Makefile\.old$ +^MariaDB\.bs$ +^MariaDB\.c$ +^MariaDB\.def$ +^MariaDB\.xsi$ +^\.git/.*$ +^\.gitignore$ +^\.mailmap$ +^\.travis\.yml$ +^appveyor\.yml$ +^blib/.*$ +^dll\.base$ +^dll\.exp$ +^pm_to_blib$ +^t/MariaDB\.mtest$ diff -Nru libdbd-mariadb-perl-1.11/MariaDB.xs libdbd-mariadb-perl-1.21/MariaDB.xs --- libdbd-mariadb-perl-1.11/MariaDB.xs 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/MariaDB.xs 2019-02-27 11:04:38.000000000 +0000 @@ -63,12 +63,15 @@ newTypeSub(stash, MYSQL_TYPE_VAR_STRING); newTypeSub(stash, MYSQL_TYPE_STRING); #undef newTypeSub -#ifdef HAVE_DEINITIALIZE_SSL +#if defined(HAVE_DEINITIALIZE_SSL) && defined(HAVE_PROBLEM_WITH_OPENSSL) /* Do not deinitialize OpenSSL library after mysql_server_end() * See: https://github.com/gooddata/DBD-MariaDB/issues/119 */ mariadb_deinitialize_ssl = 0; #endif +#ifndef _WIN32 + /* Calling mysql_thread_init() on WIN32 cause crash */ mysql_thread_init(); +#endif } MODULE = DBD::MariaDB PACKAGE = DBD::MariaDB::db @@ -233,6 +236,8 @@ XSRETURN_UNDEF; } } + if (imp_sth->row_num == (my_ulonglong)-1) + XSRETURN_IV(-1); RETVAL = my_ulonglong2sv(imp_sth->row_num); OUTPUT: RETVAL @@ -270,8 +275,6 @@ if (retval == (my_ulonglong)-1) XSRETURN_UNDEF; - imp_sth->row_num = retval; - if (retval == 0) XSRETURN_PV("0E0"); diff -Nru libdbd-mariadb-perl-1.11/META.json libdbd-mariadb-perl-1.21/META.json --- libdbd-mariadb-perl-1.11/META.json 2019-01-02 15:34:06.000000000 +0000 +++ libdbd-mariadb-perl-1.21/META.json 2019-02-27 11:05:31.000000000 +0000 @@ -51,7 +51,7 @@ "test" : { "recommends" : { "CPAN::Meta::YAML" : "0", - "Net::SSLeay" : "0", + "Net::SSLeay" : "1.43", "Proc::ProcessTable" : "0", "TAP::Harness" : "3.31" }, @@ -97,7 +97,7 @@ "x_IRC" : "irc://irc.perl.org/#dbi", "x_MailingList" : "mailto:dbi-dev@perl.org" }, - "version" : "1.11", + "version" : "1.21", "x_contributors" : [ "Alexandr Ciornii ", "Alexey Molchanov ", diff -Nru libdbd-mariadb-perl-1.11/META.yml libdbd-mariadb-perl-1.21/META.yml --- libdbd-mariadb-perl-1.11/META.yml 2019-01-02 15:34:06.000000000 +0000 +++ libdbd-mariadb-perl-1.21/META.yml 2019-02-27 11:05:31.000000000 +0000 @@ -55,7 +55,7 @@ homepage: https://github.com/gooddata/DBD-MariaDB license: http://dev.perl.org/licenses/ repository: git://github.com/gooddata/DBD-MariaDB.git -version: '1.11' +version: '1.21' x_contributors: - 'Alexandr Ciornii ' - 'Alexey Molchanov ' diff -Nru libdbd-mariadb-perl-1.11/README.pod libdbd-mariadb-perl-1.21/README.pod --- libdbd-mariadb-perl-1.11/README.pod 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/README.pod 2019-02-27 11:04:38.000000000 +0000 @@ -1,6 +1,17 @@ =head1 DBD::MariaDB - database driver for Perl -=for html +=begin html + +

+ +Travis CI Build Status + +AppVeyor Build Status +

+ +=end html This is the Perl L driver for access to MariaDB and MySQL databases. diff -Nru libdbd-mariadb-perl-1.11/socket.c libdbd-mariadb-perl-1.21/socket.c --- libdbd-mariadb-perl-1.11/socket.c 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/socket.c 2019-02-27 11:04:38.000000000 +0000 @@ -1,15 +1,21 @@ +/* + * On WIN32 windows.h and winsock.h need to be included before mysql.h + * Otherwise SOCKET type which is needed for mysql.h is not defined + */ #ifdef _WIN32 -#include "windows.h" -#include "winsock.h" +#include +#include #endif +#include +#include +#include #ifndef _WIN32 -#include -#include +#include +#include +#include #endif -#include - /* * Warning: Native socket code must be outside of dbdimp.c and dbdimp.h because * perl header files redefine socket function. This file must not @@ -18,12 +24,9 @@ int mariadb_dr_socket_ready(my_socket fd) { - int retval; - -#ifdef _WIN32 - /* Windows does not have poll(), so use select() instead */ struct timeval timeout; fd_set fds; + int retval; FD_ZERO(&fds); FD_SET(fd, &fds); @@ -32,15 +35,6 @@ timeout.tv_usec = 0; retval = select(fd+1, &fds, NULL, NULL, &timeout); -#else - struct pollfd fds; - - fds.fd = fd; - fds.events = POLLIN; - - retval = poll(&fds, 1, 0); -#endif - if (retval < 0) { #ifdef _WIN32 /* Windows does not update errno */ diff -Nru libdbd-mariadb-perl-1.11/t/14destruct.t libdbd-mariadb-perl-1.21/t/14destruct.t --- libdbd-mariadb-perl-1.11/t/14destruct.t 1970-01-01 00:00:00.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/14destruct.t 2019-02-27 11:04:38.000000000 +0000 @@ -0,0 +1,25 @@ +use strict; +use warnings; + +use Test::More; +use DBI; + +use vars qw($test_dsn $test_user $test_password); +use lib 't', '.'; +require 'lib.pl'; + +my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0 }); + +plan tests => 3; + +ok my $sth1 = $dbh->prepare("SELECT 1"); +ok my $sth2 = $dbh->prepare("SELECT 1", { mariadb_server_prepare => 1 }); + +# install a handler so that a warning about unfreed resources gets caught +$SIG{__WARN__} = sub { die @_ }; + +END { + my $sth1_copy = $sth1; + my $sth2_copy = $sth2; + pass if $sth1; +} diff -Nru libdbd-mariadb-perl-1.11/t/25lockunlock.t libdbd-mariadb-perl-1.21/t/25lockunlock.t --- libdbd-mariadb-perl-1.11/t/25lockunlock.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/25lockunlock.t 2019-02-27 11:04:38.000000000 +0000 @@ -40,7 +40,6 @@ $errstr= ''; $row = $sth->fetchrow_arrayref; $errstr= $sth->errstr; -$sth->finish; ok !defined($row), "Fetch should have failed"; ok !defined($errstr), "Fetch should have failed"; diff -Nru libdbd-mariadb-perl-1.11/t/29warnings.t libdbd-mariadb-perl-1.21/t/29warnings.t --- libdbd-mariadb-perl-1.11/t/29warnings.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/29warnings.t 2019-02-27 11:04:38.000000000 +0000 @@ -12,11 +12,6 @@ my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0, AutoCommit => 0 }); -my $expected_warnings = 2; -if ($dbh->{mariadb_serverversion} >= 50000 && $dbh->{mariadb_serverversion} < 50500) { - $expected_warnings = 1; -} - plan tests => 14; ok(defined $dbh, "Connected to database"); @@ -43,15 +38,14 @@ is($sth->{'mariadb_warning_count'}, 2 ); -# $dbh->{mariadb_info} actually uses mysql_info() -my $str = $dbh->{mariadb_info}; -my $numwarn; -if ( $str =~ /Warnings:\s(\d+)$/ ) { - $numwarn = $1; -} - # this test passes on mysql 5.5.x and fails on 5.1.x -# but I'm not sure which versions, so I'll just disable it for now -is($numwarn, $expected_warnings); +# so change number of expected warnings from mysql_info() +my $expected_warnings = 2; +if ($dbh->{mariadb_serverversion} >= 50000 && $dbh->{mariadb_serverversion} < 50500) { + $expected_warnings = 1; +} +# $dbh->{mariadb_info} actually uses mysql_info() +my $info = $dbh->{mariadb_info}; +like($info, qr/Warnings:\s\Q$expected_warnings\E$/); ok($dbh->disconnect); diff -Nru libdbd-mariadb-perl-1.11/t/30insertfetch.t libdbd-mariadb-perl-1.21/t/30insertfetch.t --- libdbd-mariadb-perl-1.11/t/30insertfetch.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/30insertfetch.t 2019-02-27 11:04:38.000000000 +0000 @@ -40,8 +40,6 @@ ok(not $sth->fetchrow_arrayref()); -ok($sth->finish()); - ok($dbh->disconnect()); done_testing; diff -Nru libdbd-mariadb-perl-1.11/t/31insertid.t libdbd-mariadb-perl-1.21/t/31insertid.t --- libdbd-mariadb-perl-1.11/t/31insertid.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/31insertid.t 2019-02-27 11:04:38.000000000 +0000 @@ -11,7 +11,7 @@ my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0 }); -plan tests => 3 + 2*37; +plan tests => 3 + 2*35; SKIP: { skip 'SET @@auto_increment_offset needs MySQL >= 5.0.2', 2 unless $dbh->{mariadb_serverversion} >= 50002; @@ -87,9 +87,6 @@ is $sth3->{mariadb_insertid}, 3, "third insert id == \$sth3->{mariadb_insertid}"; is $sth3->last_insert_id(), 3, "third insert id == \$sth3->last_insert_id()"; -ok $sth->finish(); -ok $sth2->finish(); - ok $dbh->do('DROP TEMPORARY TABLE dbd_mysql_t31'); } diff -Nru libdbd-mariadb-perl-1.11/t/32insert_error.t libdbd-mariadb-perl-1.21/t/32insert_error.t --- libdbd-mariadb-perl-1.11/t/32insert_error.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/32insert_error.t 2019-02-27 11:04:38.000000000 +0000 @@ -11,7 +11,7 @@ my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0 }); -plan tests => 9; +plan tests => 8; ok $dbh->do("DROP TABLE IF EXISTS dbd_mysql_t32"); @@ -33,8 +33,6 @@ ok $sth->execute(2, "Jochen"); -ok $sth->finish; - ok $dbh->do("DROP TABLE dbd_mysql_t32"); ok $dbh->disconnect(); diff -Nru libdbd-mariadb-perl-1.11/t/35limit.t libdbd-mariadb-perl-1.21/t/35limit.t --- libdbd-mariadb-perl-1.11/t/35limit.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/35limit.t 2019-02-27 11:04:38.000000000 +0000 @@ -14,7 +14,7 @@ my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0, AutoCommit => 0 }); -plan tests => 111; +plan tests => 110; ok(defined $dbh, "Connected to database"); @@ -44,8 +44,6 @@ ok(@$array_ref == 50); -ok($sth->finish); - ok($dbh->do("DROP TABLE dbd_mysql_t35")); ok($dbh->disconnect); diff -Nru libdbd-mariadb-perl-1.11/t/35prepare.t libdbd-mariadb-perl-1.21/t/35prepare.t --- libdbd-mariadb-perl-1.11/t/35prepare.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/35prepare.t 2019-02-27 11:04:38.000000000 +0000 @@ -13,9 +13,11 @@ $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0 }); -plan tests => 50; +plan tests => 5+2*63; -ok(defined $dbh, "Connected to database"); +for my $mariadb_server_prepare (0, 1) { + +$dbh->{mariadb_server_prepare} = $mariadb_server_prepare; ok($dbh->do("DROP TABLE IF EXISTS dbd_mysql_t35prepare"), "Making slate clean"); @@ -45,8 +47,6 @@ ok($rows == 1, "One row should have been inserted"); -ok($sth->finish, "Finishing up with statement handle"); - ok($sth= $dbh->prepare("SELECT id, name FROM dbd_mysql_t35prepare WHERE id = 1"), "Testing prepare of query"); @@ -66,11 +66,9 @@ # save these values for later testing $testInsertVals->{$i}= $random_chars; ok($rows= $sth->execute($i, $random_chars), "Testing insert row"); - ok($rows= 1, "Should have inserted one row"); + is($rows, 1, "Should have inserted one row"); } -ok($sth->finish, "Testing closing of statement handle"); - ok($sth= $dbh->prepare("SELECT * FROM dbd_mysql_t35prepare WHERE id = ? OR id = ?"), "Testing prepare of query with placeholders"); @@ -83,18 +81,47 @@ note "RETREF " . scalar @$ret_ref . "\n"; ok(@{$ret_ref} == 4 , "\$ret_ref should contain four rows in result set"); +# Check that repeated $sth->execute + $sth->fetchall_arrayref work as expected +ok($sth = $dbh->prepare("SELECT * FROM dbd_mysql_t35prepare LIMIT 2")); +ok($sth->execute()); +is_deeply($sth->fetchall_arrayref(), [ [ 1, '1st first value' ], [ 2, '2nd second value' ] ]); +ok($sth->execute()); +is_deeply($sth->fetchall_arrayref(), [ [ 1, '1st first value' ], [ 2, '2nd second value' ] ]); +ok($sth->execute()); +is_deeply($sth->fetchall_arrayref(), [ [ 1, '1st first value' ], [ 2, '2nd second value' ] ]); + +# Check that repeated $sth->execute + $sth->fetchrow_arrayref work as expected +ok($sth = $dbh->prepare("SELECT * FROM dbd_mysql_t35prepare LIMIT 3")); +ok($sth->execute()); +is_deeply($sth->fetchrow_arrayref(), [ 1, '1st first value' ]); +is_deeply($sth->fetchrow_arrayref(), [ 2, '2nd second value' ]); +ok($sth->finish()); +ok($sth->execute()); +is_deeply($sth->fetchrow_arrayref(), [ 1, '1st first value' ]); +is_deeply($sth->fetchrow_arrayref(), [ 2, '2nd second value' ]); +ok($sth->finish()); + +# Check that repeated calls of $dbh->selectcol_arrayref, $dbh->prepare and $dbh->prepare_cached work as expected +is_deeply($dbh->selectcol_arrayref("SELECT id FROM dbd_mysql_t35prepare LIMIT 2"), [ 1, 2 ]); +is_deeply($dbh->selectcol_arrayref("SELECT id FROM dbd_mysql_t35prepare LIMIT 2"), [ 1, 2 ]); +is_deeply($dbh->selectcol_arrayref($dbh->prepare("SELECT id FROM dbd_mysql_t35prepare LIMIT 2")), [ 1, 2 ]); +is_deeply($dbh->selectcol_arrayref($dbh->prepare("SELECT id FROM dbd_mysql_t35prepare LIMIT 2")), [ 1, 2 ]); +is_deeply($dbh->selectcol_arrayref($dbh->prepare_cached("SELECT id FROM dbd_mysql_t35prepare LIMIT 2")), [ 1, 2 ]); +is_deeply($dbh->selectcol_arrayref($dbh->prepare_cached("SELECT id FROM dbd_mysql_t35prepare LIMIT 2")), [ 1, 2 ]); + ok($sth= $dbh->prepare("DROP TABLE IF EXISTS dbd_mysql_t35prepare"), "Testing prepare of dropping table"); ok($sth->execute(), "Executing drop table"); +} + # Bug #20153: Fetching all data from a statement handle does not mark it # as finished ok($sth= $dbh->prepare("SELECT 1"), "Prepare - Testing bug #20153"); ok($sth->execute(), "Execute - Testing bug #20153"); ok($sth->fetchrow_arrayref(), "Fetch - Testing bug #20153"); ok(!($sth->fetchrow_arrayref()),"Not Fetch - Testing bug #20153"); -ok($sth->finish); # Install a handler so that a warning about unfreed resources gets caught $SIG{__WARN__} = sub { die @_ }; diff -Nru libdbd-mariadb-perl-1.11/t/40bindparam2.t libdbd-mariadb-perl-1.21/t/40bindparam2.t --- libdbd-mariadb-perl-1.11/t/40bindparam2.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/40bindparam2.t 2019-02-27 11:04:38.000000000 +0000 @@ -10,7 +10,7 @@ my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0 }); -plan tests => 14; +plan tests => 13; SKIP: { skip 'SET @@auto_increment_offset needs MySQL >= 5.0.2', 2 unless $dbh->{mariadb_serverversion} >= 50002; @@ -41,8 +41,6 @@ ok ($sth->execute()); -ok ($sth->finish()); - ok ($rows = $dbh->selectall_arrayref("SELECT * FROM dbd_mysql_t40bindparam2")); ok !defined($rows->[0][1]); diff -Nru libdbd-mariadb-perl-1.11/t/40bindparam.t libdbd-mariadb-perl-1.21/t/40bindparam.t --- libdbd-mariadb-perl-1.11/t/40bindparam.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/40bindparam.t 2019-02-27 11:04:38.000000000 +0000 @@ -10,7 +10,7 @@ my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0 }); -plan tests => 41; +plan tests => 40; ok ($dbh->do("DROP TABLE IF EXISTS dbd_mysql_t40bindparam")); @@ -109,6 +109,4 @@ ok ($dbh->do("DROP TABLE dbd_mysql_t40bindparam")); -ok $sth->finish; - ok $dbh->disconnect; diff -Nru libdbd-mariadb-perl-1.11/t/40bit.t libdbd-mariadb-perl-1.21/t/40bit.t --- libdbd-mariadb-perl-1.11/t/40bit.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/40bit.t 2019-02-27 11:04:38.000000000 +0000 @@ -14,7 +14,7 @@ plan skip_all => "Servers < 5.0.8 do not support b'' syntax"; } -plan tests => 15; +plan tests => 14; ok $dbh->do("DROP TABLE IF EXISTS dbd_mysql_b1"), "Drop table if exists dbd_mysql_b1"; @@ -36,8 +36,6 @@ is $result->[1][0], 1010, "should be 1010"; is $result->[2][0], 101, "should be 101"; -ok ($sth->finish); - ok $dbh->do("DROP TABLE dbd_mysql_b1"), "Drop table dbd_mysql_b1"; ok $dbh->disconnect; diff -Nru libdbd-mariadb-perl-1.11/t/40blobs.t libdbd-mariadb-perl-1.21/t/40blobs.t --- libdbd-mariadb-perl-1.11/t/40blobs.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/40blobs.t 2019-02-27 11:04:38.000000000 +0000 @@ -24,7 +24,7 @@ my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0 }); -plan tests => 14; +plan tests => 13; my $size= 128; @@ -70,8 +70,6 @@ ShowBlob($blob), ShowBlob(defined($$row[1]) ? $$row[1] : ""); -ok ($sth->finish); - ok $dbh->do("DROP TABLE dbd_mysql_t40blobs"), "Drop table dbd_mysql_t40blobs"; ok $dbh->disconnect; diff -Nru libdbd-mariadb-perl-1.11/t/40nulls_prepare.t libdbd-mariadb-perl-1.21/t/40nulls_prepare.t --- libdbd-mariadb-perl-1.11/t/40nulls_prepare.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/40nulls_prepare.t 2019-02-27 11:04:38.000000000 +0000 @@ -60,9 +60,6 @@ ok($sth_lookup->execute(43), "Query for record of id = 43"); is_deeply($sth_lookup->fetchrow_arrayref(), [43, 2002, 20003, 200004]); -ok($sth_insert->finish()); -ok($sth_lookup->finish()); - ok $dbh->do("DROP TABLE dbd_mysql_t40nullsprepare"); ok($dbh->disconnect(), "Testing disconnect"); diff -Nru libdbd-mariadb-perl-1.11/t/40nulls.t libdbd-mariadb-perl-1.21/t/40nulls.t --- libdbd-mariadb-perl-1.11/t/40nulls.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/40nulls.t 2019-02-27 11:04:38.000000000 +0000 @@ -10,7 +10,7 @@ my ($dbh, $sth); $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0, AutoCommit => 0 }); -plan tests => 10; +plan tests => 9; ok $dbh->do("DROP TABLE IF EXISTS dbd_mysql_t40nulls"), "DROP TABLE IF EXISTS dbd_mysql_t40nulls"; @@ -34,8 +34,6 @@ ok defined($$aref[1]); -ok $sth->finish; - ok $dbh->do("DROP TABLE dbd_mysql_t40nulls"); ok $dbh->disconnect; diff -Nru libdbd-mariadb-perl-1.11/t/40numrows.t libdbd-mariadb-perl-1.21/t/40numrows.t --- libdbd-mariadb-perl-1.11/t/40numrows.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/40numrows.t 2019-02-27 11:04:38.000000000 +0000 @@ -10,51 +10,59 @@ my ($dbh, $sth, $aref); $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0, AutoCommit => 0 }); -plan tests => 31; +plan tests => 2*36 + 1; -ok $dbh->do("DROP TABLE IF EXISTS dbd_mysql_t40numrows"); +for my $mariadb_server_prepare (0, 1) { + +$dbh->{mariadb_server_prepare} = $mariadb_server_prepare; my $create= <do($create), "CREATE TABLE dbd_mysql_t40numrows"; +ok $dbh->do($create), "create table dbd_mysql_t40numrows"; ok $dbh->do("INSERT INTO dbd_mysql_t40numrows VALUES( 1, 'Alligator Descartes' )"), 'inserting first row'; ok ($sth = $dbh->prepare("SELECT * FROM dbd_mysql_t40numrows WHERE id = 1")); +is $sth->rows, -1, '$sth->rows prior execute is unknown (-1)'; + ok $sth->execute; -is $sth->rows, 1, '\$sth->rows should be 1'; +is $sth->rows, 1, '$sth->rows should be 1'; ok ($aref= $sth->fetchall_arrayref); is scalar @$aref, 1, 'Verified rows should be 1'; -ok $sth->finish; +is $sth->rows, 1, '$sth->rows still should be 1'; ok $dbh->do("INSERT INTO dbd_mysql_t40numrows VALUES( 2, 'Jochen Wiedmann' )"), 'inserting second row'; ok ($sth = $dbh->prepare("SELECT * FROM dbd_mysql_t40numrows WHERE id >= 1")); +is $sth->rows, -1, '$sth->rows prior execute is unknown (-1)'; + ok $sth->execute; -is $sth->rows, 2, '\$sth->rows should be 2'; +is $sth->rows, 2, '$sth->rows should be 2'; ok ($aref= $sth->fetchall_arrayref); is scalar @$aref, 2, 'Verified rows should be 2'; -ok $sth->finish; +is $sth->rows, 2, '$sth->rows still should be 2'; ok $dbh->do("INSERT INTO dbd_mysql_t40numrows VALUES(3, 'Tim Bunce')"), "inserting third row"; ok ($sth = $dbh->prepare("SELECT * FROM dbd_mysql_t40numrows WHERE id >= 2")); +is $sth->rows, -1, '$sth->rows prior execute is unknown (-1)'; + ok $sth->execute; is $sth->rows, 2, 'rows should be 2'; @@ -63,10 +71,12 @@ is scalar @$aref, 2, 'Verified rows should be 2'; -ok $sth->finish; +is $sth->rows, 2, 'rows still should be 2'; ok ($sth = $dbh->prepare("SELECT * FROM dbd_mysql_t40numrows")); +is $sth->rows, -1, '$sth->rows prior execute is unknown (-1)'; + ok $sth->execute; is $sth->rows, 3, 'rows should be 3'; @@ -75,8 +85,19 @@ is scalar @$aref, 3, 'Verified rows should be 3'; -ok $sth->finish; +is $sth->rows, 3, 'rows still should be 3'; + +my $sth = eval { $dbh->prepare("SYNTAX ERROR") }; +if ($sth) { + is $sth->rows, -1, '$sth->rows prior execute is unknown (-1)'; + ok !eval { $sth->execute() }, '$sth->execute for SYNTAX ERROR failed'; + is $sth->rows, -1, '$sth->rows for SYNTAX ERROR is unknown (-1)'; +} else { + pass '$dbh->prepare for SYNTAX ERROR failed' for 1..3; +} + +ok $dbh->do("DROP TEMPORARY TABLE dbd_mysql_t40numrows"), "drop table dbd_mysql_t40numrows"; -ok $dbh->do("DROP TABLE dbd_mysql_t40numrows"), "drop table dbd_mysql_t40numrows"; +} ok $dbh->disconnect; diff -Nru libdbd-mariadb-perl-1.11/t/40server_prepare_crash.t libdbd-mariadb-perl-1.21/t/40server_prepare_crash.t --- libdbd-mariadb-perl-1.11/t/40server_prepare_crash.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/40server_prepare_crash.t 2019-02-27 11:04:38.000000000 +0000 @@ -10,7 +10,7 @@ my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { PrintError => 0, RaiseError => 1, AutoCommit => 0, mariadb_server_prepare => 1, mariadb_server_prepare_disable_fallback => 1 }); -plan tests => 44; +plan tests => 43; my $sth; @@ -25,13 +25,13 @@ ok $sth->execute(4, "x" x 10000); ok $sth->execute(5, "x" x 100000); ok $sth->execute(6, "x" x 1000000); -ok $sth->finish(); ok $sth = $dbh->prepare("SELECT * FROM t WHERE i=? AND n=?"); ok $sth->bind_param(2, "x" x 1000000); ok $sth->bind_param(1, "abcx", 12); ok $sth->execute(); +ok $sth->finish(); ok $sth->bind_param(2, "a" x 1000000); ok $sth->bind_param(1, 1, 3); @@ -73,8 +73,6 @@ $test = map { $_ } 'hijk' x 10000000; # try to reuse of released memory ok $sth->fetchrow_arrayref(); -ok $sth->finish(); - ok $dbh->do("SELECT 1 FROM t WHERE i = ?" . (" OR i = ?" x 10000), {}, (1) x (10001)); # $sth2 is statement that cannot be executed as mysql server side prepared statement, so fallback must be allowed diff -Nru libdbd-mariadb-perl-1.11/t/40server_prepare.t libdbd-mariadb-perl-1.21/t/40server_prepare.t --- libdbd-mariadb-perl-1.11/t/40server_prepare.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/40server_prepare.t 2019-02-27 11:04:38.000000000 +0000 @@ -14,7 +14,7 @@ my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0, AutoCommit => 0 }); -plan tests => 31; +plan tests => 29; ok(defined $dbh, "connecting"); @@ -37,8 +37,6 @@ is_deeply($sth->fetchall_arrayref({}), [ { 'num' => '3' } ]); -ok ($sth->finish); - ok ($dbh->do(qq{DROP TABLE dbd_mysql_t40serverprepare1}), "cleaning up"); # @@ -85,7 +83,6 @@ my $sth4; ok($sth4 = $dbh->prepare("USE " . $dbh->quote_identifier($test_db)), 'USE is supported with mariadb_server_prepare_disable_fallback=0'); ok($sth4->execute()); -ok($sth4->finish()); ok ($dbh->do(qq{DROP TABLE t3}), "cleaning up"); diff -Nru libdbd-mariadb-perl-1.11/t/40sth_attr.t libdbd-mariadb-perl-1.21/t/40sth_attr.t --- libdbd-mariadb-perl-1.11/t/40sth_attr.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/40sth_attr.t 2019-02-27 11:04:38.000000000 +0000 @@ -3,6 +3,7 @@ use Test::More; use DBI; +use DBD::MariaDB; use vars qw($test_dsn $test_user $test_password); use lib 't', '.'; @@ -10,21 +11,117 @@ my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { PrintError => 0, RaiseError => 1 }); -plan tests => 11; +plan tests => 90; ok($dbh->do("CREATE TEMPORARY TABLE t(id INT)")); ok($dbh->do("INSERT INTO t(id) VALUES(1)")); -my $sth = $dbh->prepare("SELECT * FROM t"); -ok($sth->execute()); -ok($sth->fetchall_arrayref()); -is_deeply($sth->{NAME}, ["id"]); -ok($sth->finish()); +my $sth1 = $dbh->prepare("SELECT * FROM t"); +ok(!$sth1->{Active}); +ok($sth1->execute()); +ok($sth1->{Active}); +is_deeply($sth1->{NAME}, ["id"]); +is_deeply($sth1->fetchall_arrayref(), [ [ 1 ] ]); +ok(!$sth1->{Active}); +is_deeply($sth1->{mariadb_type}, [ DBD::MariaDB::TYPE_LONG ]); my $sth2 = $dbh->prepare("SELECT * FROM t", { mariadb_server_prepare => 1 }); +ok(!$sth2->{Active}); ok($sth2->execute()); -ok($sth2->fetchall_arrayref()); +ok($sth2->{Active}); is_deeply($sth2->{NAME}, ["id"]); -ok($sth2->finish()); +is_deeply($sth2->fetchall_arrayref(), [ [ 1 ] ]); +ok(!$sth2->{Active}); +is_deeply($sth2->{mariadb_type}, [ DBD::MariaDB::TYPE_LONG ]); + +ok($dbh->do("INSERT INTO t(id) VALUES(2)")); + +my $sth3 = $dbh->prepare("SELECT * FROM t"); +ok(!$sth3->{Active}); +ok($sth3->execute()); +ok($sth3->{Active}); +is_deeply($sth3->{NAME}, ["id"]); +is_deeply($sth3->fetchrow_arrayref(), [ 1 ]); +ok($sth3->{Active}); +is_deeply($sth3->{NAME}, ["id"]); +is_deeply($sth3->fetchrow_arrayref(), [ 2 ]); +ok(!$sth3->{Active}); +is_deeply($sth3->{NAME}, ["id"]); +is_deeply($sth3->{mariadb_type}, [ DBD::MariaDB::TYPE_LONG ]); + +my $sth4 = $dbh->prepare("SELECT * FROM t", { mariadb_server_prepare => 1 }); +ok(!$sth4->{Active}); +ok($sth4->execute()); +ok($sth4->{Active}); +is_deeply($sth4->{NAME}, ["id"]); +is_deeply($sth4->fetchrow_arrayref(), [ 1 ]); +ok($sth4->{Active}); +is_deeply($sth4->{NAME}, ["id"]); +is_deeply($sth4->fetchrow_arrayref(), [ 2 ]); +ok(!$sth4->{Active}); +is_deeply($sth4->{NAME}, ["id"]); +is_deeply($sth4->{mariadb_type}, [ DBD::MariaDB::TYPE_LONG ]); + +my $sth5 = $dbh->prepare("SELECT * FROM t"); +ok(!$sth5->{Active}); +ok($sth5->execute()); +ok($sth5->{Active}); +is_deeply($sth5->{NAME}, ["id"]); +is_deeply($sth5->fetchrow_arrayref(), [ 1 ]); +ok($sth5->{Active}); +is_deeply($sth5->{NAME}, ["id"]); +ok($sth5->finish); +ok(!$sth5->{Active}); +is_deeply($sth5->{NAME}, ["id"]); +is_deeply($sth5->{mariadb_type}, [ DBD::MariaDB::TYPE_LONG ]); + +my $sth6 = $dbh->prepare("SELECT * FROM t", { mariadb_server_prepare => 1 }); +ok(!$sth6->{Active}); +ok($sth6->execute()); +ok($sth6->{Active}); +is_deeply($sth6->{NAME}, ["id"]); +is_deeply($sth6->fetchrow_arrayref(), [ 1 ]); +ok($sth6->{Active}); +is_deeply($sth6->{NAME}, ["id"]); +ok($sth6->finish); +ok(!$sth6->{Active}); +is_deeply($sth6->{NAME}, ["id"]); +is_deeply($sth6->{mariadb_type}, [ DBD::MariaDB::TYPE_LONG ]); + +my $sth7 = $dbh->prepare("SELECT NULL as my_name LIMIT 0"); +ok(!$sth7->{Active}); +ok($sth7->execute()); +ok(!$sth7->{Active}); +is_deeply($sth7->{NAME}, ["my_name"]); +ok(!$sth7->fetchrow_arrayref()); +ok(!$sth7->{Active}); +is_deeply($sth7->{mariadb_type}, [ DBD::MariaDB::TYPE_NULL ]); + +my $sth8 = $dbh->prepare("SELECT NULL as my_name LIMIT 0"); +ok(!$sth8->{Active}); +ok($sth8->execute()); +ok(!$sth8->{Active}); +is_deeply($sth8->{NAME}, ["my_name"]); +ok(!$sth8->fetchrow_arrayref()); +ok(!$sth8->{Active}); +is_deeply($sth8->{mariadb_type}, [ DBD::MariaDB::TYPE_NULL ]); + +my $sth9 = $dbh->prepare("SELECT NULL as my_name LIMIT 0"); +ok(!$sth9->{Active}); +ok($sth9->execute()); +ok(!$sth9->{Active}); +is_deeply($sth9->{NAME}, ["my_name"]); +is_deeply($sth9->fetchall_arrayref(), []); +ok(!$sth9->{Active}); +is_deeply($sth9->{mariadb_type}, [ DBD::MariaDB::TYPE_NULL ]); + +my $sth10 = $dbh->prepare("SELECT NULL as my_name LIMIT 0"); +ok(!$sth10->{Active}); +ok($sth10->execute()); +ok(!$sth10->{Active}); +is_deeply($sth10->{NAME}, ["my_name"]); +is_deeply($sth10->fetchall_arrayref(), []); +ok(!$sth10->{Active}); +is_deeply($sth10->{mariadb_type}, [ DBD::MariaDB::TYPE_NULL ]); ok($dbh->disconnect()); diff -Nru libdbd-mariadb-perl-1.11/t/40types.t libdbd-mariadb-perl-1.21/t/40types.t --- libdbd-mariadb-perl-1.11/t/40types.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/40types.t 2019-02-27 11:04:38.000000000 +0000 @@ -15,7 +15,7 @@ my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0, AutoCommit => 0 }); -plan tests => 78*2; +plan tests => 70*2; for my $mariadb_server_prepare (0, 1) { $dbh->{mariadb_server_prepare} = $mariadb_server_prepare; @@ -44,7 +44,6 @@ is_deeply($sth->{TYPE}, [ DBI::SQL_INTEGER ], "checking column type"); is_deeply($sth->{mariadb_type}, [ DBD::MariaDB::TYPE_LONG ], "checking mariadb column type"); -ok($sth->finish); ok($dbh->do(qq{DROP TABLE t_dbd_40types}), "cleaning up"); ok($dbh->do(qq{CREATE TABLE t_dbd_40types (num VARCHAR(10))}), "creating table"); @@ -69,11 +68,10 @@ is_deeply($sth->{TYPE}, [ DBI::SQL_VARCHAR ], "checking column type"); cmp_deeply($sth->{mariadb_type}, [ any(DBD::MariaDB::TYPE_VARCHAR, DBD::MariaDB::TYPE_VAR_STRING) ], "checking mariadb column type"); -ok($sth->finish); ok($dbh->do(qq{DROP TABLE t_dbd_40types}), "cleaning up"); SKIP: { -skip "Clients < 5.0.3 do not support new decimal type from servers >= 5.0.3", 6 if $dbh->{mariadb_serverversion} >= 50003 and $dbh->{mariadb_clientversion} < 50003; +skip "Clients < 5.0.3 do not support new decimal type from servers >= 5.0.3", 5 if $dbh->{mariadb_serverversion} >= 50003 and $dbh->{mariadb_clientversion} < 50003; ok($dbh->do(qq{CREATE TABLE t_dbd_40types (d DECIMAL(5,2))}), "creating table"); @@ -83,7 +81,6 @@ is_deeply($sth->{TYPE}, [ DBI::SQL_DECIMAL ], "checking column type"); cmp_deeply($sth->{mariadb_type}, [ any(DBD::MariaDB::TYPE_DECIMAL, DBD::MariaDB::TYPE_NEWDECIMAL) ], "checking mariadb column type"); -ok($sth->finish); ok($dbh->do(qq{DROP TABLE t_dbd_40types}), "cleaning up"); } @@ -96,10 +93,8 @@ $sth= $dbh->prepare("INSERT INTO t_dbd_40types VALUES (?)"); ok($sth->bind_param(1, 2.1, DBI::SQL_DOUBLE), "binding parameter"); ok($sth->execute(), "inserting data"); -ok($sth->finish); ok($sth->bind_param(1, -1, DBI::SQL_DOUBLE), "binding parameter"); ok($sth->execute(), "inserting data"); -ok($sth->finish); my $ret = $dbh->selectall_arrayref("SELECT * FROM t_dbd_40types"); cmp_deeply($ret, [ [num(2.1, 0.00001)], [num(-1, 0.00001)] ]); @@ -128,7 +123,6 @@ is_deeply($sth->{TYPE}, [ DBI::SQL_DOUBLE ], "checking column type"); is_deeply($sth->{mariadb_type}, [ DBD::MariaDB::TYPE_DOUBLE ], "checking mariadb column type"); -ok($sth->finish); ok($dbh->do(qq{DROP TABLE t_dbd_40types}), "cleaning up"); # @@ -164,7 +158,6 @@ is_deeply($sth->{TYPE}, [ DBI::SQL_INTEGER ], "checking column type"); is_deeply($sth->{mariadb_type}, [ DBD::MariaDB::TYPE_LONG ], "checking mariadb column type"); -ok($sth->finish); ok($dbh->do(qq{DROP TABLE t_dbd_40types}), "cleaning up"); # https://github.com/gooddata/DBD-MariaDB/issues/109: Check DBI::SQL_BIGINT type @@ -173,7 +166,6 @@ ok($sth->execute()); is_deeply($sth->{TYPE}, [ DBI::SQL_BIGINT ], "checking column type of bigint"); is_deeply($sth->{mariadb_type}, [ DBD::MariaDB::TYPE_LONGLONG ], "checking mariadb column type of bigint"); -ok($sth->finish); ok($dbh->do(qq{DROP TABLE t_dbd_40types}), "cleaning up"); } diff -Nru libdbd-mariadb-perl-1.11/t/41bindparam.t libdbd-mariadb-perl-1.21/t/41bindparam.t --- libdbd-mariadb-perl-1.11/t/41bindparam.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/41bindparam.t 2019-02-27 11:04:38.000000000 +0000 @@ -11,7 +11,7 @@ my ($dbh, $sth); $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0, AutoCommit => 0 }); -plan tests => 11; +plan tests => 10; my ($rows, $errstr, $ret_ref); ok $dbh->do("drop table if exists dbd_mysql_41bindparam"), "drop table dbd_mysql_41bindparam"; @@ -32,6 +32,4 @@ ok $sth->execute(); -ok $sth->finish; - ok $dbh->disconnect; diff -Nru libdbd-mariadb-perl-1.11/t/41blobs_prepare.t libdbd-mariadb-perl-1.21/t/41blobs_prepare.t --- libdbd-mariadb-perl-1.11/t/41blobs_prepare.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/41blobs_prepare.t 2019-02-27 11:04:38.000000000 +0000 @@ -12,7 +12,7 @@ my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0 }); -plan tests => 25; +plan tests => 21; my @chars = grep !/[0O1Iil]/, 0..9, 'A'..'Z', 'a'..'z'; my $blob1= join '', map { $chars[rand @chars] } 0 .. 10000; @@ -50,8 +50,6 @@ ok $sth->execute(1, $blob1), "inserting \$blob1"; -ok $sth->finish; - ok ($sth= $dbh->prepare("SELECT * FROM dbd_mysql_41blobs_prepare WHERE id = 1")); ok $sth->execute, "select from dbd_mysql_41blobs_prepare"; @@ -64,14 +62,10 @@ cmp_ok $$row[1], 'eq', $blob1, ShowBlob($blob1); -ok $sth->finish; - ok ($sth= $dbh->prepare("UPDATE dbd_mysql_41blobs_prepare SET name = ? WHERE id = 1")); ok $sth->execute($blob2), 'inserting $blob2'; -ok ($sth->finish); - ok ($sth= $dbh->prepare("SELECT * FROM dbd_mysql_41blobs_prepare WHERE id = 1")); ok ($sth->execute); @@ -84,8 +78,6 @@ cmp_ok $$row[1], 'eq', $blob2, ShowBlob($blob2); -ok ($sth->finish); - ok $dbh->do("DROP TABLE dbd_mysql_41blobs_prepare"), "drop dbd_mysql_41blobs_prepare"; ok $dbh->disconnect; diff -Nru libdbd-mariadb-perl-1.11/t/41int_min_max.t libdbd-mariadb-perl-1.21/t/41int_min_max.t --- libdbd-mariadb-perl-1.11/t/41int_min_max.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/41int_min_max.t 2019-02-27 11:04:38.000000000 +0000 @@ -17,7 +17,7 @@ "SKIP TEST: You must have MySQL version 5.0.2 and greater for this test to run"; } # nostrict tests + strict tests + init/tear down commands -plan tests => (19*8 + 19*8 + 4) * 2; +plan tests => (19*8 + 19*8 + 3) * 2; my $table = 'dbd_mysql_t41minmax'; # name of the table we will be using my $mode; # 'strict' or 'nostrict' corresponds to strict SQL mode @@ -26,9 +26,8 @@ my ($perl_type, $mariadb_type, $min, $max) = @_; # Create the table - ok($dbh->do(qq{DROP TABLE IF EXISTS $table}), "removing $table"); ok($dbh->do(qq{ - CREATE TABLE `$table` ( + CREATE TEMPORARY TABLE `$table` ( `id` int not null auto_increment, `val` $mariadb_type, primary key (id) @@ -38,7 +37,7 @@ my ($store, $retrieve); # statements my $read_value; # retrieved value ok($store = $dbh->prepare("INSERT INTO $table (val) VALUES (?)")); - ok($retrieve = $dbh->prepare("SELECT val from $table where id=(SELECT MAX(id) FROM $table)")); + ok($retrieve = $dbh->prepare("SELECT val from $table ORDER BY id DESC LIMIT 1")); ######################################## # Insert allowed min value @@ -107,6 +106,8 @@ ($read_value) = $retrieve->fetchrow_array(); cmp_ok($read_value, 'eq', $max, "retrieved maximal value for type $mariadb_type, mode=$mode"); }; + + ok($dbh->do(qq{DROP TEMPORARY TABLE `$table`}), "removing $table"); } $dbh->disconnect; @@ -141,7 +142,5 @@ test_int_type(DBI::SQL_BIGINT, 'bigint signed', -2**63, 2**63-1); test_int_type(DBI::SQL_BIGINT, 'bigint unsigned', 0, 2**64-1); -ok ($dbh->do("DROP TABLE $table")); - ok $dbh->disconnect; } diff -Nru libdbd-mariadb-perl-1.11/t/42bindparam.t libdbd-mariadb-perl-1.21/t/42bindparam.t --- libdbd-mariadb-perl-1.11/t/42bindparam.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/42bindparam.t 2019-02-27 11:04:38.000000000 +0000 @@ -10,7 +10,7 @@ my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0, AutoCommit => 0 }); -plan tests => 12; +plan tests => 11; ok $dbh->do("drop table if exists dbd_mysql_t42bindparams"); @@ -39,6 +39,4 @@ ok $dbh->do("DROP TABLE dbd_mysql_t42bindparams"); -ok $sth->finish; - ok $dbh->disconnect; diff -Nru libdbd-mariadb-perl-1.11/t/44call_placeholder.t libdbd-mariadb-perl-1.21/t/44call_placeholder.t --- libdbd-mariadb-perl-1.11/t/44call_placeholder.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/44call_placeholder.t 2019-02-27 11:04:38.000000000 +0000 @@ -14,7 +14,7 @@ plan skip_all => $dbh->errstr() if !CheckRoutinePerms($dbh); -plan tests => 13; +plan tests => 12; ok $dbh->do('DROP PROCEDURE IF EXISTS t44_call_placeholder'); @@ -28,7 +28,6 @@ ok my $sth = $dbh->prepare('CALL t44_call_placeholder(?)'); ok $sth->execute(10); is_deeply $sth->fetchall_arrayref(), [ [5, 10] ]; -ok $sth->finish(); ok $dbh->do('DROP PROCEDURE t44_call_placeholder'); diff -Nru libdbd-mariadb-perl-1.11/t/44limit_placeholder.t libdbd-mariadb-perl-1.21/t/44limit_placeholder.t --- libdbd-mariadb-perl-1.11/t/44limit_placeholder.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/44limit_placeholder.t 2019-02-27 11:04:38.000000000 +0000 @@ -10,7 +10,7 @@ my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0, AutoCommit => 0, mariadb_server_prepare => 1 }); -plan tests => 38; +plan tests => 32; ok $dbh->do('CREATE TEMPORARY TABLE t(id INT)'); ok $dbh->do('CREATE TEMPORARY TABLE t2(id INT)'); @@ -20,7 +20,6 @@ ok my $sth = $dbh->prepare('SELECT id FROM t ORDER BY id LIMIT ?'); ok $sth->execute(1); is_deeply $sth->fetchall_arrayref(), [ [10] ]; -ok $sth->finish(); ok $dbh->do('INSERT INTO t2(id) SELECT id FROM t ORDER BY id LIMIT ?', undef, 1); is_deeply $dbh->selectall_arrayref('SELECT id FROM t2'), [ [10] ]; @@ -29,7 +28,6 @@ ok $sth = $dbh->prepare('SELECT id FROM t ORDER BY id LIMIT ?,?'); ok $sth->execute(0, 1); is_deeply $sth->fetchall_arrayref(), [ [10] ]; -ok $sth->finish(); ok $dbh->do('INSERT INTO t2(id) SELECT id FROM t ORDER BY id LIMIT ?,?', undef, 0, 1); is_deeply $dbh->selectall_arrayref('SELECT id FROM t2'), [ [10] ]; @@ -38,7 +36,6 @@ ok $sth = $dbh->prepare('SELECT id FROM t ORDER BY id LIMIT ? OFFSET ?'); ok $sth->execute(1, 0); is_deeply $sth->fetchall_arrayref(), [ [10] ]; -ok $sth->finish(); ok $dbh->do('INSERT INTO t2(id) SELECT id FROM t ORDER BY id LIMIT ? OFFSET ?', undef, 1, 0); is_deeply $dbh->selectall_arrayref('SELECT id FROM t2'), [ [10] ]; @@ -47,16 +44,13 @@ ok $sth = $dbh->prepare('select id from t order by id LiMIt ?,?'); ok $sth->execute(0, 1); is_deeply $sth->fetchall_arrayref(), [ [10] ]; -ok $sth->finish(); ok $sth = $dbh->prepare('select id from t order by id LiMIt 0 ,?'); ok $sth->execute(1); is_deeply $sth->fetchall_arrayref(), [ [10] ]; -ok $sth->finish(); ok $sth = $dbh->prepare('select id from t order by id lImIt 1 OFFSET ?'); ok $sth->execute(0); is_deeply $sth->fetchall_arrayref(), [ [10] ]; -ok $sth->finish(); ok $dbh->disconnect(); diff -Nru libdbd-mariadb-perl-1.11/t/45bind_no_backslash_escapes.t libdbd-mariadb-perl-1.21/t/45bind_no_backslash_escapes.t --- libdbd-mariadb-perl-1.11/t/45bind_no_backslash_escapes.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/45bind_no_backslash_escapes.t 2019-02-27 11:04:38.000000000 +0000 @@ -22,7 +22,7 @@ $id2_quoted_no_backslash = q(X'737472696E675C737472696E6722737472696E6727737472696E67'); } -plan tests => 24; +plan tests => 20; ok $dbh->do('CREATE TEMPORARY TABLE t(id VARCHAR(255), value TEXT)'); ok $dbh->do('INSERT INTO t(id, value) VALUES(?, ?)', undef, $id1, 'value1'); @@ -41,12 +41,10 @@ ok $sth->bind_param(1, $id1); ok $sth->execute(); is_deeply $sth->fetchall_arrayref(), [ [ $id1, 'value1' ] ]; - ok $sth->finish(); ok $sth->bind_param(1, $id2); ok $sth->execute(); is_deeply $sth->fetchall_arrayref(), [ [ $id2, 'value2' ] ]; - ok $sth->finish(); } diff -Nru libdbd-mariadb-perl-1.11/t/50chopblanks.t libdbd-mariadb-perl-1.21/t/50chopblanks.t --- libdbd-mariadb-perl-1.11/t/50chopblanks.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/50chopblanks.t 2019-02-27 11:04:38.000000000 +0000 @@ -12,7 +12,7 @@ { RaiseError => 1, PrintError => 0 }); $dbh->disconnect; -plan tests => (8 + ((5 + 8 + 8) * 4)) * 2; +plan tests => (6 + ((5 + 8 + 8) * 4)) * 2; for my $mariadb_server_prepare (0, 1) { $dbh = DBI->connect("$test_dsn;mariadb_server_prepare=$mariadb_server_prepare;mariadb_server_prepare_disable_fallback=1", $test_user, $test_password, @@ -76,8 +76,6 @@ } } -ok $sth->finish; -ok $sth2->finish; ok $dbh->do("DROP TABLE dbd_mysql_t50chopblanks"), "drop dbd_mysql_t50chopblanks"; ok $dbh->disconnect; } diff -Nru libdbd-mariadb-perl-1.11/t/50commit.t libdbd-mariadb-perl-1.21/t/50commit.t --- libdbd-mariadb-perl-1.11/t/50commit.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/50commit.t 2019-02-27 11:04:38.000000000 +0000 @@ -39,9 +39,11 @@ my $engines = $dbh->selectall_hashref('SHOW ENGINES', 'Engine'); my $have_innodb = exists $engines->{InnoDB} && $engines->{InnoDB}->{Support} ne 'NO'; +my $have_myisam = exists $engines->{MyISAM} && $engines->{MyISAM}->{Support} ne 'NO'; + +plan tests => 1 + ($have_myisam ? 12 : 0) + ($have_innodb ? 22 : 0); if ($have_innodb) { - plan tests => 22; ok $dbh->do("DROP TABLE IF EXISTS dbd_mysql_t50commit"), "drop table if exists dbd_mysql_t50commit"; my $create =<do("DROP TABLE dbd_mysql_t50commit"); } -else { - plan tests => 13; + +if ($have_myisam) { ok $dbh->do("DROP TABLE IF EXISTS dbd_mysql_t50commit"), "drop table if exists dbd_mysql_t50commit"; my $create =<do($create), 'create dbd_mysql_t50commit'; @@ -154,5 +156,7 @@ ok $got_warning, "Should be warning defined upon rollback of non-trx table"; ok $dbh->do("DROP TABLE dbd_mysql_t50commit"); - ok $dbh->disconnect(); + } + +ok $dbh->disconnect(); diff -Nru libdbd-mariadb-perl-1.11/t/51bind_type_guessing.t libdbd-mariadb-perl-1.21/t/51bind_type_guessing.t --- libdbd-mariadb-perl-1.11/t/51bind_type_guessing.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/51bind_type_guessing.t 2019-02-27 11:04:38.000000000 +0000 @@ -76,6 +76,7 @@ ok $sth3= $dbh->prepare("select * from dbd_mysql_t51bind_type_guessing limit ?"); ok $rows= $sth3->execute(1); +$sth3->finish(); ok $rows= $sth3->execute(' 1'); $sth3->finish(); diff -Nru libdbd-mariadb-perl-1.11/t/52comment.t libdbd-mariadb-perl-1.21/t/52comment.t --- libdbd-mariadb-perl-1.11/t/52comment.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/52comment.t 2019-02-27 11:04:38.000000000 +0000 @@ -34,7 +34,6 @@ my $rows; ok $rows= $sth->execute('1'); cmp_ok $rows, '==', 1; -$sth->finish(); $statement= <execute('1'); cmp_ok $rows, '==', 1; -$sth->finish(); my $retrow; diff -Nru libdbd-mariadb-perl-1.11/t/55unicode.t libdbd-mariadb-perl-1.21/t/55unicode.t --- libdbd-mariadb-perl-1.11/t/55unicode.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/55unicode.t 2019-02-27 11:04:38.000000000 +0000 @@ -30,7 +30,6 @@ $sth->execute(); my $fetch = $dbh->selectrow_array("SELECT s FROM t"); is($fetch, $ins, "test $ins without bind"); - $sth->finish(); $dbh->do("DROP TEMPORARY TABLE t"); } SKIP: { @@ -40,7 +39,6 @@ $sth->execute($ins); my $fetch = $dbh->selectrow_array("SELECT s FROM t"); is($fetch, $ins, "test $ins with bind"); - $sth->finish(); $dbh->do("DROP TEMPORARY TABLE t"); } } diff -Nru libdbd-mariadb-perl-1.11/t/55utf8mb4.t libdbd-mariadb-perl-1.21/t/55utf8mb4.t --- libdbd-mariadb-perl-1.11/t/55utf8mb4.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/55utf8mb4.t 2019-02-27 11:04:38.000000000 +0000 @@ -24,7 +24,6 @@ ok $sth->execute; ok(my $ref = $sth->fetchrow_arrayref, 'fetch row'); -ok($sth->finish, 'close sth'); cmp_ok $ref->[0], 'eq', "😈", 'test U+1F608'; cmp_ok $ref->[1], 'eq', "F09F9888"; diff -Nru libdbd-mariadb-perl-1.11/t/55utf8.t libdbd-mariadb-perl-1.21/t/55utf8.t --- libdbd-mariadb-perl-1.11/t/55utf8.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/55utf8.t 2019-02-27 11:04:38.000000000 +0000 @@ -16,7 +16,7 @@ my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0, AutoCommit => 0 }); -plan tests => 42 * 2; +plan tests => 40 * 2; for my $mariadb_server_prepare (0, 1) { $dbh= DBI->connect("$test_dsn;mariadb_server_prepare=$mariadb_server_prepare;mariadb_server_prepare_disable_fallback=1", $test_user, $test_password, @@ -76,11 +76,10 @@ ok $sth->bind_param(6, $unicode_str); ok $sth->bind_param(7, $unicode_str2); ok $sth->execute() or die("Execute failed: ".$DBI::errstr); -ok $sth->finish; cmp_ok($dbh->{mariadb_warning_count}, '==', 1, 'got warning for INSERT') or do { diag("SHOW WARNINGS:"); diag($_->[2]) foreach $dbh->selectall_array("SHOW WARNINGS", { mariadb_server_prepare => 0 }); }; my (undef, undef, $warning) = $dbh->selectrow_array("SHOW WARNINGS", { mariadb_server_prepare => 0 }); -like($warning, qr/^(?:Incorrect string value: '\\xC4\\x80dam'|Data truncated) for column 'ascii' at row 1$/, 'warning is correct'); +like($warning, qr/^(?:Incorrect string value: '\\xC4\\x80dam'|Data truncated) for column (?:'ascii'|`.*`\.`.*`\.`ascii`) at row 1$/, 'warning is correct'); # AsBinary() is deprecated as of MySQL 5.7.6, use ST_AsBinary() instead my $asbinary = $dbh->{mariadb_serverversion} >= 50706 ? 'ST_AsBinary' : 'AsBinary'; @@ -105,8 +104,6 @@ cmp_ok $ref->[1], 'eq', $blob, "compare $ref->[1] eq $blob"; -ok $sth->finish; - my $prev_charset = $dbh->selectrow_array('SELECT @@character_set_results'); ok $dbh->do("SET character_set_results='latin1'"), "SET character_set_results='latin1'"; $ref = $dbh->selectrow_arrayref($query); diff -Nru libdbd-mariadb-perl-1.11/t/56connattr.t libdbd-mariadb-perl-1.21/t/56connattr.t --- libdbd-mariadb-perl-1.11/t/56connattr.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/56connattr.t 2019-02-27 11:04:38.000000000 +0000 @@ -26,8 +26,9 @@ } if (not eval { $dbh->do("select * from performance_schema.session_connect_attrs where processlist_id=connection_id()") }) { + my $err = $dbh->errstr || 'no permission on performance_schema tables'; $dbh->disconnect(); - plan skip_all => "no permission on performance_schema tables"; + plan skip_all => $err; } $dbh->disconnect(); diff -Nru libdbd-mariadb-perl-1.11/t/60leaks.t libdbd-mariadb-perl-1.21/t/60leaks.t --- libdbd-mariadb-perl-1.11/t/60leaks.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/60leaks.t 2019-02-27 11:04:38.000000000 +0000 @@ -303,7 +303,6 @@ $sth->execute(); my $row; while ($row = $sth->fetchrow_arrayref()) { } - $sth->finish(); } if ($i % 100 == 99) { @@ -344,7 +343,6 @@ $sth->execute(); my $row; while ($row = $sth->fetchrow_hashref()) { } - $sth->finish(); } if ($i % 100 == 99) { diff -Nru libdbd-mariadb-perl-1.11/t/65types.t libdbd-mariadb-perl-1.21/t/65types.t --- libdbd-mariadb-perl-1.11/t/65types.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/65types.t 2019-02-27 11:04:38.000000000 +0000 @@ -9,7 +9,7 @@ my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0, AutoCommit => 0 }); -plan tests => 19; +plan tests => 18; ok $dbh->do("drop table if exists dbd_mysql_65types"); @@ -51,8 +51,6 @@ ok $sth->execute(); -ok $sth->finish; - ok $dbh->do("DROP TABLE dbd_mysql_65types"); ok $dbh->disconnect; diff -Nru libdbd-mariadb-perl-1.11/t/75supported_sql.t libdbd-mariadb-perl-1.21/t/75supported_sql.t --- libdbd-mariadb-perl-1.11/t/75supported_sql.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/75supported_sql.t 2019-02-27 11:04:38.000000000 +0000 @@ -12,7 +12,7 @@ my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0 }); -plan tests => 12; +plan tests => 11; ok $dbh->do("DROP TABLE IF EXISTS dbd_mysql_t75supported"); @@ -34,8 +34,6 @@ cmp_ok $row->[0], 'eq', 'dbd_mysql_t75supported', "\$row->[0] eq dbd_mysql_t75supported"; -ok $sth->finish; - ok $dbh->do("DROP TABLE dbd_mysql_t75supported"), "drop dbd_mysql_t75supported"; ok $dbh->do("CREATE TABLE dbd_mysql_t75supported (a int)"), "creating dbd_mysql_t75supported again with 1 col"; diff -Nru libdbd-mariadb-perl-1.11/t/76multi_statement.t libdbd-mariadb-perl-1.21/t/76multi_statement.t --- libdbd-mariadb-perl-1.11/t/76multi_statement.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/76multi_statement.t 2019-02-27 11:04:38.000000000 +0000 @@ -3,6 +3,7 @@ use Test::More; use DBI; +use DBD::MariaDB; use lib 't', '.'; require 'lib.pl'; $|= 1; @@ -13,15 +14,7 @@ { RaiseError => 1, PrintError => 0, AutoCommit => 0, mariadb_multi_statements => 1 }); -if ($dbh->{mariadb_serverversion} < 50025 or ($dbh->{mariadb_serverversion} >= 50100 and $dbh->{mariadb_serverversion} < 50112)) { - plan skip_all => "Server has deadlock bug 16581"; -} - -if ($dbh->{mariadb_clientversion} < 50025 or ($dbh->{mariadb_clientversion} >= 50100 and $dbh->{mariadb_clientversion} < 50112)) { - plan skip_all => "Client has multiple-result-set detection deadlock bug 15752"; -} - -plan tests => 36; +plan tests => 77; ok (defined $dbh, "Connected to database with multi statement support"); @@ -40,7 +33,8 @@ # Check that more_results works for non-SELECT results too my $sth; - ok($sth = $dbh->prepare("UPDATE dbd_mysql_t76multi SET a=5 WHERE a=1; UPDATE dbd_mysql_t76multi SET a='6-' WHERE a<4")); + ok($sth = $dbh->prepare("UPDATE dbd_mysql_t76multi SET a=5 WHERE a=1; UPDATE dbd_mysql_t76multi SET a='6suffix' WHERE a<4")); + is($sth->rows, -1); ok($sth->execute(), "Execute updates"); is($sth->rows, 1, "First update affected 1 row"); is($sth->{mariadb_warning_count}, 0, "First update had no warnings"); @@ -49,7 +43,6 @@ is($sth->rows, 2, "Second update affected 2 rows"); is($sth->{mariadb_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"); @@ -79,6 +72,57 @@ is($sth->last_insert_id(), 2); is($dbh->last_insert_id(undef, undef, undef, undef), 2); ok(not $sth->more_results()); + + # Check that $dbh->last_insert_id works after $dbh->do with multi statements + ok($dbh->do("INSERT INTO dbd_mysql_t76multi2 VALUES(3); INSERT INTO dbd_mysql_t76multi2 VALUES(4);")); + is($dbh->last_insert_id(undef, undef, undef, undef), 4, '$dbh->last_insert_id is correct after $dbh->do with multi statements'); + + # Check that $dbh->last_insert_id works after prepare, execute and finish but without more_results + ok($sth = $dbh->prepare("INSERT INTO dbd_mysql_t76multi2 VALUES(5); INSERT INTO dbd_mysql_t76multi2 VALUES(6);")); + ok($sth->execute()); + ok($sth->finish()); + is($dbh->last_insert_id(undef, undef, undef, undef), 6, '$dbh->last_insert_id is correct after multi statement prepare, execute and finish'); + + # Check that $dbh->last_insert_id works after prepare and execute, but without more_results; after preparing new statement + ok($sth = $dbh->prepare("INSERT INTO dbd_mysql_t76multi2 VALUES(7); INSERT INTO dbd_mysql_t76multi2 VALUES(8);")); + ok($sth->execute()); + ok($sth = $dbh->prepare("SELECT 1")); + is($dbh->last_insert_id(undef, undef, undef, undef), 8, '$dbh->last_insert_id is correct after multi statement prepare and execute without finish followed by new prepare'); + + # Check that $dbh->last_insert_id works after prepare and execute, but without more_results; after calling $dbh->do which do not modify last_insert_id + ok($sth = $dbh->prepare("INSERT INTO dbd_mysql_t76multi2 VALUES(9); INSERT INTO dbd_mysql_t76multi2 VALUES(10);")); + ok($sth->execute()); + ok($dbh->do("SELECT 1")); + is($dbh->last_insert_id(undef, undef, undef, undef), 10, '$dbh->last_insert_id is correct after multi statement prepare and execute without finish followed by $dbh->do'); ok($sth->finish()); + # Check that statement attributes are correct after calling more_results + ok($dbh->do("CREATE TEMPORARY TABLE dbd_mysql_t76multi3 (name_id1 INT, name_id2 INT)")); + ok($sth = $dbh->prepare("SELECT name_id1 FROM dbd_mysql_t76multi3; INSERT INTO dbd_mysql_t76multi2 VALUES(11); SELECT name_id1, name_id2 FROM dbd_mysql_t76multi3; SYNTAX ERROR")); + is($sth->rows, -1); + ok($sth->execute()); + is($sth->{NUM_OF_FIELDS}, 1); + is($sth->{NUM_OF_PARAMS}, 0); + is($sth->rows, 0); + is_deeply($sth->{NAME}, [ 'name_id1' ]); + is_deeply($sth->{mariadb_type}, [ DBD::MariaDB::TYPE_LONG ]); + ok($sth->more_results()); + is($sth->{NUM_OF_FIELDS}, 0); + is($sth->{NUM_OF_PARAMS}, 0); + is($sth->rows, 1); + ok(!eval { $sth->{NAME} }); + ok(!eval { $sth->{mariadb_type} }); + ok($sth->more_results()); + is($sth->{NUM_OF_FIELDS}, 2); + is($sth->{NUM_OF_PARAMS}, 0); + is($sth->rows, 0); + is_deeply($sth->{NAME}, [ 'name_id1', 'name_id2' ]); + is_deeply($sth->{mariadb_type}, [ DBD::MariaDB::TYPE_LONG, DBD::MariaDB::TYPE_LONG ]); + ok(!eval { $sth->more_results() }); + is($sth->{NUM_OF_FIELDS}, 0); + is($sth->{NUM_OF_PARAMS}, 0); + ok(!eval { $sth->{NAME} }); + ok(!eval { $sth->{mariadb_type} }); + is($sth->rows, -1); + $dbh->disconnect(); diff -Nru libdbd-mariadb-perl-1.11/t/80procs.t libdbd-mariadb-perl-1.21/t/80procs.t --- libdbd-mariadb-perl-1.11/t/80procs.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/80procs.t 2019-02-27 11:04:38.000000000 +0000 @@ -120,12 +120,12 @@ is @$resultset, 3, "3 Rows in resultset"; -ok $sth->more_results(); +is $sth->more_results(), 1, "each CALL returns a result to indicate the call status"; -is $sth->{NUM_OF_FIELDS}, 0, "NUM_OF_FIELDS == 0"; + +is $sth->{NUM_OF_FIELDS}, 0, "NUM_OF_FIELDS == 0"; -local $SIG{__WARN__} = sub { die @_ }; +ok !$sth->more_results(); -ok $sth->finish; +local $SIG{__WARN__} = sub { die @_ }; ok $dbh->disconnect(); diff -Nru libdbd-mariadb-perl-1.11/t/81procs.t libdbd-mariadb-perl-1.21/t/81procs.t --- libdbd-mariadb-perl-1.11/t/81procs.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/81procs.t 2019-02-27 11:04:38.000000000 +0000 @@ -25,7 +25,7 @@ $dbh->errstr(); } -plan tests => 32; +plan tests => 31; $dbh->disconnect(); @@ -128,6 +128,4 @@ local $SIG{__WARN__} = sub { die @_ }; -ok $sth->finish; - ok $dbh->disconnect(); diff -Nru libdbd-mariadb-perl-1.11/t/85init_command.t libdbd-mariadb-perl-1.21/t/85init_command.t --- libdbd-mariadb-perl-1.11/t/85init_command.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/85init_command.t 2019-02-27 11:04:38.000000000 +0000 @@ -27,7 +27,5 @@ is($fetchrow[1],'7','session variable is 7'); -$sth->finish(); - $dbh->disconnect(); diff -Nru libdbd-mariadb-perl-1.11/t/87async.t libdbd-mariadb-perl-1.21/t/87async.t --- libdbd-mariadb-perl-1.11/t/87async.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/87async.t 2019-02-27 11:04:38.000000000 +0000 @@ -16,7 +16,7 @@ if ($dbh->{mariadb_serverversion} < 50012) { plan skip_all => "Servers < 5.0.12 do not support SLEEP()"; } -plan tests => 92; +plan tests => 137; is $dbh->get_info($GetInfoType{'SQL_ASYNC_MODE'}), 2; # statement-level async is $dbh->get_info($GetInfoType{'SQL_MAX_ASYNC_CONCURRENT_STATEMENTS'}), 1; @@ -93,23 +93,31 @@ is $c, 2; $sth = $dbh->prepare('SELECT SLEEP(2)'); +ok !$sth->{Active}; ok !defined($sth->mariadb_async_ready); $start = Time::HiRes::gettimeofday(); ok $sth->execute; $end = Time::HiRes::gettimeofday(); cmp_ok(($end - $start), '>=', 1.9); +ok $sth->{Active}; +ok $sth->finish; +ok !$sth->{Active}; $sth = $dbh->prepare('SELECT SLEEP(2)', { mariadb_async => 1 }); +ok !$sth->{Active}; ok !defined($sth->mariadb_async_ready); $start = Time::HiRes::gettimeofday(); ok $sth->execute; ok defined($sth->mariadb_async_ready); $end = Time::HiRes::gettimeofday(); cmp_ok(($end - $start), '<', 2); +ok $sth->{Active}; sleep 1 until $sth->mariadb_async_ready; +ok $sth->{Active}; my $row = $sth->fetch; +ok !$sth->{Active}; $end = Time::HiRes::gettimeofday(); ok $row; is $row->[0], 0; @@ -126,16 +134,19 @@ $dbh->do('DELETE FROM async_test'); $sth = $dbh->prepare('INSERT INTO async_test VALUES(SLEEP(2), ?, ?)', { mariadb_async => 1 }); +ok !$sth->{Active}; $start = Time::HiRes::gettimeofday(); $rows = $sth->execute(1, 2); $end = Time::HiRes::gettimeofday(); cmp_ok(($end - $start), '<', 2); +ok $sth->{Active}; ok $rows; is $rows, '0E0'; $rows = $sth->mariadb_async_result; $end = Time::HiRes::gettimeofday(); cmp_ok(($end - $start), '>=', 1.9); +ok !$sth->{Active}; is $rows, 1; ( $a, $b, $c ) = $dbh->selectrow_array('SELECT * FROM async_test'); @@ -164,10 +175,13 @@ is $rows, '0E0'; $sth = $dbh->prepare('UPDATE async_test SET value0 = 0 WHERE value0 = 999', { mariadb_async => 1 }); +ok !$sth->{Active}; $rows = $sth->execute; +ok $sth->{Active}; ok $rows; is $rows, '0E0'; $rows = $sth->mariadb_async_result; +ok !$sth->{Active}; ok $rows; is $rows, '0E0'; @@ -179,7 +193,9 @@ is $rows, 1; $sth = $dbh->prepare('SELECT 1, value0, value1, value2 FROM async_test WHERE value0 = ?', { mariadb_async => 1 }); +ok !$sth->{Active}; $sth->execute(1); +ok $sth->{Active}; is $sth->{'NUM_OF_FIELDS'}, undef; is $sth->{'NUM_OF_PARAMS'}, 1; is $sth->{'NAME'}, undef; @@ -195,6 +211,7 @@ is $sth->{'Database'}, $dbh; is $sth->{'Statement'}, 'SELECT 1, value0, value1, value2 FROM async_test WHERE value0 = ?'; $sth->mariadb_async_result; +ok $sth->{Active}; is $sth->{'NUM_OF_FIELDS'}, 4; is $sth->{'NUM_OF_PARAMS'}, 1; cmp_bag $sth->{'NAME'}, [qw/1 value0 value1 value2/]; @@ -210,27 +227,60 @@ is $sth->{'Database'}, $dbh; is $sth->{'Statement'}, 'SELECT 1, value0, value1, value2 FROM async_test WHERE value0 = ?'; $sth->finish; +ok !$sth->{Active}; $sth->execute(1); +ok $sth->{Active}; $row = $sth->fetch; +ok !$sth->{Active}; is_deeply $row, [1, 1, 2, 3]; -$sth->finish; +is $sth->rows, 1; + +$sth->execute(1); +ok $sth->{Active}; +$sth->mariadb_async_result; +ok $sth->{Active}; +$row = $sth->fetch; +ok !$sth->{Active}; +is_deeply $row, [1, 1, 2, 3]; +is $sth->rows, 1; $sth->execute(1); +ok $sth->{Active}; $row = $sth->fetchrow_arrayref; +ok !$sth->{Active}; is_deeply $row, [1, 1, 2, 3]; -$sth->finish; +is $sth->rows, 1; $sth->execute(1); +ok $sth->{Active}; my @row = $sth->fetchrow_array; +ok !$sth->{Active}; is_deeply \@row, [1, 1, 2, 3]; -$sth->finish; +is $sth->rows, 1; $sth->execute(1); +ok $sth->{Active}; $row = $sth->fetchrow_hashref; +ok !$sth->{Active}; cmp_bag [ keys %$row ], [qw/1 value0 value1 value2/]; cmp_bag [ values %$row ], [1, 1, 2, 3]; -$sth->finish; +is $sth->rows, 1; + +$sth = $dbh->prepare('UPDATE async_test SET value0 = 2 WHERE value0 = 1', { mariadb_async => 1 }); +ok !$sth->{Active}; +ok $sth->execute(); +ok $sth->{Active}; +ok $sth->mariadb_async_result; +ok !$sth->{Active}; + +$sth = $dbh->prepare('SYNTAX ERROR', { mariadb_async => 1 }); +ok !$sth->{Active}; +ok $sth->execute(); +ok $sth->{Active}; +ok !$sth->mariadb_async_result; +ok !$sth->{Active}; + +local $SIG{__WARN__} = sub { die @_ }; -undef $sth; ok $dbh->disconnect; diff -Nru libdbd-mariadb-perl-1.11/t/88async-multi-stmts.t libdbd-mariadb-perl-1.21/t/88async-multi-stmts.t --- libdbd-mariadb-perl-1.11/t/88async-multi-stmts.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/88async-multi-stmts.t 2019-02-27 11:04:38.000000000 +0000 @@ -9,19 +9,32 @@ require 'lib.pl'; my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, - { RaiseError => 0, PrintError => 0, AutoCommit => 0 }); -plan tests => 8; + { RaiseError => 0, PrintError => 0, AutoCommit => 0, mariadb_multi_statements => 1 }); +plan tests => 104; -$dbh->do(<do(<prepare('INSERT INTO async_test VALUES(0)', { mariadb_async => 1 }); -my $sth1 = $dbh->prepare('INSERT INTO async_test VALUES(1)', { mariadb_async => 1 }); +my $sth0 = $dbh->prepare('INSERT INTO async_test VALUES(1)', { mariadb_async => 1 }); +ok $sth0 or die $dbh->err; +my $sth1 = $dbh->prepare('INSERT INTO async_test VALUES(2)', { mariadb_async => 1 }); +ok $sth1 or die $dbh->err; +my $sth2 = $dbh->prepare('INSERT INTO async_test VALUES(3); INSERT INTO async_test VALUES(4);', { mariadb_async => 1 }); +ok $sth2 or die $dbh->err; + +ok !$sth0->{Active}; +ok !$sth1->{Active}; +ok !$sth2->{Active}; + +ok $sth0->execute; + +ok $sth0->{Active}; +ok !$sth1->{Active}; +ok !$sth2->{Active}; -$sth0->execute; ok !defined($sth1->mariadb_async_ready); ok $sth1->errstr; ok !defined($sth1->mariadb_async_result); @@ -32,7 +45,125 @@ ok defined($sth0->mariadb_async_result); ok !$sth1->errstr; -undef $sth0; -undef $sth1; +ok !$sth0->{Active}; +ok !$sth1->{Active}; +ok !$sth2->{Active}; + +is($sth0->last_insert_id(), 1); +is($dbh->last_insert_id(undef, undef, undef, undef), 1); + +ok $sth2->execute; + +ok !$sth0->{Active}; +ok !$sth1->{Active}; +ok $sth2->{Active}; + +ok !defined($sth1->mariadb_async_ready); +ok $sth1->err; +ok !defined($sth1->mariadb_async_result); +ok $sth1->err; + +ok !$sth0->{Active}; +ok !$sth1->{Active}; +ok $sth2->{Active}; + +is($sth0->last_insert_id(), 1); +is($dbh->last_insert_id(undef, undef, undef, undef), 1); + +ok defined($sth2->mariadb_async_ready); +ok !$sth2->err; + +is($sth0->last_insert_id(), 1); +is($dbh->last_insert_id(undef, undef, undef, undef), 1); + +ok defined($sth2->mariadb_async_result); +ok !$sth2->err; + +ok !$sth0->{Active}; +ok !$sth1->{Active}; +ok $sth2->{Active}; + +is($sth0->last_insert_id(), 1); +is($sth2->last_insert_id(), 3); +is($dbh->last_insert_id(undef, undef, undef, undef), 3); + +ok $sth2->more_results; +ok defined($sth2->mariadb_async_result); +ok !$sth2->err; + +ok !$sth0->{Active}; +ok !$sth1->{Active}; +ok !$sth2->{Active}; + +is($sth0->last_insert_id(), 1); +is($sth2->last_insert_id(), 4); +is($dbh->last_insert_id(undef, undef, undef, undef), 4); + +ok !$sth2->more_results; + +ok !$sth0->{Active}; +ok !$sth1->{Active}; +ok !$sth2->{Active}; + +ok $dbh->do('INSERT INTO async_test VALUES(5)', { mariadb_async => 1 }); + +is($sth0->last_insert_id(), 1); +is($sth2->last_insert_id(), 4); +is($dbh->last_insert_id(undef, undef, undef, undef), 4); + +ok defined($dbh->mariadb_async_ready); +ok !$dbh->err; + +is($sth0->last_insert_id(), 1); +is($sth2->last_insert_id(), 4); +is($dbh->last_insert_id(undef, undef, undef, undef), 4); + +ok defined($dbh->mariadb_async_result); +ok !$sth2->err; + +is($sth0->last_insert_id(), 1); +is($sth2->last_insert_id(), 4); +is($dbh->last_insert_id(undef, undef, undef, undef), 5); + +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 }); + +ok $sth3 or die $dbh->err; + +ok !$sth3->{Active}; +ok $sth3->execute(); +ok $sth3->{Active}; + +is($sth0->last_insert_id(), 1); +is($sth2->last_insert_id(), 4); +is($dbh->last_insert_id(undef, undef, undef, undef), 5); + +ok $sth3->{Active}; +ok $sth3->mariadb_async_result(); +ok $sth3->{Active}; + +is($sth0->last_insert_id(), 1); +is($sth2->last_insert_id(), 4); +is($sth3->last_insert_id(), 6); +is($dbh->last_insert_id(undef, undef, undef, undef), 6); + +ok $sth3->{Active}; +ok $sth3->more_results(); +ok $sth3->{Active}; + +is($sth0->last_insert_id(), 1); +is($sth2->last_insert_id(), 4); +is($sth3->last_insert_id(), 7); +is($dbh->last_insert_id(undef, undef, undef, undef), 7); + +ok $sth3->{Active}; +ok !$sth3->more_results(); +ok !$sth3->{Active}; + +is($sth0->last_insert_id(), 1); +is($sth2->last_insert_id(), 4); +is($sth3->last_insert_id(), 7); +is($dbh->last_insert_id(undef, undef, undef, undef), 7); + +local $SIG{__WARN__} = sub { die @_ }; $dbh->disconnect; diff -Nru libdbd-mariadb-perl-1.11/t/89async-method-check.t libdbd-mariadb-perl-1.21/t/89async-method-check.t --- libdbd-mariadb-perl-1.11/t/89async-method-check.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/89async-method-check.t 2019-02-27 11:04:38.000000000 +0000 @@ -30,6 +30,8 @@ foreign_key_info statistics_info tables quote /; +push @db_unsafe_methods, 'selectall_array' if DBI::db->can('selectall_array'); + my @st_safe_methods = qw/ fetchrow_arrayref fetch fetchrow_array fetchrow_hashref fetchall_arrayref fetchall_hashref finish rows @@ -54,6 +56,7 @@ selectrow_array => ['SELECT 1'], selectrow_arrayref => ['SELECT 1'], selectrow_hashref => ['SELECT 1'], + selectall_array => ['SELECT 1'], selectall_arrayref => ['SELECT 1'], selectall_hashref => ['SELECT 1', '1'], selectcol_arrayref => ['SELECT 1'], diff -Nru libdbd-mariadb-perl-1.11/t/93net_ssleay.t libdbd-mariadb-perl-1.21/t/93net_ssleay.t --- libdbd-mariadb-perl-1.11/t/93net_ssleay.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/93net_ssleay.t 2019-02-27 11:04:38.000000000 +0000 @@ -7,7 +7,12 @@ use DBD::MariaDB; BEGIN { - plan skip_all => 'Net::SSLeay is required for this test' unless eval { require Net::SSLeay }; + eval { + require Net::SSLeay; + Net::SSLeay->VERSION(1.43); # for Net::SSLeay::initialize() + } or do { + plan skip_all => 'Net::SSLeay 1.43 is required for this test'; + }; Net::SSLeay->import(); } diff -Nru libdbd-mariadb-perl-1.11/t/99_bug_server_prepare_blob_null.t libdbd-mariadb-perl-1.21/t/99_bug_server_prepare_blob_null.t --- libdbd-mariadb-perl-1.11/t/99_bug_server_prepare_blob_null.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/99_bug_server_prepare_blob_null.t 2019-02-27 11:04:38.000000000 +0000 @@ -12,7 +12,7 @@ my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0, AutoCommit => 0 }); -plan tests => 11; +plan tests => 9; ok $dbh->do("DROP TABLE IF EXISTS dbd_mysql_t99_prepare"); @@ -31,8 +31,6 @@ my $row = $sth->fetch; is $row->[0] => undef; -ok $sth->finish; - $dbh->do("insert into dbd_mysql_t99_prepare (data) values('a')"); $sth = $dbh->prepare("select data from dbd_mysql_t99_prepare"); ok $sth->execute; @@ -41,8 +39,6 @@ $row = $sth->fetch; is $row->[0] => 'a'; -ok $sth->finish; - ok $dbh->do("DROP TABLE dbd_mysql_t99_prepare"); ok $dbh->disconnect; diff -Nru libdbd-mariadb-perl-1.11/t/rt25389-bin-case.t libdbd-mariadb-perl-1.21/t/rt25389-bin-case.t --- libdbd-mariadb-perl-1.11/t/rt25389-bin-case.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/rt25389-bin-case.t 2019-02-27 11:04:38.000000000 +0000 @@ -41,7 +41,6 @@ $i++; } is( $i, scalar @test, $q1 ); - $sth->finish; my $q2 = "select name from `$table` where " . join( " OR ", map { "name = '$_'" } @test ); diff -Nru libdbd-mariadb-perl-1.11/t/rt85919-fetch-lost-connection.t libdbd-mariadb-perl-1.21/t/rt85919-fetch-lost-connection.t --- libdbd-mariadb-perl-1.11/t/rt85919-fetch-lost-connection.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/rt85919-fetch-lost-connection.t 2019-02-27 11:04:38.000000000 +0000 @@ -20,7 +20,6 @@ ok( $sth->execute(), 'execute SQL'); my @res = $sth->fetchrow_array(); is ( $res[0], undef, 'no rows returned'); - ok( $sth->finish(), 'finish'); $sth = undef; } else { diff -Nru libdbd-mariadb-perl-1.11/t/rt88006-bit-prepare.t libdbd-mariadb-perl-1.21/t/rt88006-bit-prepare.t --- libdbd-mariadb-perl-1.11/t/rt88006-bit-prepare.t 2019-01-02 15:31:56.000000000 +0000 +++ libdbd-mariadb-perl-1.21/t/rt88006-bit-prepare.t 2019-02-27 11:04:38.000000000 +0000 @@ -49,28 +49,24 @@ ok $sth->bind_param(1, 4, DBI::SQL_INTEGER); ok $sth->bind_param(2, pack("B*", '1110000000000000011101100000000011111101'), DBI::SQL_BINARY); ok $sth->execute() or die("Execute failed: ".$DBI::errstr); -ok $sth->finish; ok $sth = $dbh->prepare("SELECT id,flags FROM dbd_mysql_rt88006_bit_prep WHERE id = 1"); ok $sth->execute() or die("Execute failed: ".$DBI::errstr); ok (my $r = $sth->fetchrow_hashref(), "fetchrow_hashref for $scenario"); is ($r->{id}, 1, 'id test contents'); is (unpack("B*", $r->{flags}), '0000000000000000000000000000000000000010', 'flags has contents'); -ok $sth->finish; ok $sth = $dbh->prepare("SELECT id,flags FROM dbd_mysql_rt88006_bit_prep WHERE id = 3"); ok $sth->execute() or die("Execute failed: ".$DBI::errstr); ok ($r = $sth->fetchrow_hashref(), "fetchrow_hashref for $scenario with more then 32 bits"); is ($r->{id}, 3, 'id test contents'); is (unpack("B*", $r->{flags}), '1111011111101111101101111111101111111101', 'flags has contents'); -ok $sth->finish; ok $sth = $dbh->prepare("SELECT id,flags FROM dbd_mysql_rt88006_bit_prep WHERE id = 4"); ok $sth->execute() or die("Execute failed: ".$DBI::errstr); ok ($r = $sth->fetchrow_hashref(), "fetchrow_hashref for $scenario with binary insert"); is ($r->{id}, 4, 'id test contents'); is (unpack("B*", $r->{flags}), '1110000000000000011101100000000011111101', 'flags has contents'); -ok $sth->finish; ok $sth = $dbh->prepare("SELECT id,BIN(flags) FROM dbd_mysql_rt88006_bit_prep WHERE ID =1"); ok $sth->execute() or die("Execute failed: ".$DBI::errstr); @@ -90,7 +86,6 @@ is ($r->{id}, 4, 'id test contents'); is ($r->{'BIN(flags)'}, '1110000000000000011101100000000011111101', 'flags has contents'); -ok $sth->finish; ok $dbh->disconnect; }