Hello community, here is the log from the commit of package perl-DBD-mysql for openSUSE:Factory checked in at 2016-11-22 18:58:59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/perl-DBD-mysql (Old) and /work/SRC/openSUSE:Factory/.perl-DBD-mysql.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "perl-DBD-mysql" Changes: -------- --- /work/SRC/openSUSE:Factory/perl-DBD-mysql/perl-DBD-mysql.changes 2016-11-18 22:03:31.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.perl-DBD-mysql.new/perl-DBD-mysql.changes 2016-11-22 18:59:00.000000000 +0100 @@ -1,0 +2,26 @@ +Sun Nov 20 06:16:34 UTC 2016 - co...@suse.com + +- updated to 4.040 + see /usr/share/doc/packages/perl-DBD-mysql/Changes + + 2016-11-19 Patrick Galbraith, Michiel Beijen, DBI/DBD community (4.040) + * Since 4.038 we had problems compiling on big-endian architectures, such + as MIPS, s390 and Sparc. Thanks to Salvatore Bonaccorso @ Debian project + (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=844538) + and Vladimir Marek (https://rt.cpan.org/Public/Bug/Display.html?id=118835) + for reporting the issues. Fix by Pali Rohár. + + Fix integer types when server side prepare statements are enabled + Fixed problems: + * SQL_BIGINT was incorrectly handled as 32bit MYSQL_TYPE_LONG type instead + 64bit MYSQL_TYPE_LONGLONG which led to integer overflow/underflow + * 32bit MYSQL_TYPE_LONG was used for perl's IV storage when IV was 64bit + and 64bit MYSQL_TYPE_LONGLONG was used when IV was 32bit + * All unsigned types were handled as signed, so all high positive values + were treated as negative + * Numeric conversions in perl which led to overflow/underflow was ignored + even when mysql strict mode was enabled + * Test t/41int_min_max.t was running only for normal non-prepared statements + * Test t/40server_prepare.t used incorrect SQL type for big (64bit) integers + +------------------------------------------------------------------- Old: ---- DBD-mysql-4.039.tar.gz New: ---- DBD-mysql-4.040.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ perl-DBD-mysql.spec ++++++ --- /var/tmp/diff_new_pack.KpnGlf/_old 2016-11-22 18:59:01.000000000 +0100 +++ /var/tmp/diff_new_pack.KpnGlf/_new 2016-11-22 18:59:01.000000000 +0100 @@ -17,14 +17,14 @@ Name: perl-DBD-mysql -Version: 4.039 +Version: 4.040 Release: 0 %define cpan_name DBD-mysql Summary: MySQL driver for the Perl5 Database Interface (DBI) License: Artistic-1.0 or GPL-1.0+ Group: Development/Libraries/Perl Url: http://search.cpan.org/dist/DBD-mysql/ -Source0: http://www.cpan.org/authors/id/C/CA/CAPTTOFU/%{cpan_name}-%{version}.tar.gz +Source0: http://www.cpan.org/authors/id/M/MI/MICHIELB/%{cpan_name}-%{version}.tar.gz Source1: cpanspec.yml BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: perl ++++++ DBD-mysql-4.039.tar.gz -> DBD-mysql-4.040.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/DBD-mysql-4.039/Changes new/DBD-mysql-4.040/Changes --- old/DBD-mysql-4.039/Changes 2016-11-16 04:33:41.000000000 +0100 +++ new/DBD-mysql-4.040/Changes 2016-11-19 20:55:08.000000000 +0100 @@ -1,3 +1,23 @@ +2016-11-19 Patrick Galbraith, Michiel Beijen, DBI/DBD community (4.040) +* Since 4.038 we had problems compiling on big-endian architectures, such + as MIPS, s390 and Sparc. Thanks to Salvatore Bonaccorso @ Debian project + (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=844538) + and Vladimir Marek (https://rt.cpan.org/Public/Bug/Display.html?id=118835) + for reporting the issues. Fix by Pali Rohár. + + Fix integer types when server side prepare statements are enabled + Fixed problems: + * SQL_BIGINT was incorrectly handled as 32bit MYSQL_TYPE_LONG type instead + 64bit MYSQL_TYPE_LONGLONG which led to integer overflow/underflow + * 32bit MYSQL_TYPE_LONG was used for perl's IV storage when IV was 64bit + and 64bit MYSQL_TYPE_LONGLONG was used when IV was 32bit + * All unsigned types were handled as signed, so all high positive values + were treated as negative + * Numeric conversions in perl which led to overflow/underflow was ignored + even when mysql strict mode was enabled + * Test t/41int_min_max.t was running only for normal non-prepared statements + * Test t/40server_prepare.t used incorrect SQL type for big (64bit) integers + 2016-11-15 Patrick Galbraith, Michiel Beijen, DBI/DBD community (4.039) * Fix for security issue Out-of-bounds read by DBD::mysql CVE-2016-1249 (pali) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/DBD-mysql-4.039/META.json new/DBD-mysql-4.040/META.json --- old/DBD-mysql-4.039/META.json 2016-11-16 04:53:20.000000000 +0100 +++ new/DBD-mysql-4.040/META.json 2016-11-19 20:55:49.000000000 +0100 @@ -4,7 +4,7 @@ "Patrick Galbraith <p...@patg.net>" ], "dynamic_config" : 1, - "generated_by" : "ExtUtils::MakeMaker version 6.66, CPAN::Meta::Converter version 2.120921", + "generated_by" : "ExtUtils::MakeMaker version 7.18, CPAN::Meta::Converter version 2.150005", "license" : [ "perl_5" ], @@ -22,10 +22,7 @@ "prereqs" : { "build" : { "requires" : { - "ExtUtils::MakeMaker" : "0", - "Test::Deep" : "0", - "Test::Simple" : "0.90", - "Time::HiRes" : "0" + "ExtUtils::MakeMaker" : "0" } }, "configure" : { @@ -39,6 +36,13 @@ "DBI" : "1.609", "perl" : "5.008001" } + }, + "test" : { + "requires" : { + "Test::Deep" : "0", + "Test::Simple" : "0.90", + "Time::HiRes" : "0" + } } }, "release_status" : "stable", @@ -53,7 +57,7 @@ "x_IRC" : "irc://irc.perl.org/#dbi", "x_MailingList" : "mailto:dbi-...@perl.org" }, - "version" : "4.039", + "version" : "4.040", "x_contributors" : [ "Alexandr Ciornii <alexcho...@gmail.com>", "Alexey Molchanov <alexey.molcha...@portaone.com>", @@ -107,5 +111,6 @@ "tokuhirom <tokuhi...@gmail.com>", "zefram <zef...@fysh.org>", "zentooo <ankera...@gmail.com>" - ] + ], + "x_serialization_backend" : "JSON::PP version 2.27300" } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/DBD-mysql-4.039/META.yml new/DBD-mysql-4.040/META.yml --- old/DBD-mysql-4.039/META.yml 2016-11-16 04:53:20.000000000 +0100 +++ new/DBD-mysql-4.040/META.yml 2016-11-19 20:55:49.000000000 +0100 @@ -3,34 +3,34 @@ author: - 'Patrick Galbraith <p...@patg.net>' build_requires: - ExtUtils::MakeMaker: 0 - Test::Deep: 0 - Test::Simple: 0.90 - Time::HiRes: 0 + ExtUtils::MakeMaker: '0' + Test::Deep: '0' + Test::Simple: '0.90' + Time::HiRes: '0' configure_requires: - DBI: 1.609 - Data::Dumper: 0 + DBI: '1.609' + Data::Dumper: '0' dynamic_config: 1 -generated_by: 'ExtUtils::MakeMaker version 6.66, CPAN::Meta::Converter version 2.120921' +generated_by: 'ExtUtils::MakeMaker version 7.18, CPAN::Meta::Converter version 2.150005' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html - version: 1.4 + version: '1.4' name: DBD-mysql no_index: directory: - t - inc requires: - DBI: 1.609 - perl: 5.008001 + DBI: '1.609' + perl: '5.008001' resources: + IRC: irc://irc.perl.org/#dbi + MailingList: mailto:dbi-...@perl.org homepage: http://dbi.perl.org/ license: http://dev.perl.org/licenses/ repository: https://github.com/perl5-dbi/DBD-mysql - x_IRC: irc://irc.perl.org/#dbi - x_MailingList: mailto:dbi-...@perl.org -version: 4.039 +version: '4.040' x_contributors: - 'Alexandr Ciornii <alexcho...@gmail.com>' - 'Alexey Molchanov <alexey.molcha...@portaone.com>' @@ -84,3 +84,4 @@ - 'tokuhirom <tokuhi...@gmail.com>' - 'zefram <zef...@fysh.org>' - 'zentooo <ankera...@gmail.com>' +x_serialization_backend: 'CPAN::Meta::YAML version 0.018' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/DBD-mysql-4.039/dbdimp.c new/DBD-mysql-4.040/dbdimp.c --- old/DBD-mysql-4.039/dbdimp.c 2016-11-15 03:27:49.000000000 +0100 +++ new/DBD-mysql-4.040/dbdimp.c 2016-11-19 20:55:08.000000000 +0100 @@ -360,8 +360,10 @@ case MYSQL_TYPE_YEAR: #if IVSIZE >= 8 case MYSQL_TYPE_LONGLONG: -#endif + enum_type= MYSQL_TYPE_LONGLONG; +#else enum_type= MYSQL_TYPE_LONG; +#endif break; #if MYSQL_VERSION_ID > NEW_DATATYPE_VERSION @@ -1869,6 +1871,13 @@ PerlIO_printf(DBIc_LOGPIO(imp_xxh), "imp_dbh->use_server_side_prepare: %d\n", imp_dbh->use_server_side_prepare); + + if ((svp = hv_fetch(hv, "mysql_server_prepare_disable_fallback", 37, FALSE)) && *svp) + imp_dbh->disable_fallback_for_server_prepare = SvTRUE(*svp); + if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) + PerlIO_printf(DBIc_LOGPIO(imp_xxh), + "imp_dbh->disable_fallback_for_server_prepare: %d\n", + imp_dbh->disable_fallback_for_server_prepare); #endif /* HELMUT */ @@ -2455,6 +2464,8 @@ imp_dbh->auto_reconnect = bool_value; else if (kl == 20 && strEQ(key, "mysql_server_prepare")) imp_dbh->use_server_side_prepare = bool_value; + else if (kl == 37 && strEQ(key, "mysql_server_prepare_disable_fallback")) + imp_dbh->disable_fallback_for_server_prepare = bool_value; else if (kl == 23 && strEQ(key,"mysql_no_autocommit_cmd")) imp_dbh->no_autocommit_cmd = bool_value; else if (kl == 24 && strEQ(key,"mysql_bind_type_guessing")) @@ -2690,6 +2701,8 @@ } else if (kl == 14 && strEQ(key,"server_prepare")) result= sv_2mortal(newSViv((IV) imp_dbh->use_server_side_prepare)); + else if (kl == 31 && strEQ(key, "server_prepare_disable_fallback")) + result= sv_2mortal(newSViv((IV) imp_dbh->disable_fallback_for_server_prepare)); break; case 't': @@ -2765,17 +2778,28 @@ #if MYSQL_VERSION_ID >= SERVER_PREPARE_VERSION /* Set default value of 'mysql_server_prepare' attribute for sth from dbh */ 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; if (attribs) { svp= DBD_ATTRIB_GET_SVP(attribs, "mysql_server_prepare", 20); imp_sth->use_server_side_prepare = (svp) ? SvTRUE(*svp) : imp_dbh->use_server_side_prepare; + svp= DBD_ATTRIB_GET_SVP(attribs, "mysql_server_prepare_disable_fallback", 37); + imp_sth->disable_fallback_for_server_prepare = (svp) ? + SvTRUE(*svp) : imp_dbh->disable_fallback_for_server_prepare; + svp = DBD_ATTRIB_GET_SVP(attribs, "async", 5); if(svp && SvTRUE(*svp)) { #if MYSQL_ASYNC imp_sth->is_async = TRUE; + if (imp_sth->disable_fallback_for_server_prepare) + { + do_error(sth, ER_UNSUPPORTED_PS, + "Async option not supported with server side prepare", "HY000"); + return 0; + } imp_sth->use_server_side_prepare = FALSE; #else do_error(sth, 2000, @@ -2842,6 +2866,15 @@ if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\t\tLIMIT and ? found, set to use_server_side_prepare=0\n"); + if (imp_sth->disable_fallback_for_server_prepare) + { + do_error(sth, ER_UNSUPPORTED_PS, + "\"LIMIT ?\" not supported with server side prepare", + "HY000"); + mysql_stmt_close(imp_sth->stmt); + imp_sth->stmt= NULL; + return FALSE; + } /* ... then we do not want to try server side prepare (use emulation) */ imp_sth->use_server_side_prepare= 0; break; @@ -2873,6 +2906,15 @@ { if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) PerlIO_printf(DBIc_LOGPIO(imp_xxh), "Disable PS mode for CALL()\n"); + if (imp_sth->disable_fallback_for_server_prepare) + { + do_error(sth, ER_UNSUPPORTED_PS, + "\"CALL()\" not supported with server side prepare", + "HY000"); + mysql_stmt_close(imp_sth->stmt); + imp_sth->stmt= NULL; + return FALSE; + } imp_sth->use_server_side_prepare= 0; break; } @@ -2922,7 +2964,7 @@ /* For commands that are not supported by server side prepared statement mechanism lets try to pass them through regular API */ - if (mysql_stmt_errno(imp_sth->stmt) == ER_UNSUPPORTED_PS) + if (!imp_sth->disable_fallback_for_server_prepare && mysql_stmt_errno(imp_sth->stmt) == ER_UNSUPPORTED_PS) { if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) PerlIO_printf(DBIc_LOGPIO(imp_xxh), @@ -3508,7 +3550,7 @@ { for (i = mysql_stmt_field_count(stmt) - 1; i >=0; --i) { enum_type = mysql_to_perl_type(stmt->fields[i].type); - if (enum_type != MYSQL_TYPE_DOUBLE && enum_type != MYSQL_TYPE_LONG && enum_type != MYSQL_TYPE_BIT) + if (enum_type != MYSQL_TYPE_DOUBLE && enum_type != MYSQL_TYPE_LONG && enum_type != MYSQL_TYPE_LONGLONG && enum_type != MYSQL_TYPE_BIT) { /* mysql_stmt_store_result to update MYSQL_FIELD->max_length */ my_bool on = 1; @@ -3578,6 +3620,10 @@ #if defined (dTHR) dTHR; #endif +#if MYSQL_VERSION_ID >= SERVER_PREPARE_VERSION + int use_server_side_prepare = imp_sth->use_server_side_prepare; + int disable_fallback_for_server_prepare = imp_sth->disable_fallback_for_server_prepare; +#endif ASYNC_CHECK_RETURN(sth, -2); @@ -3606,20 +3652,44 @@ mysql_st_free_result_sets (sth, imp_sth); #if MYSQL_VERSION_ID >= SERVER_PREPARE_VERSION - - if (imp_sth->use_server_side_prepare && ! imp_sth->use_mysql_use_result) + if (use_server_side_prepare) { - imp_sth->row_num= mysql_st_internal_execute41( - sth, - DBIc_NUM_PARAMS(imp_sth), - &imp_sth->result, - imp_sth->stmt, - imp_sth->bind, - &imp_sth->has_been_bound - ); + if (imp_sth->use_mysql_use_result) + { + if (disable_fallback_for_server_prepare) + { + do_error(sth, ER_UNSUPPORTED_PS, + "\"mysql_use_result\" not supported with server side prepare", + "HY000"); + return 0; + } + use_server_side_prepare = 0; + } + + if (use_server_side_prepare) + { + imp_sth->row_num= mysql_st_internal_execute41( + sth, + DBIc_NUM_PARAMS(imp_sth), + &imp_sth->result, + imp_sth->stmt, + imp_sth->bind, + &imp_sth->has_been_bound + ); + if (imp_sth->row_num == (my_ulonglong)-2) /* -2 means error */ + { + SV *err = DBIc_ERR(imp_xxh); + if (!disable_fallback_for_server_prepare && SvIV(err) == ER_UNSUPPORTED_PS) + { + use_server_side_prepare = 0; + } + } + } } - else { + + if (!use_server_side_prepare) #endif + { imp_sth->row_num= mysql_st_internal_execute( sth, *statement, @@ -3653,7 +3723,7 @@ /** Store the result in the current statement handle */ DBIc_NUM_FIELDS(imp_sth)= mysql_num_fields(imp_sth->result); DBIc_ACTIVE_on(imp_sth); - if (!imp_sth->use_server_side_prepare) + if (!use_server_side_prepare) imp_sth->done_desc= 0; imp_sth->fetch_done= 0; } @@ -3776,6 +3846,7 @@ break; case MYSQL_TYPE_LONG: + case MYSQL_TYPE_LONGLONG: buffer->buffer_length= sizeof(fbh->ldata); buffer->buffer= (char*) &fbh->ldata; buffer->is_unsigned= (fields[i].flags & UNSIGNED_FLAG) ? 1 : 0; @@ -4016,6 +4087,7 @@ break; case MYSQL_TYPE_LONG: + case MYSQL_TYPE_LONGLONG: if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\t\tst_fetch int data %"IVdf", unsigned? %d\n", fbh->ldata, buffer->is_unsigned); @@ -4178,6 +4250,7 @@ break; case MYSQL_TYPE_LONG: + case MYSQL_TYPE_LONGLONG: /* Coerce to integer and set scalar as UV resp. IV */ if (fields[i].flags & UNSIGNED_FLAG) { @@ -4742,6 +4815,14 @@ if (strEQ(key, "mysql_is_auto_increment")) retsv = ST_FETCH_AV(AV_ATTRIB_IS_AUTO_INCREMENT); break; + case 37: + if (strEQ(key, "mysql_server_prepare_disable_fallback")) +#if MYSQL_VERSION_ID >= SERVER_PREPARE_VERSION + retsv= sv_2mortal(newSViv((IV) imp_sth->disable_fallback_for_server_prepare)); +#else + retsv= boolSV(0); +#endif + break; } break; } @@ -4825,6 +4906,7 @@ STRLEN slen; char *buffer= NULL; int buffer_is_null= 0; + int buffer_is_unsigned= 0; int buffer_length= slen; unsigned int buffer_type= 0; #endif @@ -4882,9 +4964,13 @@ case SQL_NUMERIC: case SQL_INTEGER: case SQL_SMALLINT: - case SQL_BIGINT: case SQL_TINYINT: +#if IVSIZE >= 8 + case SQL_BIGINT: + buffer_type= MYSQL_TYPE_LONGLONG; +#else buffer_type= MYSQL_TYPE_LONG; +#endif break; case SQL_DOUBLE: case SQL_DECIMAL: @@ -4910,12 +4996,24 @@ if (! buffer_is_null) { switch(buffer_type) { case MYSQL_TYPE_LONG: + case MYSQL_TYPE_LONGLONG: /* INT */ if (!SvIOK(imp_sth->params[idx].value) && DBIc_TRACE_LEVEL(imp_xxh) >= 2) PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\t\tTRY TO BIND AN INT NUMBER\n"); buffer_length = sizeof imp_sth->fbind[idx].numeric_val.lval; imp_sth->fbind[idx].numeric_val.lval= SvIV(imp_sth->params[idx].value); buffer=(void*)&(imp_sth->fbind[idx].numeric_val.lval); + if (!SvIOK(imp_sth->params[idx].value)) + { + if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) + PerlIO_printf(DBIc_LOGPIO(imp_xxh), + " Conversion to INT NUMBER was not successful -> '%s' --> (unsigned) '%"UVuf"' / (signed) '%"IVdf"' <- fallback to STRING\n", + SvPV_nolen(imp_sth->params[idx].value), imp_sth->fbind[idx].numeric_val.lval, imp_sth->fbind[idx].numeric_val.lval); + buffer_type = MYSQL_TYPE_STRING; + break; + } + if (SvIsUV(imp_sth->params[idx].value)) + buffer_is_unsigned= 1; if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) PerlIO_printf(DBIc_LOGPIO(imp_xxh), " SCALAR type %"IVdf" ->%"IVdf"<- IS A INT NUMBER\n", @@ -4970,7 +5068,7 @@ } /* Type of column was changed. Force to rebind */ - if (imp_sth->bind[idx].buffer_type != buffer_type) { + if (imp_sth->bind[idx].buffer_type != buffer_type || imp_sth->bind[idx].is_unsigned != buffer_is_unsigned) { if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) PerlIO_printf(DBIc_LOGPIO(imp_xxh), " FORCE REBIND: buffer type changed from %d to %d, sql-type=%"IVdf"\n", @@ -4988,6 +5086,7 @@ imp_sth->bind[idx].buffer_type= buffer_type; imp_sth->bind[idx].buffer= buffer; imp_sth->bind[idx].buffer_length= buffer_length; + imp_sth->bind[idx].is_unsigned= buffer_is_unsigned; imp_sth->fbind[idx].length= buffer_length; imp_sth->fbind[idx].is_null= buffer_is_null; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/DBD-mysql-4.039/dbdimp.h new/DBD-mysql-4.040/dbdimp.h --- old/DBD-mysql-4.039/dbdimp.h 2016-11-08 14:30:17.000000000 +0100 +++ new/DBD-mysql-4.040/dbdimp.h 2016-11-19 20:55:08.000000000 +0100 @@ -183,6 +183,7 @@ * mysql_store_result */ bool use_server_side_prepare; + bool disable_fallback_for_server_prepare; #if MYSQL_ASYNC void* async_query_in_flight; #endif @@ -268,6 +269,7 @@ imp_sth_fbh_t *fbh; int has_been_bound; int use_server_side_prepare; /* server side prepare statements? */ + int disable_fallback_for_server_prepare; #endif MYSQL_RES* result; /* result */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/DBD-mysql-4.039/lib/Bundle/DBD/mysql.pm new/DBD-mysql-4.040/lib/Bundle/DBD/mysql.pm --- old/DBD-mysql-4.039/lib/Bundle/DBD/mysql.pm 2016-11-16 04:39:27.000000000 +0100 +++ new/DBD-mysql-4.040/lib/Bundle/DBD/mysql.pm 2016-11-19 20:55:08.000000000 +0100 @@ -3,7 +3,7 @@ use strict; use warnings; -our $VERSION = '4.039'; +our $VERSION = '4.040'; 1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/DBD-mysql-4.039/lib/DBD/mysql.pm new/DBD-mysql-4.040/lib/DBD/mysql.pm --- old/DBD-mysql-4.039/lib/DBD/mysql.pm 2016-11-16 04:31:12.000000000 +0100 +++ new/DBD-mysql-4.040/lib/DBD/mysql.pm 2016-11-19 20:55:08.000000000 +0100 @@ -15,7 +15,7 @@ # SQL_DRIVER_VER is formatted as dd.dd.dddd # for version 5.x please switch to 5.00(_00) version numbering # keep $VERSION in Bundle/DBD/mysql.pm in sync -our $VERSION = '4.039'; +our $VERSION = '4.040'; bootstrap DBD::mysql $VERSION; @@ -1201,7 +1201,9 @@ (;) may be enabled by using this option. Enabling this option may cause problems if server-side prepared statements are also enabled. -=item Prepared statement support (server side prepare) +=item mysql_server_prepare + +This option is used to enable server side prepared statements. To use server side prepared statements, all you need to do is set the variable mysql_server_prepare in the connect: @@ -1213,6 +1215,15 @@ { RaiseError => 1, AutoCommit => 1 } ); +or: + + $dbh = DBI->connect( + "DBI:mysql:database=test;host=localhost", + "", + "", + { RaiseError => 1, AutoCommit => 1, mysql_server_prepare => 1 } + ); + There are many benefits to using server side prepare statements, mostly if you are performing many inserts because of that fact that a single statement is prepared to accept multiple insert values. @@ -1222,6 +1233,17 @@ export MYSQL_SERVER_PREPARE=1 +Please note that mysql server cannot prepare or execute some prepared statements. +In this case DBD::mysql fallbacks to normal non-prepared statement and tries again. + +=item mysql_server_prepare_disable_fallback + +This option disable fallback to normal non-prepared statement when mysql server +does not support execution of current statement as prepared. + +Useful when you want to be sure that statement is going to be executed as +server side prepared. Error message and code in case of failure is propagated +back to DBI. =item mysql_embedded_options diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/DBD-mysql-4.039/mysql.xs new/DBD-mysql-4.040/mysql.xs --- old/DBD-mysql-4.039/mysql.xs 2016-11-08 14:41:15.000000000 +0100 +++ new/DBD-mysql-4.040/mysql.xs 2016-11-19 20:55:08.000000000 +0100 @@ -269,6 +269,7 @@ int buffer_length= slen; int buffer_type= 0; int use_server_side_prepare= 0; + int disable_fallback_for_server_prepare= 0; MYSQL_STMT *stmt= NULL; MYSQL_BIND *bind= NULL; #endif @@ -301,6 +302,10 @@ use_server_side_prepare = (svp) ? SvTRUE(*svp) : imp_dbh->use_server_side_prepare; + svp = DBD_ATTRIB_GET_SVP(attr, "mysql_server_prepare_disable_fallback", 37); + disable_fallback_for_server_prepare = (svp) ? + SvTRUE(*svp) : imp_dbh->disable_fallback_for_server_prepare; + svp = DBD_ATTRIB_GET_SVP(attr, "async", 5); async = (svp) ? *svp : &PL_sv_no; } @@ -313,6 +318,12 @@ if(SvTRUE(async)) { #if MYSQL_ASYNC + if (disable_fallback_for_server_prepare) + { + do_error(dbh, ER_UNSUPPORTED_PS, + "Async option not supported with server side prepare", "HY000"); + XSRETURN_UNDEF; + } use_server_side_prepare = FALSE; /* for now */ imp_dbh->async_query_in_flight = imp_dbh; #else @@ -336,7 +347,7 @@ For commands that are not supported by server side prepared statement mechanism lets try to pass them through regular API */ - if (mysql_stmt_errno(stmt) == ER_UNSUPPORTED_PS) + if (!disable_fallback_for_server_prepare && mysql_stmt_errno(stmt) == ER_UNSUPPORTED_PS) { use_server_side_prepare= 0; } @@ -410,6 +421,15 @@ fprintf(stderr, "\n failed while closing the statement"); fprintf(stderr, "\n %s", mysql_stmt_error(stmt)); } + + if (retval == -2) /* -2 means error */ + { + SV *err = DBIc_ERR(imp_dbh); + if (!disable_fallback_for_server_prepare && SvIV(err) == ER_UNSUPPORTED_PS) + { + use_server_side_prepare = 0; + } + } } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/DBD-mysql-4.039/t/15reconnect.t new/DBD-mysql-4.040/t/15reconnect.t --- old/DBD-mysql-4.039/t/15reconnect.t 2016-11-08 14:30:17.000000000 +0100 +++ new/DBD-mysql-4.040/t/15reconnect.t 2016-11-19 20:55:08.000000000 +0100 @@ -19,7 +19,7 @@ plan tests => 8 * 2; for my $mysql_server_prepare (0, 1) { -$dbh= DBI->connect($test_dsn . ';mysql_server_prepare=' . $mysql_server_prepare, $test_user, $test_password, +$dbh= DBI->connect("$test_dsn;mysql_server_prepare=$mysql_server_prepare;mysql_server_prepare_disable_fallback=1", $test_user, $test_password, { RaiseError => 1, PrintError => 1, AutoCommit => 0 }); ok(defined $dbh, "Connected to database"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/DBD-mysql-4.039/t/40server_prepare.t new/DBD-mysql-4.040/t/40server_prepare.t --- old/DBD-mysql-4.039/t/40server_prepare.t 2016-11-08 14:30:17.000000000 +0100 +++ new/DBD-mysql-4.040/t/40server_prepare.t 2016-11-19 20:55:08.000000000 +0100 @@ -9,7 +9,7 @@ $|= 1; -$test_dsn.= ";mysql_server_prepare=1"; +$test_dsn.= ";mysql_server_prepare=1;mysql_server_prepare_disable_fallback=1"; my $dbh; eval {$dbh= DBI->connect($test_dsn, $test_user, $test_password, @@ -18,7 +18,7 @@ if ($@) { plan skip_all => "no database connection"; } -plan tests => 27; +plan tests => 31; ok(defined $dbh, "connecting"); @@ -59,11 +59,11 @@ ok($sth2->bind_param(1, 101, DBI::SQL_INTEGER), "binding int"); ok($sth2->bind_param(2, 102, DBI::SQL_SMALLINT), "binding smallint"); ok($sth2->bind_param(3, 103, DBI::SQL_TINYINT), "binding tinyint"); -ok($sth2->bind_param(4, 104, DBI::SQL_INTEGER), "binding bigint"); +ok($sth2->bind_param(4, '8589934697', DBI::SQL_BIGINT), "binding bigint"); ok($sth2->execute(), "inserting data"); -is_deeply($dbh->selectall_arrayref('SELECT * FROM dbd_mysql_t40serverprepare2'), [[101, 102, 103, 104]]); +is_deeply($dbh->selectall_arrayref('SELECT * FROM dbd_mysql_t40serverprepare2'), [[101, 102, 103, '8589934697']]); ok ($dbh->do(qq{DROP TABLE dbd_mysql_t40serverprepare2}), "cleaning up"); @@ -78,6 +78,21 @@ is_deeply($dbh->selectall_arrayref('SELECT id, mydata FROM t3'), [[1, 2]]); +my $dbname = $dbh->selectrow_arrayref("SELECT DATABASE()")->[0]; + +$dbh->{mysql_server_prepare_disable_fallback} = 1; +my $error_handler_called = 0; +$dbh->{HandleError} = sub { $error_handler_called = 1; die $_[0]; }; +eval { $dbh->prepare("USE $dbname") }; +$dbh->{HandleError} = undef; +ok($error_handler_called, 'USE is not supported with mysql_server_prepare_disable_fallback=1'); + +$dbh->{mysql_server_prepare_disable_fallback} = 0; +my $sth4; +ok($sth4 = $dbh->prepare("USE $dbname"), 'USE is supported with mysql_server_prepare_disable_fallback=0'); +ok($sth4->execute()); +ok($sth4->finish()); + ok ($dbh->do(qq{DROP TABLE t3}), "cleaning up"); $dbh->disconnect(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/DBD-mysql-4.039/t/40server_prepare_crash.t new/DBD-mysql-4.040/t/40server_prepare_crash.t --- old/DBD-mysql-4.039/t/40server_prepare_crash.t 2016-11-08 14:41:15.000000000 +0100 +++ new/DBD-mysql-4.040/t/40server_prepare_crash.t 2016-11-19 20:55:08.000000000 +0100 @@ -7,7 +7,7 @@ use vars qw($test_dsn $test_user $test_password); require "t/lib.pl"; -my $dbh = eval { DBI->connect($test_dsn, $test_user, $test_password, { PrintError => 1, RaiseError => 1, AutoCommit => 0, mysql_server_prepare => 1 }) }; +my $dbh = eval { DBI->connect($test_dsn, $test_user, $test_password, { PrintError => 1, RaiseError => 1, AutoCommit => 0, mysql_server_prepare => 1, mysql_server_prepare_disable_fallback => 1 }) }; plan skip_all => "no database connection" if $@ or not $dbh; plan tests => 17; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/DBD-mysql-4.039/t/40server_prepare_error.t new/DBD-mysql-4.040/t/40server_prepare_error.t --- old/DBD-mysql-4.039/t/40server_prepare_error.t 2016-11-08 14:30:17.000000000 +0100 +++ new/DBD-mysql-4.040/t/40server_prepare_error.t 2016-11-19 20:55:08.000000000 +0100 @@ -8,7 +8,7 @@ use vars qw($test_dsn $test_user $test_password); -$test_dsn.= ";mysql_server_prepare=1"; +$test_dsn.= ";mysql_server_prepare=1;mysql_server_prepare_disable_fallback=1"; my $dbh; eval {$dbh = DBI->connect($test_dsn, $test_user, $test_password, { RaiseError => 1, AutoCommit => 1})}; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/DBD-mysql-4.039/t/41int_min_max.t new/DBD-mysql-4.040/t/41int_min_max.t --- old/DBD-mysql-4.039/t/41int_min_max.t 2016-11-08 14:30:17.000000000 +0100 +++ new/DBD-mysql-4.040/t/41int_min_max.t 2016-11-19 20:55:08.000000000 +0100 @@ -22,7 +22,7 @@ "SKIP TEST: You must have MySQL version 4.1 and greater for this test to run"; } # nostrict tests + strict tests + init/tear down commands -plan tests => 19*8 + 17*8 + 4; +plan tests => (19*8 + 17*8 + 4) * 2; my $table = 'dbd_mysql_t41minmax'; # name of the table we will be using my $mode; # 'strict' or 'nostrict' corresponds to strict SQL mode @@ -117,6 +117,12 @@ }; } +$dbh->disconnect; + +for my $mysql_server_prepare (0, 1) { +$dbh= DBI->connect($test_dsn . ';mysql_server_prepare=' . $mysql_server_prepare, $test_user, $test_password, + { RaiseError => 1, PrintError => 1, AutoCommit => 0 }); + # Set strict SQL mode ok($dbh->do("SET SQL_MODE='STRICT_ALL_TABLES'"),"Enter strict SQL mode."); $mode = 'strict'; @@ -146,3 +152,4 @@ ok ($dbh->do("DROP TABLE $table")); ok $dbh->disconnect; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/DBD-mysql-4.039/t/50chopblanks.t new/DBD-mysql-4.040/t/50chopblanks.t --- old/DBD-mysql-4.039/t/50chopblanks.t 2016-11-08 14:30:17.000000000 +0100 +++ new/DBD-mysql-4.040/t/50chopblanks.t 2016-11-19 20:55:08.000000000 +0100 @@ -17,7 +17,7 @@ plan tests => 36 * 2; for my $mysql_server_prepare (0, 1) { -eval {$dbh= DBI->connect($test_dsn . ';mysql_server_prepare=' . $mysql_server_prepare, $test_user, $test_password, +eval {$dbh= DBI->connect("$test_dsn;mysql_server_prepare=$mysql_server_prepare;mysql_server_prepare_disable_fallback=1", $test_user, $test_password, { RaiseError => 1, PrintError => 1, AutoCommit => 1 });}; ok $dbh->do("DROP TABLE IF EXISTS dbd_mysql_t50chopblanks"), "drop table if exists dbd_mysql_t50chopblanks"; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/DBD-mysql-4.039/t/55utf8.t new/DBD-mysql-4.040/t/55utf8.t --- old/DBD-mysql-4.039/t/55utf8.t 2016-11-08 14:30:17.000000000 +0100 +++ new/DBD-mysql-4.040/t/55utf8.t 2016-11-19 20:55:08.000000000 +0100 @@ -25,7 +25,7 @@ plan tests => 16 * 2; for my $mysql_server_prepare (0, 1) { -$dbh= DBI->connect($test_dsn . ';mysql_server_prepare=' . $mysql_server_prepare, $test_user, $test_password, +$dbh= DBI->connect("$test_dsn;mysql_server_prepare=$mysql_server_prepare;mysql_server_prepare_disable_fallback=1", $test_user, $test_password, { RaiseError => 1, PrintError => 1, AutoCommit => 0 }); ok $dbh->do("DROP TABLE IF EXISTS dbd_mysql_t55utf8"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/DBD-mysql-4.039/t/60leaks.t new/DBD-mysql-4.040/t/60leaks.t --- old/DBD-mysql-4.039/t/60leaks.t 2016-11-08 14:30:17.000000000 +0100 +++ new/DBD-mysql-4.040/t/60leaks.t 2016-11-19 20:55:08.000000000 +0100 @@ -52,7 +52,7 @@ note "Testing memory leaks with mysql_server_prepare=$mysql_server_prepare\n"; $dbh= DBI->connect($test_dsn, $test_user, $test_password, - { RaiseError => 1, PrintError => 1, AutoCommit => 0, mysql_server_prepare => $mysql_server_prepare }); + { RaiseError => 1, PrintError => 1, AutoCommit => 0, mysql_server_prepare => $mysql_server_prepare, mysql_server_prepare_disable_fallback => 1 }); ok $dbh->do("DROP TABLE IF EXISTS dbd_mysql_t60leaks"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/DBD-mysql-4.039/t/99_bug_server_prepare_blob_null.t new/DBD-mysql-4.040/t/99_bug_server_prepare_blob_null.t --- old/DBD-mysql-4.039/t/99_bug_server_prepare_blob_null.t 2016-11-08 14:30:17.000000000 +0100 +++ new/DBD-mysql-4.040/t/99_bug_server_prepare_blob_null.t 2016-11-19 20:55:08.000000000 +0100 @@ -9,7 +9,7 @@ require 'lib.pl'; my $dbh; -$test_dsn .= ';mysql_server_prepare=1'; +$test_dsn .= ';mysql_server_prepare=1;mysql_server_prepare_disable_fallback=1'; eval {$dbh= DBI->connect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 1, AutoCommit => 0 });}; if ($@) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/DBD-mysql-4.039/t/rt88006-bit-prepare.t new/DBD-mysql-4.040/t/rt88006-bit-prepare.t --- old/DBD-mysql-4.039/t/rt88006-bit-prepare.t 2016-11-08 14:30:17.000000000 +0100 +++ new/DBD-mysql-4.040/t/rt88006-bit-prepare.t 2016-11-19 20:55:08.000000000 +0100 @@ -13,7 +13,7 @@ my $sth; my $dsn = $test_dsn; -$dsn .= ';mysql_server_prepare=1;' if $scenario eq 'prepare'; +$dsn .= ';mysql_server_prepare=1;mysql_server_prepare_disable_fallback=1' if $scenario eq 'prepare'; eval {$dbh = DBI->connect($dsn, $test_user, $test_password, { RaiseError => 1, AutoCommit => 1})};