Hello community, here is the log from the commit of package rubygem-mysql2 for openSUSE:Factory checked in at 2016-11-07 12:23:28 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 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 2016-05-29 03:12:47.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.rubygem-mysql2.new/rubygem-mysql2.changes 2016-11-07 12:23:29.000000000 +0100 @@ -1,0 +2,6 @@ +Sun Oct 23 04:39:33 UTC 2016 - [email protected] + +- updated to version 0.4.5 + see installed CHANGELOG.md + +------------------------------------------------------------------- Old: ---- mysql2-0.4.4.gem New: ---- mysql2-0.4.5.gem ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ rubygem-mysql2.spec ++++++ --- /var/tmp/diff_new_pack.q0Gphg/_old 2016-11-07 12:23:30.000000000 +0100 +++ /var/tmp/diff_new_pack.q0Gphg/_new 2016-11-07 12:23:30.000000000 +0100 @@ -24,7 +24,7 @@ # Name: rubygem-mysql2 -Version: 0.4.4 +Version: 0.4.5 Release: 0 %define mod_name mysql2 %define mod_full_name %{mod_name}-%{version} ++++++ mysql2-0.4.4.gem -> mysql2-0.4.5.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 @@ -164,8 +164,8 @@ ``` ruby headers = results.fields # <= that's an array of field names, in order results.each(:as => :array) do |row| -# Each row is an array, ordered the same as the query results -# An otter's den is called a "holt" or "couch" + # Each row is an array, ordered the same as the query results + # An otter's den is called a "holt" or "couch" end ``` @@ -203,6 +203,7 @@ :reconnect = true/false, :local_infile = true/false, :secure_auth = true/false, + :ssl_mode = :disabled / :preferred / :required / :verify_ca / :verify_identity, :default_file = '/path/to/my.cfg', :default_group = 'my.cfg section', :init_command => sql @@ -398,6 +399,15 @@ result = client.query("SELECT * FROM table_with_boolean_field", :cast_booleans => true) ``` +Keep in mind that this works only with fields and not with computed values, e.g. this result will contain `1`, not `true`: + +``` ruby +client = Mysql2::Client.new +result = client.query("SELECT true", :cast_booleans => true) +``` + +CAST function wouldn't help here as there's no way to cast to TINYINT(1). Apparently the only way to solve this is to use a stored procedure with return type set to TINYINT(1). + ### Skipping casting Mysql2 casting is fast, but not as fast as not casting data. In rare cases where typecasting is not needed, it will be faster to disable it by providing :cast => false. (Note that :cast => false overrides :cast_booleans => true.) @@ -484,13 +494,13 @@ This gem is tested with the following Ruby versions on Linux and Mac OS X: - * Ruby MRI 1.8.7, 1.9.3, 2.0.0, 2.1.x, 2.2.x, 2.3.x + * Ruby MRI 1.8.7, 1.9.3, 2.0.0, 2.1.x, 2.2.x, 2.3.x, 2.4.x * Ruby Enterprise Edition (based on MRI 1.8.7) - * Rubinius 2.x, 3.x + * Rubinius 2.x and 3.x do work but may fail under some workloads This gem is tested with the following MySQL and MariaDB versions: - * MySQL 5.5, 5.6, 5.7 + * MySQL 5.5, 5.6, 5.7, 8.0 * MySQL Connector/C 6.0 and 6.1 (primarily on Windows) * MariaDB 5.5, 10.0, 10.1 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 @@ -30,6 +30,12 @@ rb_raise(cMysql2Error, "MySQL client is not initialized"); \ } +#define REQUIRE_CONNECTED(wrapper) \ + REQUIRE_INITIALIZED(wrapper) \ + if (!wrapper->connected && !wrapper->reconnect_enabled) { \ + rb_raise(cMysql2Error, "MySQL client is not connected"); \ + } + #define REQUIRE_NOT_CONNECTED(wrapper) \ REQUIRE_INITIALIZED(wrapper) \ if (wrapper->connected) { \ @@ -48,6 +54,16 @@ #endif /* + * compatibility with mysql-connector-c 6.1.x, and with MySQL 5.7.3 - 5.7.10. + */ +#ifdef HAVE_CONST_MYSQL_OPT_SSL_ENFORCE + #define SSL_MODE_DISABLED 1 + #define SSL_MODE_REQUIRED 3 + #define HAVE_CONST_SSL_MODE_DISABLED + #define HAVE_CONST_SSL_MODE_REQUIRED +#endif + +/* * used to pass all arguments to mysql_real_connect while inside * rb_thread_call_without_gvl */ @@ -83,6 +99,43 @@ char *db; }; +static VALUE rb_set_ssl_mode_option(VALUE self, VALUE setting) { + unsigned long version = mysql_get_client_version(); + + if (version < 50703) { + rb_warn( "Your mysql client library does not support setting ssl_mode; full support comes with 5.7.11." ); + return Qnil; + } +#ifdef HAVE_CONST_MYSQL_OPT_SSL_ENFORCE + GET_CLIENT(self); + int val = NUM2INT( setting ); + if (version >= 50703 && version < 50711) { + if (val == SSL_MODE_DISABLED || val == SSL_MODE_REQUIRED) { + my_bool b = ( val == SSL_MODE_REQUIRED ); + int result = mysql_options( wrapper->client, MYSQL_OPT_SSL_ENFORCE, &b ); + return INT2NUM(result); + + } else { + rb_warn( "MySQL client libraries between 5.7.3 and 5.7.10 only support SSL_MODE_DISABLED and SSL_MODE_REQUIRED" ); + return Qnil; + } + } +#endif +#ifdef FULL_SSL_MODE_SUPPORT + GET_CLIENT(self); + int val = NUM2INT( setting ); + + if (val != SSL_MODE_DISABLED && val != SSL_MODE_PREFERRED && val != SSL_MODE_REQUIRED && val != SSL_MODE_VERIFY_CA && val != SSL_MODE_VERIFY_IDENTITY) { + rb_raise(cMysql2Error, "ssl_mode= takes DISABLED, PREFERRED, REQUIRED, VERIFY_CA, VERIFY_IDENTITY, you passed: %d", val ); + } + int result = mysql_options( wrapper->client, MYSQL_OPT_SSL_MODE, &val ); + + return INT2NUM(result); +#endif +#ifdef NO_SSL_MODE_SUPPORT + return Qnil; +#endif +} /* * non-blocking mysql_*() functions that we won't be wrapping since * they do not appear to hit the network nor issue any interruptible @@ -1192,6 +1245,7 @@ #endif GET_CLIENT(self); + Check_Type(value, T_STRING); charset_name = RSTRING_PTR(value); #ifdef HAVE_RUBY_ENCODING_H @@ -1337,6 +1391,7 @@ rb_define_private_method(cMysql2Client, "default_group=", set_read_default_group, 1); rb_define_private_method(cMysql2Client, "init_command=", set_init_command, 1); rb_define_private_method(cMysql2Client, "ssl_set", set_ssl_options, 5); + rb_define_private_method(cMysql2Client, "ssl_mode=", rb_set_ssl_mode_option, 1); rb_define_private_method(cMysql2Client, "initialize_ext", initialize_ext, 0); rb_define_private_method(cMysql2Client, "connect", rb_connect, 7); rb_define_private_method(cMysql2Client, "_query", rb_query, 2); @@ -1464,4 +1519,31 @@ rb_const_set(cMysql2Client, rb_intern("BASIC_FLAGS"), LONG2NUM(CLIENT_BASIC_FLAGS)); #endif + +#if defined(FULL_SSL_MODE_SUPPORT) // MySQL 5.7.11 and above + rb_const_set(cMysql2Client, rb_intern("SSL_MODE_DISABLED"), INT2NUM(SSL_MODE_DISABLED)); + rb_const_set(cMysql2Client, rb_intern("SSL_MODE_PREFERRED"), INT2NUM(SSL_MODE_PREFERRED)); + rb_const_set(cMysql2Client, rb_intern("SSL_MODE_REQUIRED"), INT2NUM(SSL_MODE_REQUIRED)); + rb_const_set(cMysql2Client, rb_intern("SSL_MODE_VERIFY_CA"), INT2NUM(SSL_MODE_VERIFY_CA)); + rb_const_set(cMysql2Client, rb_intern("SSL_MODE_VERIFY_IDENTITY"), INT2NUM(SSL_MODE_VERIFY_IDENTITY)); +#elif defined(HAVE_CONST_MYSQL_OPT_SSL_ENFORCE) // MySQL 5.7.3 - 5.7.10 + rb_const_set(cMysql2Client, rb_intern("SSL_MODE_DISABLED"), INT2NUM(SSL_MODE_DISABLED)); + rb_const_set(cMysql2Client, rb_intern("SSL_MODE_REQUIRED"), INT2NUM(SSL_MODE_REQUIRED)); +#endif + +#ifndef HAVE_CONST_SSL_MODE_DISABLED + rb_const_set(cMysql2Client, rb_intern("SSL_MODE_DISABLED"), INT2NUM(0)); +#endif +#ifndef HAVE_CONST_SSL_MODE_PREFERRED + rb_const_set(cMysql2Client, rb_intern("SSL_MODE_PREFERRED"), INT2NUM(0)); +#endif +#ifndef HAVE_CONST_SSL_MODE_REQUIRED + rb_const_set(cMysql2Client, rb_intern("SSL_MODE_REQUIRED"), INT2NUM(0)); +#endif +#ifndef HAVE_CONST_SSL_MODE_VERIFY_CA + rb_const_set(cMysql2Client, rb_intern("SSL_MODE_VERIFY_CA"), INT2NUM(0)); +#endif +#ifndef HAVE_CONST_SSL_MODE_VERIFY_IDENTITY + rb_const_set(cMysql2Client, rb_intern("SSL_MODE_VERIFY_IDENTITY"), INT2NUM(0)); +#endif } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ext/mysql2/client.h new/ext/mysql2/client.h --- old/ext/mysql2/client.h 1970-01-01 01:00:00.000000000 +0100 +++ new/ext/mysql2/client.h 1970-01-01 01:00:00.000000000 +0100 @@ -51,12 +51,6 @@ MYSQL *client; } mysql_client_wrapper; -#define REQUIRE_CONNECTED(wrapper) \ - REQUIRE_INITIALIZED(wrapper) \ - if (!wrapper->connected && !wrapper->reconnect_enabled) { \ - rb_raise(cMysql2Error, "closed MySQL connection"); \ - } - void rb_mysql_client_set_active_thread(VALUE self); #define GET_CLIENT(self) \ 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 @@ -12,6 +12,20 @@ end end +def add_ssl_defines(header) + all_modes_found = %w(SSL_MODE_DISABLED SSL_MODE_PREFERRED SSL_MODE_REQUIRED SSL_MODE_VERIFY_CA SSL_MODE_VERIFY_IDENTITY).inject(true) do |m, ssl_mode| + m && have_const(ssl_mode, header) + end + $CFLAGS << ' -DFULL_SSL_MODE_SUPPORT' if all_modes_found + # if we only have ssl toggle (--ssl,--disable-ssl) from 5.7.3 to 5.7.10 + has_no_support = all_modes_found ? false : !have_const('MYSQL_OPT_SSL_ENFORCE', header) + $CFLAGS << ' -DNO_SSL_MODE_SUPPORT' if has_no_support +end + +# 2.1+ +have_func('rb_absint_size') +have_func('rb_absint_singlebit_p') + # 2.0-only have_header('ruby/thread.h') && have_func('rb_thread_call_without_gvl', 'ruby/thread.h') @@ -20,6 +34,7 @@ have_func('rb_wait_for_single_fd') have_func('rb_hash_dup') have_func('rb_intern3') +have_func('rb_big_cmp') # borrowed from mysqlplus # http://github.com/oldmoe/mysqlplus/blob/master/ext/extconf.rb @@ -37,6 +52,9 @@ /usr/local/opt/mysql5* ).map { |dir| dir << '/bin' } +# For those without HOMEBREW_ROOT in PATH +dirs << "#{ENV['HOMEBREW_ROOT']}/bin" if ENV['HOMEBREW_ROOT'] + GLOB = "{#{dirs.join(',')}}/{mysql_config,mysql_config5,mariadb_config}" # If the user has provided a --with-mysql-dir argument, we must respect it or fail. @@ -87,6 +105,8 @@ asplode 'mysql.h' end +add_ssl_defines([prefix, 'mysql.h'].compact.join('/')) + %w(errmsg.h mysqld_error.h).each do |h| header = [prefix, h].compact.join '/' asplode h unless have_header header 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 @@ -920,6 +920,9 @@ wrapper->numberOfRows = wrapper->stmt_wrapper ? mysql_stmt_num_rows(wrapper->stmt_wrapper->stmt) : mysql_num_rows(wrapper->result); wrapper->rows = rb_ary_new2(wrapper->numberOfRows); } else if (wrapper->rows && !cacheRows) { + if (wrapper->resultFreed) { + rb_raise(cMysql2Error, "Result set has already been freed"); + } mysql_data_seek(wrapper->result, 0); wrapper->lastRowProcessed = 0; wrapper->rows = rb_ary_new2(wrapper->numberOfRows); 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 @@ -2,8 +2,11 @@ VALUE cMysql2Statement; extern VALUE mMysql2, cMysql2Error, cBigDecimal, cDateTime, cDate; -static VALUE sym_stream, intern_new_with_args, intern_each; -static VALUE intern_usec, intern_sec, intern_min, intern_hour, intern_day, intern_month, intern_year, intern_to_s; +static VALUE sym_stream, intern_new_with_args, intern_each, intern_to_s; +static VALUE intern_sec_fraction, intern_usec, intern_sec, intern_min, intern_hour, intern_day, intern_month, intern_year; +#ifndef HAVE_RB_BIG_CMP +static ID id_cmp; +#endif #define GET_STATEMENT(self) \ mysql_stmt_wrapper *stmt_wrapper; \ @@ -180,7 +183,6 @@ static void set_buffer_for_string(MYSQL_BIND* bind_buffer, unsigned long *length_buffer, VALUE string) { unsigned long length; - bind_buffer->buffer_type = MYSQL_TYPE_STRING; bind_buffer->buffer = RSTRING_PTR(string); length = RSTRING_LEN(string); @@ -204,6 +206,50 @@ xfree(length_buffers); \ } +/* return 0 if the given bignum can cast as LONG_LONG, otherwise 1 */ +static int my_big2ll(VALUE bignum, LONG_LONG *ptr) +{ + unsigned LONG_LONG num; + size_t len; +#ifdef HAVE_RB_ABSINT_SIZE + int nlz_bits = 0; + len = rb_absint_size(bignum, &nlz_bits); +#else + len = RBIGNUM_LEN(bignum) * SIZEOF_BDIGITS; +#endif + if (len > sizeof(LONG_LONG)) goto overflow; + if (RBIGNUM_POSITIVE_P(bignum)) { + num = rb_big2ull(bignum); + if (num > LLONG_MAX) + goto overflow; + *ptr = num; + } + else { + if (len == 8 && +#ifdef HAVE_RB_ABSINT_SIZE + nlz_bits == 0 && +#endif +#if defined(HAVE_RB_ABSINT_SIZE) && defined(HAVE_RB_ABSINT_SINGLEBIT_P) + /* Optimized to avoid object allocation for Ruby 2.1+ + * only -0x8000000000000000 is safe if `len == 8 && nlz_bits == 0` + */ + !rb_absint_singlebit_p(bignum) +#elif defined(HAVE_RB_BIG_CMP) + rb_big_cmp(bignum, LL2NUM(LLONG_MIN)) == INT2FIX(-1) +#else + /* Ruby 1.8.7 and REE doesn't have rb_big_cmp */ + rb_funcall(bignum, id_cmp, 1, LL2NUM(LLONG_MIN)) == INT2FIX(-1) +#endif + ) { + goto overflow; + } + *ptr = rb_big2ll(bignum); + } + return 0; +overflow: + return 1; +} + /* call-seq: stmt.execute * * Executes the current prepared statement, returns +result+. @@ -265,9 +311,23 @@ #endif break; case T_BIGNUM: - bind_buffers[i].buffer_type = MYSQL_TYPE_LONGLONG; - bind_buffers[i].buffer = xmalloc(sizeof(long long int)); - *(LONG_LONG*)(bind_buffers[i].buffer) = rb_big2ll(argv[i]); + { + LONG_LONG num; + if (my_big2ll(argv[i], &num) == 0) { + bind_buffers[i].buffer_type = MYSQL_TYPE_LONGLONG; + bind_buffers[i].buffer = xmalloc(sizeof(long long int)); + *(LONG_LONG*)(bind_buffers[i].buffer) = num; + } else { + /* The bignum was larger than we can fit in LONG_LONG, send it as a string */ + VALUE rb_val_as_string = rb_big2str(argv[i], 10); + bind_buffers[i].buffer_type = MYSQL_TYPE_NEWDECIMAL; + params_enc[i] = rb_val_as_string; +#ifdef HAVE_RUBY_ENCODING_H + params_enc[i] = rb_str_export_to_enc(params_enc[i], conn_enc); +#endif + set_buffer_for_string(&bind_buffers[i], &length_buffers[i], params_enc[i]); + } + } break; case T_FLOAT: bind_buffers[i].buffer_type = MYSQL_TYPE_DOUBLE; @@ -275,13 +335,13 @@ *(double*)(bind_buffers[i].buffer) = NUM2DBL(argv[i]); break; case T_STRING: - { - params_enc[i] = argv[i]; + bind_buffers[i].buffer_type = MYSQL_TYPE_STRING; + + params_enc[i] = argv[i]; #ifdef HAVE_RUBY_ENCODING_H - params_enc[i] = rb_str_export_to_enc(params_enc[i], conn_enc); + params_enc[i] = rb_str_export_to_enc(params_enc[i], conn_enc); #endif - set_buffer_for_string(&bind_buffers[i], &length_buffers[i], params_enc[i]); - } + set_buffer_for_string(&bind_buffers[i], &length_buffers[i], params_enc[i]); break; default: // TODO: what Ruby type should support MYSQL_TYPE_TIME @@ -294,7 +354,13 @@ memset(&t, 0, sizeof(MYSQL_TIME)); t.neg = 0; - t.second_part = FIX2INT(rb_funcall(rb_time, intern_usec, 0)); + + if (CLASS_OF(argv[i]) == rb_cTime) { + t.second_part = FIX2INT(rb_funcall(rb_time, intern_usec, 0)); + } else if (CLASS_OF(argv[i]) == cDateTime) { + t.second_part = NUM2DBL(rb_funcall(rb_time, intern_sec_fraction, 0)) * 1000000; + } + t.second = FIX2INT(rb_funcall(rb_time, intern_sec, 0)); t.minute = FIX2INT(rb_funcall(rb_time, intern_min, 0)); t.hour = FIX2INT(rb_funcall(rb_time, intern_hour, 0)); @@ -492,6 +558,7 @@ intern_new_with_args = rb_intern("new_with_args"); intern_each = rb_intern("each"); + intern_sec_fraction = rb_intern("sec_fraction"); intern_usec = rb_intern("usec"); intern_sec = rb_intern("sec"); intern_min = rb_intern("min"); @@ -501,4 +568,7 @@ intern_year = rb_intern("year"); intern_to_s = rb_intern("to_s"); +#ifndef HAVE_RB_BIG_CMP + id_cmp = rb_intern("<=>"); +#endif } 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 @@ -19,6 +19,7 @@ end def initialize(opts = {}) + fail Mysql2::Error, "Options parameter must be a Hash" unless opts.is_a? Hash opts = Mysql2::Util.key_hash_as_symbols(opts) @read_timeout = nil @query_options = self.class.default_query_options.dup @@ -36,7 +37,7 @@ when :reconnect, :local_infile, :secure_auth, :automatic_close send(:"#{key}=", !!opts[key]) # rubocop:disable Style/DoubleNegation when :connect_timeout, :read_timeout, :write_timeout - send(:"#{key}=", opts[key]) unless opts[key].nil? + send(:"#{key}=", opts[key].to_i) unless opts[key].nil? else send(:"#{key}=", opts[key]) end @@ -47,6 +48,7 @@ ssl_options = opts.values_at(:sslkey, :sslcert, :sslca, :sslcapath, :sslcipher) ssl_set(*ssl_options) if ssl_options.any? + self.ssl_mode = parse_ssl_mode(opts[:ssl_mode]) if opts[:ssl_mode] case opts[:flags] when Array @@ -87,6 +89,17 @@ connect user, pass, host, port, database, socket, flags end + def parse_ssl_mode(mode) + m = mode.to_s.upcase + if m.start_with?('SSL_MODE_') + return Mysql2::Client.const_get(m) if Mysql2::Client.const_defined?(m) + else + x = 'SSL_MODE_' + m + return Mysql2::Client.const_get(x) if Mysql2::Client.const_defined?(x) + end + warn "Unknown MySQL ssl_mode flag: #{mode}" + end + def parse_flags_array(flags, initial = 0) flags.reduce(initial) do |memo, f| fneg = f.start_with?('-') ? f[1..-1] : nil 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.4" + VERSION = "0.4.5" 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.4 + version: 0.4.5 platform: ruby authors: - Brian Lopez @@ -9,7 +9,7 @@ autorequire: bindir: bin cert_chain: [] -date: 2016-04-19 00:00:00.000000000 Z +date: 2016-10-22 00:00:00.000000000 Z dependencies: [] description: email: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec/configuration.yml.example new/spec/configuration.yml.example --- old/spec/configuration.yml.example 1970-01-01 01:00:00.000000000 +0100 +++ new/spec/configuration.yml.example 1970-01-01 01:00:00.000000000 +0100 @@ -9,9 +9,3 @@ username: LOCALUSERNAME password: database: mysql2_test - -numericuser: - host: localhost - username: LOCALUSERNAME - password: - database: 12345 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 @@ -1,6 +1,5 @@ # encoding: UTF-8 require 'spec_helper' -require 'stringio' RSpec.describe Mysql2::Client do context "using defaults file" do @@ -34,6 +33,12 @@ }.to raise_error(Mysql2::Error) end + it "should raise an exception on non-string encodings" do + expect { + Mysql2::Client.new(DatabaseCredentials['root'].merge(:encoding => :fake)) + }.to raise_error(TypeError) + end + it "should not raise an exception on create for a valid encoding" do expect { Mysql2::Client.new(DatabaseCredentials['root'].merge(:encoding => "utf8")) @@ -200,22 +205,21 @@ if RUBY_PLATFORM =~ /mingw|mswin/ it "cannot be disabled" do - stderr, $stderr = $stderr, StringIO.new - - begin - Mysql2::Client.new(DatabaseCredentials['root'].merge(:automatic_close => false)) - expect($stderr.string).to include('always closed by garbage collector') - $stderr.reopen + expect do + client = Mysql2::Client.new(DatabaseCredentials['root'].merge(:automatic_close => false)) + expect(client.automatic_close?).to be(true) + end.to output(/always closed by garbage collector/).to_stderr + + expect do + client = Mysql2::Client.new(DatabaseCredentials['root'].merge(:automatic_close => true)) + expect(client.automatic_close?).to be(true) + end.to_not output(/always closed by garbage collector/).to_stderr - client = Mysql2::Client.new(DatabaseCredentials['root']) + expect do + client = Mysql2::Client.new(DatabaseCredentials['root'].merge(:automatic_close => true)) client.automatic_close = false - expect($stderr.string).to include('always closed by garbage collector') - $stderr.reopen - - expect { client.automatic_close = true }.to_not change { $stderr.string } - ensure - $stderr = stderr - end + expect(client.automatic_close?).to be(true) + end.to output(/always closed by garbage collector/).to_stderr end else it "can be configured" do @@ -263,13 +267,14 @@ end it "should be able to connect to database with numeric-only name" do - creds = DatabaseCredentials['numericuser'] - @client.query "CREATE DATABASE IF NOT EXISTS `#{creds['database']}`" - @client.query "GRANT ALL ON `#{creds['database']}`.* TO #{creds['username']}@`#{creds['host']}`" + database = 1235 + @client.query "CREATE DATABASE IF NOT EXISTS `#{database}`" - expect { Mysql2::Client.new(creds) }.not_to raise_error + expect { + Mysql2::Client.new(DatabaseCredentials['root'].merge('database' => database)) + }.not_to raise_error - @client.query "DROP DATABASE IF EXISTS `#{creds['database']}`" + @client.query "DROP DATABASE IF EXISTS `#{database}`" end it "should respond to #close" do @@ -559,7 +564,7 @@ context 'when a non-standard exception class is raised' do it "should close the connection when an exception is raised" do expect { Timeout.timeout(0.1, ArgumentError) { @client.query('SELECT SLEEP(1)') } }.to raise_error(ArgumentError) - expect { @client.query('SELECT 1') }.to raise_error(Mysql2::Error, 'closed MySQL connection') + expect { @client.query('SELECT 1') }.to raise_error(Mysql2::Error, 'MySQL client is not connected') end it "should handle Timeouts without leaving the connection hanging if reconnect is true" do diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec/mysql2/error_spec.rb new/spec/mysql2/error_spec.rb --- old/spec/mysql2/error_spec.rb 1970-01-01 01:00:00.000000000 +0100 +++ new/spec/mysql2/error_spec.rb 1970-01-01 01:00:00.000000000 +0100 @@ -34,7 +34,7 @@ end end - let(:invalid_utf8) { "\xE5\xC6\x7D\x1F" } + let(:invalid_utf8) { ["e5c67d1f"].pack('H*').force_encoding(Encoding::UTF_8) } let(:bad_err) do begin client.query(invalid_utf8) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec/mysql2/statement_spec.rb new/spec/mysql2/statement_spec.rb --- old/spec/mysql2/statement_spec.rb 1970-01-01 01:00:00.000000000 +0100 +++ new/spec/mysql2/statement_spec.rb 1970-01-01 01:00:00.000000000 +0100 @@ -6,11 +6,13 @@ @client = Mysql2::Client.new(DatabaseCredentials['root'].merge(:encoding => "utf8")) end + def stmt_count + @client.query("SHOW STATUS LIKE 'Prepared_stmt_count'").first['Value'].to_i + end + it "should create a statement" do statement = nil - expect { statement = @client.prepare 'SELECT 1' }.to change { - @client.query("SHOW STATUS LIKE 'Prepared_stmt_count'").first['Value'].to_i - }.by(1) + expect { statement = @client.prepare 'SELECT 1' }.to change(&method(:stmt_count)).by(1) expect(statement).to be_an_instance_of(Mysql2::Statement) end @@ -59,6 +61,26 @@ expect(rows).to eq([{ "1" => 1 }]) end + it "should handle bignum but in int64_t" do + stmt = @client.prepare('SELECT ? AS max, ? AS min') + int64_max = (1 << 63) - 1 + int64_min = -(1 << 63) + result = stmt.execute(int64_max, int64_min) + expect(result.to_a).to eq(['max' => int64_max, 'min' => int64_min]) + end + + it "should handle bignum but beyond int64_t" do + stmt = @client.prepare('SELECT ? AS max1, ? AS max2, ? AS max3, ? AS min1, ? AS min2, ? AS min3') + int64_max1 = (1 << 63) + int64_max2 = (1 << 64) - 1 + int64_max3 = 1 << 64 + int64_min1 = -(1 << 63) - 1 + int64_min2 = -(1 << 64) + 1 + int64_min3 = -0xC000000000000000 + result = stmt.execute(int64_max1, int64_max2, int64_max3, int64_min1, int64_min2, int64_min3) + expect(result.to_a).to eq(['max1' => int64_max1, 'max2' => int64_max2, 'max3' => int64_max3, 'min1' => int64_min1, 'min2' => int64_min2, 'min3' => int64_min3]) + end + it "should keep its result after other query" do @client.query 'USE test' @client.query 'CREATE TABLE IF NOT EXISTS mysql2_stmt_q(a int)' @@ -108,6 +130,35 @@ expect(result.first.first[1]).to be_an_instance_of(Time) end + it "should prepare Date values" do + now = Date.today + statement = @client.prepare('SELECT ? AS a') + result = statement.execute(now) + expect(result.first['a'].to_s).to eql(now.strftime('%F')) + end + + it "should prepare Time values with microseconds" do + now = Time.now + statement = @client.prepare('SELECT ? AS a') + result = statement.execute(now) + if RUBY_VERSION =~ /1.8/ + expect(result.first['a'].strftime('%F %T %z')).to eql(now.strftime('%F %T %z')) + else + expect(result.first['a'].strftime('%F %T.%6N %z')).to eql(now.strftime('%F %T.%6N %z')) + end + end + + it "should prepare DateTime values with microseconds" do + now = DateTime.now + statement = @client.prepare('SELECT ? AS a') + result = statement.execute(now) + if RUBY_VERSION =~ /1.8/ + expect(result.first['a'].strftime('%F %T %z')).to eql(now.strftime('%F %T %z')) + else + expect(result.first['a'].strftime('%F %T.%6N %z')).to eql(now.strftime('%F %T.%6N %z')) + end + end + it "should tell us about the fields" do statement = @client.prepare 'SELECT 1 as foo, 2' statement.execute @@ -117,6 +168,13 @@ expect(list[1]).to eq('2') end + it "should handle as a decimal binding a BigDecimal" do + stmt = @client.prepare('SELECT ? AS decimal_test') + test_result = stmt.execute(BigDecimal.new("123.45")).first + expect(test_result['decimal_test']).to be_an_instance_of(BigDecimal) + expect(test_result['decimal_test']).to eql(123.45) + end + it "should update a DECIMAL value passing a BigDecimal" do @client.query 'USE test' @client.query 'DROP TABLE IF EXISTS mysql2_stmt_decimal_test' @@ -689,9 +747,7 @@ context 'close' do it 'should free server resources' do stmt = @client.prepare 'SELECT 1' - expect { stmt.close }.to change { - @client.query("SHOW STATUS LIKE 'Prepared_stmt_count'").first['Value'].to_i - }.by(-1) + expect { stmt.close }.to change(&method(:stmt_count)).by(-1) end it 'should raise an error on subsequent execution' do diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec/ssl/gen_certs.sh new/spec/ssl/gen_certs.sh --- old/spec/ssl/gen_certs.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/spec/ssl/gen_certs.sh 1970-01-01 01:00:00.000000000 +0100 @@ -1,6 +1,6 @@ #!/usr/bin/env bash -set -eu +set -eux echo " [ ca ]
