Hello community, here is the log from the commit of package rubygem-mysql2 for openSUSE:Factory checked in at 2015-11-28 15:19:15 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/rubygem-mysql2 (Old) and /work/SRC/openSUSE:Factory/.rubygem-mysql2.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rubygem-mysql2" Changes: -------- --- /work/SRC/openSUSE:Factory/rubygem-mysql2/rubygem-mysql2.changes 2015-10-28 17:30:09.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.rubygem-mysql2.new/rubygem-mysql2.changes 2015-11-28 15:19:16.000000000 +0100 @@ -1,0 +2,6 @@ +Thu Nov 26 05:33:34 UTC 2015 - co...@suse.com + +- updated to version 0.4.2 + see installed CHANGELOG.md + +------------------------------------------------------------------- Old: ---- mysql2-0.4.1.gem New: ---- mysql2-0.4.2.gem ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ rubygem-mysql2.spec ++++++ --- /var/tmp/diff_new_pack.qeQR5P/_old 2015-11-28 15:19:17.000000000 +0100 +++ /var/tmp/diff_new_pack.qeQR5P/_new 2015-11-28 15:19:17.000000000 +0100 @@ -24,7 +24,7 @@ # Name: rubygem-mysql2 -Version: 0.4.1 +Version: 0.4.2 Release: 0 %define mod_name mysql2 %define mod_full_name %{mod_name}-%{version} ++++++ mysql2-0.4.1.gem -> mysql2-0.4.2.gem ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/README.md new/README.md --- old/README.md 1970-01-01 01:00:00.000000000 +0100 +++ new/README.md 1970-01-01 01:00:00.000000000 +0100 @@ -58,6 +58,20 @@ are located somewhere different than on your build system. This overrides any rpath calculated by default or by the options above. +* `--with-sanitize[=address,cfi,integer,memory,thread,undefined]` - +Enable sanitizers for Clang / GCC. If no argument is given, try to enable +all sanitizers or fail if none are available. If a command-separated list of +specific sanitizers is given, configure will fail unless they all are available. +Note that the some sanitizers may incur a performance penalty, and the Address +Sanitizer may require a runtime library. +To see line numbers in backtraces, declare these environment variables +(adjust the llvm-symbolizer path as needed for your system): + +``` sh + export ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer-3.4 + export ASAN_OPTIONS=symbolize=1 +``` + ### Linux and other Unixes You may need to install a package such as `libmysqlclient-dev` or `mysql-devel`; @@ -258,15 +272,26 @@ next_result: Unknown column 'A' in 'field list' (Mysql2::Error) ``` -See https://gist.github.com/1367987 for using MULTI_STATEMENTS with Active Record. - ### Secure auth Starting wih MySQL 5.6.5, secure_auth is enabled by default on servers (it was disabled by default prior to this). When secure_auth is enabled, the server will refuse a connection if the account password is stored in old pre-MySQL 4.1 format. The MySQL 5.6.5 client library may also refuse to attempt a connection if provided an older format password. -To bypass this restriction in the client, pass the option :secure_auth => false to Mysql2::Client.new(). -If using ActiveRecord, your database.yml might look something like this: +To bypass this restriction in the client, pass the option `:secure_auth => false` to Mysql2::Client.new(). + +### Flags option parsing + +The `:flags` parameter accepts an integer, a string, or an array. The integer +form allows the client to assemble flags from constants defined under +`Mysql2::Client` such as `Mysql2::Client::FOUND_ROWS`. Use a bitwise `|` (OR) +to specify several flags. + +The string form will be split on whitespace and parsed as with the array form: +Plain flags are added to the default flags, while flags prefixed with `-` +(minus) are removed from the default flags. + +This allows easier use with ActiveRecord's database.yml, avoiding the need for magic flag numbers. +For example, to disable protocol compression, and enable multiple statements and result sets: ``` yaml development: @@ -277,13 +302,17 @@ password: my_password host: 127.0.0.1 port: 3306 + flags: + - -COMPRESS + - FOUND_ROWS + - MULTI_STATEMENTS secure_auth: false ``` ### Reading a MySQL config file You may read configuration options from a MySQL configuration file by passing -the `:default_file` and `:default_group` paramters. For example: +the `:default_file` and `:default_group` parameters. For example: ``` ruby Mysql2::Client.new(:default_file => '/user/.my.cnf', :default_group => 'client') @@ -291,7 +320,7 @@ ### Initial command on connect and reconnect -If you specify the init_command option, the SQL string you provide will be executed after the connection is established. +If you specify the `:init_command` option, the SQL string you provide will be executed after the connection is established. If `:reconnect` is set to `true`, init_command will also be executed after a successful reconnect. It is useful if you want to provide session options which survive reconnection. Files old/checksums.yaml.gz and new/checksums.yaml.gz differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ext/mysql2/client.c new/ext/mysql2/client.c --- old/ext/mysql2/client.c 1970-01-01 01:00:00.000000000 +0100 +++ new/ext/mysql2/client.c 1970-01-01 01:00:00.000000000 +0100 @@ -133,7 +133,7 @@ static void *nogvl_init(void *ptr) { MYSQL *client; - mysql_client_wrapper *wrapper = (mysql_client_wrapper *)ptr; + mysql_client_wrapper *wrapper = ptr; /* may initialize embedded server and read /etc/services off disk */ client = mysql_init(wrapper->client); @@ -213,6 +213,7 @@ if (wrapper->client) { mysql_close(wrapper->client); + xfree(wrapper->client); wrapper->client = NULL; wrapper->connected = 0; wrapper->active_thread = Qnil; @@ -223,7 +224,7 @@ /* this is called during GC */ static void rb_mysql_client_free(void *ptr) { - mysql_client_wrapper *wrapper = (mysql_client_wrapper *)ptr; + mysql_client_wrapper *wrapper = ptr; decr_mysql2_client(wrapper); } @@ -249,7 +250,6 @@ #endif nogvl_close(wrapper); - xfree(wrapper->client); xfree(wrapper); } } @@ -437,10 +437,9 @@ } static void *nogvl_do_result(void *ptr, char use_result) { - mysql_client_wrapper *wrapper; + mysql_client_wrapper *wrapper = ptr; MYSQL_RES *result; - wrapper = (mysql_client_wrapper *)ptr; if (use_result) { result = mysql_use_result(wrapper->client); } else { @@ -533,14 +532,13 @@ } static VALUE do_query(void *args) { - struct async_query_args *async_args; + struct async_query_args *async_args = args; struct timeval tv; - struct timeval* tvp; + struct timeval *tvp; long int sec; int retval; VALUE read_timeout; - async_args = (struct async_query_args *)args; read_timeout = rb_iv_get(async_args->self, "@read_timeout"); tvp = NULL; @@ -578,11 +576,9 @@ } #else static VALUE finish_and_mark_inactive(void *args) { - VALUE self; + VALUE self = args; MYSQL_RES *result; - self = (VALUE)args; - GET_CLIENT(self); if (!NIL_P(wrapper->active_thread)) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ext/mysql2/extconf.rb new/ext/mysql2/extconf.rb --- old/ext/mysql2/extconf.rb 1970-01-01 01:00:00.000000000 +0100 +++ new/ext/mysql2/extconf.rb 1970-01-01 01:00:00.000000000 +0100 @@ -105,31 +105,55 @@ '-Wno-missing-field-initializers', # gperf generates bad code '-Wno-missing-variable-declarations', # missing symbols due to ruby native ext initialization '-Wno-padded', # mysql :( + '-Wno-reserved-id-macro', # rubby :( '-Wno-sign-conversion', # gperf generates bad code '-Wno-static-in-inline', # gperf generates bad code '-Wno-switch-enum', # result.c -- enum_field_types (when not fully covered, e.g. mysql 5.6+) '-Wno-undef', # rubinius :( + '-Wno-unreachable-code', # rubby :( '-Wno-used-but-marked-unused', # rubby :( ] -if ENV['CI'] - wishlist += [ - '-Werror', - '-fsanitize=address', - '-fsanitize=cfi', - '-fsanitize=integer', - '-fsanitize=memory', - '-fsanitize=thread', - '-fsanitize=undefined', - ] -end - usable_flags = wishlist.select do |flag| - try_link('int main() {return 0;}', flag) + try_link('int main() {return 0;}', "-Werror #{flag}") end $CFLAGS << ' ' << usable_flags.join(' ') +enabled_sanitizers = disabled_sanitizers = [] +# Specify a commna-separated list of sanitizers, or try them all by default +sanitizers = with_config('sanitize') +case sanitizers +when true + # Try them all, turn on whatever we can + enabled_sanitizers = %w(address cfi integer memory thread undefined).select do |s| + try_link('int main() {return 0;}', "-Werror -fsanitize=#{s}") + end + abort "-----\nCould not enable any sanitizers!\n-----" if enabled_sanitizers.empty? +when String + # Figure out which sanitizers are supported + enabled_sanitizers, disabled_sanitizers = sanitizers.split(',').partition do |s| + try_link('int main() {return 0;}', "-Werror -fsanitize=#{s}") + end +end + +unless disabled_sanitizers.empty? + abort "-----\nCould not enable requested sanitizers: #{disabled_sanitizers.join(',')}\n-----" +end + +unless enabled_sanitizers.empty? + warn "-----\nEnabling sanitizers: #{enabled_sanitizers.join(',')}\n-----" + enabled_sanitizers.each do |s| + # address sanitizer requires runtime support + if s == 'address' # rubocop:disable Style/IfUnlessModifier + have_library('asan') || $LDFLAGS << ' -fsanitize=address' + end + $CFLAGS << " -fsanitize=#{s}" + end + # Options for line numbers in backtraces + $CFLAGS << ' -g -fno-omit-frame-pointer' +end + if RUBY_PLATFORM =~ /mswin|mingw/ # Build libmysql.a interface link library require 'rake' @@ -155,8 +179,8 @@ # Make sure the generated interface library works (if cross-compiling, trust without verifying) unless RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ - abort "-----\nCannot find libmysql.a\n----" unless have_library('libmysql') - abort "-----\nCannot link to libmysql.a (my_init)\n----" unless have_func('my_init') + abort "-----\nCannot find libmysql.a\n-----" unless have_library('libmysql') + abort "-----\nCannot link to libmysql.a (my_init)\n-----" unless have_func('my_init') end # Vendor libmysql.dll diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ext/mysql2/result.c new/ext/mysql2/result.c --- old/ext/mysql2/result.c 1970-01-01 01:00:00.000000000 +0100 +++ new/ext/mysql2/result.c 1970-01-01 01:00:00.000000000 +0100 @@ -48,7 +48,7 @@ #define MYSQL2_MIN_TIME 62171150401ULL #endif -#define GET_RESULT(obj) \ +#define GET_RESULT(self) \ mysql2_result_wrapper *wrapper; \ Data_Get_Struct(self, mysql2_result_wrapper, wrapper); @@ -91,16 +91,18 @@ if (wrapper->resultFreed != 1) { if (wrapper->stmt_wrapper) { - mysql_stmt_free_result(wrapper->stmt_wrapper->stmt); + if (!wrapper->stmt_wrapper->closed) { + mysql_stmt_free_result(wrapper->stmt_wrapper->stmt); - /* MySQL BUG? If the statement handle was previously used, and so - * mysql_stmt_bind_result was called, and if that result set and bind buffers were freed, - * MySQL still thinks the result set buffer is available and will prefetch the - * first result in mysql_stmt_execute. This will corrupt or crash the program. - * By setting bind_result_done back to 0, we make MySQL think that a result set - * has never been bound to this statement handle before to prevent the prefetch. - */ - wrapper->stmt_wrapper->stmt->bind_result_done = 0; + /* MySQL BUG? If the statement handle was previously used, and so + * mysql_stmt_bind_result was called, and if that result set and bind buffers were freed, + * MySQL still thinks the result set buffer is available and will prefetch the + * first result in mysql_stmt_execute. This will corrupt or crash the program. + * By setting bind_result_done back to 0, we make MySQL think that a result set + * has never been bound to this statement handle before to prevent the prefetch. + */ + wrapper->stmt_wrapper->stmt->bind_result_done = 0; + } if (wrapper->result_buffers) { unsigned int i; @@ -203,7 +205,7 @@ #ifdef HAVE_RUBY_ENCODING_H static VALUE mysql2_set_field_string_encoding(VALUE val, MYSQL_FIELD field, rb_encoding *default_internal_enc, rb_encoding *conn_enc) { - /* if binary flag is set, respect it's wishes */ + /* if binary flag is set, respect its wishes */ if (field.flags & BINARY_FLAG && field.charsetnr == 63) { rb_enc_associate(val, binaryEncoding); } else if (!field.charsetnr) { @@ -309,11 +311,10 @@ case MYSQL_TYPE_SET: // char[] case MYSQL_TYPE_ENUM: // char[] case MYSQL_TYPE_GEOMETRY: // char[] + default: wrapper->result_buffers[i].buffer = xmalloc(fields[i].max_length); wrapper->result_buffers[i].buffer_length = fields[i].max_length; break; - default: - rb_raise(cMysql2Error, "unhandled mysql type: %d", fields[i].type); } wrapper->result_buffers[i].is_null = &wrapper->is_null[i]; @@ -491,14 +492,12 @@ case MYSQL_TYPE_SET: // char[] case MYSQL_TYPE_ENUM: // char[] case MYSQL_TYPE_GEOMETRY: // char[] + default: val = rb_str_new(result_buffer->buffer, *(result_buffer->length)); #ifdef HAVE_RUBY_ENCODING_H val = mysql2_set_field_string_encoding(val, fields[i], default_internal_enc, conn_enc); #endif break; - default: - rb_raise(cMysql2Error, "unhandled buffer type: %d", - result_buffer->buffer_type); } } @@ -858,6 +857,10 @@ GET_RESULT(self); + if (wrapper->stmt_wrapper && wrapper->stmt_wrapper->closed) { + rb_raise(cMysql2Error, "Statement handle already closed"); + } + defaults = rb_iv_get(self, "@query_options"); Check_Type(defaults, T_HASH); if (rb_scan_args(argc, argv, "01&", &opts, &block) == 1) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ext/mysql2/statement.c new/ext/mysql2/statement.c --- old/ext/mysql2/statement.c 1970-01-01 01:00:00.000000000 +0100 +++ new/ext/mysql2/statement.c 1970-01-01 01:00:00.000000000 +0100 @@ -8,18 +8,19 @@ #define GET_STATEMENT(self) \ mysql_stmt_wrapper *stmt_wrapper; \ Data_Get_Struct(self, mysql_stmt_wrapper, stmt_wrapper); \ - if (!stmt_wrapper->stmt) { rb_raise(cMysql2Error, "Invalid statement handle"); } + if (!stmt_wrapper->stmt) { rb_raise(cMysql2Error, "Invalid statement handle"); } \ + if (stmt_wrapper->closed) { rb_raise(cMysql2Error, "Statement handle already closed"); } static void rb_mysql_stmt_mark(void * ptr) { - mysql_stmt_wrapper* stmt_wrapper = (mysql_stmt_wrapper *)ptr; + mysql_stmt_wrapper *stmt_wrapper = ptr; if (!stmt_wrapper) return; rb_gc_mark(stmt_wrapper->client); } static void *nogvl_stmt_close(void * ptr) { - mysql_stmt_wrapper *stmt_wrapper = (mysql_stmt_wrapper *)ptr; + mysql_stmt_wrapper *stmt_wrapper = ptr; if (stmt_wrapper->stmt) { mysql_stmt_close(stmt_wrapper->stmt); stmt_wrapper->stmt = NULL; @@ -28,7 +29,7 @@ } static void rb_mysql_stmt_free(void * ptr) { - mysql_stmt_wrapper* stmt_wrapper = (mysql_stmt_wrapper *)ptr; + mysql_stmt_wrapper *stmt_wrapper = ptr; decr_mysql2_stmt(stmt_wrapper); } @@ -93,7 +94,7 @@ } VALUE rb_mysql_stmt_new(VALUE rb_client, VALUE sql) { - mysql_stmt_wrapper* stmt_wrapper; + mysql_stmt_wrapper *stmt_wrapper; VALUE rb_stmt; #ifdef HAVE_RUBY_ENCODING_H rb_encoding *conn_enc; @@ -105,6 +106,7 @@ { stmt_wrapper->client = rb_client; stmt_wrapper->refcount = 1; + stmt_wrapper->closed = 0; stmt_wrapper->stmt = NULL; } @@ -461,6 +463,7 @@ */ static VALUE rb_mysql_stmt_close(VALUE self) { GET_STATEMENT(self); + stmt_wrapper->closed = 1; rb_thread_call_without_gvl(nogvl_stmt_close, stmt_wrapper, RUBY_UBF_IO, 0); return Qnil; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ext/mysql2/statement.h new/ext/mysql2/statement.h --- old/ext/mysql2/statement.h 1970-01-01 01:00:00.000000000 +0100 +++ new/ext/mysql2/statement.h 1970-01-01 01:00:00.000000000 +0100 @@ -7,6 +7,7 @@ VALUE client; MYSQL_STMT *stmt; int refcount; + int closed; } mysql_stmt_wrapper; void init_mysql2_statement(void); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/mysql2/client.rb new/lib/mysql2/client.rb --- old/lib/mysql2/client.rb 1970-01-01 01:00:00.000000000 +0100 +++ new/lib/mysql2/client.rb 1970-01-01 01:00:00.000000000 +0100 @@ -10,7 +10,7 @@ :symbolize_keys => false, # return field names as symbols instead of strings :database_timezone => :local, # timezone Mysql2 will assume datetime objects are stored in :application_timezone => nil, # timezone Mysql2 will convert to before handing the object back to the caller - :cache_rows => true, # tells Mysql2 to use it's internal row cache for results + :cache_rows => true, # tells Mysql2 to use its internal row cache for results :connect_flags => REMEMBER_OPTIONS | LONG_PASSWORD | LONG_FLAG | TRANSACTIONS | PROTOCOL_41 | SECURE_CONNECTION, :cast => true, :default_file => nil, @@ -48,10 +48,18 @@ ssl_options = opts.values_at(:sslkey, :sslcert, :sslca, :sslcapath, :sslcipher) ssl_set(*ssl_options) if ssl_options.any? + case opts[:flags] + when Array + flags = parse_flags_array(opts[:flags], @query_options[:connect_flags]) + when String + flags = parse_flags_array(opts[:flags].split(' '), @query_options[:connect_flags]) + when Integer + flags = @query_options[:connect_flags] | opts[:flags] + else + flags = @query_options[:connect_flags] + end + # SSL verify is a connection flag rather than a mysql_ssl_set option - flags = 0 - flags |= @query_options[:connect_flags] - flags |= opts[:flags] if opts[:flags] flags |= SSL_VERIFY_SERVER_CERT if opts[:sslverify] && ssl_options.any? if [:user, :pass, :hostname, :dbname, :db, :sock].any? { |k| @query_options.key?(k) } @@ -79,6 +87,20 @@ connect user, pass, host, port, database, socket, flags end + def parse_flags_array(flags, initial = 0) + flags.reduce(initial) do |memo, f| + fneg = f.start_with?('-') ? f[1..-1] : nil + if fneg && fneg =~ /^\w+$/ && Mysql2::Client.const_defined?(fneg) + memo & ~ Mysql2::Client.const_get(fneg) + elsif f && f =~ /^\w+$/ && Mysql2::Client.const_defined?(f) + memo | Mysql2::Client.const_get(f) + else + warn "Unknown MySQL connection flag: '#{f}'" + memo + end + end + end + if Thread.respond_to?(:handle_interrupt) def query(sql, options = {}) Thread.handle_interrupt(::Mysql2::Util::TimeoutError => :never) do diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/mysql2/version.rb new/lib/mysql2/version.rb --- old/lib/mysql2/version.rb 1970-01-01 01:00:00.000000000 +0100 +++ new/lib/mysql2/version.rb 1970-01-01 01:00:00.000000000 +0100 @@ -1,3 +1,3 @@ module Mysql2 - VERSION = "0.4.1" + VERSION = "0.4.2" end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metadata new/metadata --- old/metadata 1970-01-01 01:00:00.000000000 +0100 +++ new/metadata 1970-01-01 01:00:00.000000000 +0100 @@ -1,7 +1,7 @@ --- !ruby/object:Gem::Specification name: mysql2 version: !ruby/object:Gem::Version - version: 0.4.1 + version: 0.4.2 platform: ruby authors: - Brian Lopez @@ -9,7 +9,7 @@ autorequire: bindir: bin cert_chain: [] -date: 2015-09-16 00:00:00.000000000 Z +date: 2015-11-25 00:00:00.000000000 Z dependencies: [] description: email: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec/mysql2/client_spec.rb new/spec/mysql2/client_spec.rb --- old/spec/mysql2/client_spec.rb 1970-01-01 01:00:00.000000000 +0100 +++ new/spec/mysql2/client_spec.rb 1970-01-01 01:00:00.000000000 +0100 @@ -43,27 +43,33 @@ }.not_to raise_error end - it "should accept connect flags and pass them to #connect" do - klient = Class.new(Mysql2::Client) do - attr_reader :connect_args - def connect(*args) - @connect_args ||= [] - @connect_args << args - end + Klient = Class.new(Mysql2::Client) do + attr_reader :connect_args + def connect(*args) + @connect_args ||= [] + @connect_args << args end - client = klient.new :flags => Mysql2::Client::FOUND_ROWS + end + + it "should accept connect flags and pass them to #connect" do + client = Klient.new :flags => Mysql2::Client::FOUND_ROWS expect(client.connect_args.last[6] & Mysql2::Client::FOUND_ROWS).to be > 0 end + it "should parse flags array" do + client = Klient.new :flags => %w( FOUND_ROWS -PROTOCOL_41 ) + expect(client.connect_args.last[6] & Mysql2::Client::FOUND_ROWS).to eql(Mysql2::Client::FOUND_ROWS) + expect(client.connect_args.last[6] & Mysql2::Client::PROTOCOL_41).to eql(0) + end + + it "should parse flags string" do + client = Klient.new :flags => "FOUND_ROWS -PROTOCOL_41" + expect(client.connect_args.last[6] & Mysql2::Client::FOUND_ROWS).to eql(Mysql2::Client::FOUND_ROWS) + expect(client.connect_args.last[6] & Mysql2::Client::PROTOCOL_41).to eql(0) + end + it "should default flags to (REMEMBER_OPTIONS, LONG_PASSWORD, LONG_FLAG, TRANSACTIONS, PROTOCOL_41, SECURE_CONNECTION)" do - klient = Class.new(Mysql2::Client) do - attr_reader :connect_args - def connect(*args) - @connect_args ||= [] - @connect_args << args - end - end - client = klient.new + client = Klient.new client_flags = Mysql2::Client::REMEMBER_OPTIONS | Mysql2::Client::LONG_PASSWORD | Mysql2::Client::LONG_FLAG |