diff --git a/ext/mysql2/result.c b/ext/mysql2/result.c index c227c41fa..ccb49a5b7 100644 --- a/ext/mysql2/result.c +++ b/ext/mysql2/result.c @@ -405,6 +405,13 @@ static VALUE rb_mysql_result_fetch_row_stmt(VALUE self, MYSQL_FIELD * fields, co val = INT2NUM(*((signed char*)result_buffer->buffer)); } break; + case MYSQL_TYPE_BIT: /* BIT field (MySQL 5.0.3 and up) */ + if (args->castBool && fields[i].length == 1) { + val = (*((unsigned char*)result_buffer->buffer) != 0) ? Qtrue : Qfalse; + }else{ + val = rb_str_new(result_buffer->buffer, *(result_buffer->length)); + } + break; case MYSQL_TYPE_SHORT: // short int if (result_buffer->is_unsigned) { val = UINT2NUM(*((unsigned short int*)result_buffer->buffer)); @@ -494,7 +501,6 @@ static VALUE rb_mysql_result_fetch_row_stmt(VALUE self, MYSQL_FIELD * fields, co case MYSQL_TYPE_BLOB: // char[] case MYSQL_TYPE_MEDIUM_BLOB: // char[] case MYSQL_TYPE_LONG_BLOB: // char[] - case MYSQL_TYPE_BIT: // char[] case MYSQL_TYPE_SET: // char[] case MYSQL_TYPE_ENUM: // char[] case MYSQL_TYPE_GEOMETRY: // char[] diff --git a/spec/mysql2/client_spec.rb b/spec/mysql2/client_spec.rb index 44c311db7..dfb92a2df 100644 --- a/spec/mysql2/client_spec.rb +++ b/spec/mysql2/client_spec.rb @@ -604,7 +604,7 @@ def run_gc end it "should handle Timeouts without leaving the connection hanging if reconnect is true" do - if RUBY_PLATFORM.include?('darwin') && Mysql2::Client.server_info.fetch(:version).start_with?('5.5') + if RUBY_PLATFORM.include?('darwin') && @client.server_info.fetch(:version).start_with?('5.5') pending('MySQL 5.5 on OSX is afflicted by an unknown bug that breaks this test. See #633 and #634.') end @@ -615,7 +615,7 @@ def run_gc end it "should handle Timeouts without leaving the connection hanging if reconnect is set to true after construction" do - if RUBY_PLATFORM.include?('darwin') && Mysql2::Client.server_info.fetch(:version).start_with?('5.5') + if RUBY_PLATFORM.include?('darwin') && @client.server_info.fetch(:version).start_with?('5.5') pending('MySQL 5.5 on OSX is afflicted by an unknown bug that breaks this test. See #633 and #634.') end diff --git a/spec/mysql2/statement_spec.rb b/spec/mysql2/statement_spec.rb index 79da4d85d..c0aa46981 100644 --- a/spec/mysql2/statement_spec.rb +++ b/spec/mysql2/statement_spec.rb @@ -374,36 +374,47 @@ def stmt_count expect(@test_result['tiny_int_test']).to eql(1) end - it "should return TrueClass or FalseClass for a TINYINT value if :cast_booleans is enabled" do - @client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES (1)' - id1 = @client.last_id - @client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES (0)' - id2 = @client.last_id - @client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES (-1)' - id3 = @client.last_id - - result1 = @client.query 'SELECT bool_cast_test FROM mysql2_test WHERE bool_cast_test = 1 LIMIT 1', :cast_booleans => true - result2 = @client.query 'SELECT bool_cast_test FROM mysql2_test WHERE bool_cast_test = 0 LIMIT 1', :cast_booleans => true - result3 = @client.query 'SELECT bool_cast_test FROM mysql2_test WHERE bool_cast_test = -1 LIMIT 1', :cast_booleans => true - expect(result1.first['bool_cast_test']).to be true - expect(result2.first['bool_cast_test']).to be false - expect(result3.first['bool_cast_test']).to be true + context "cast booleans for TINYINY if :cast_booleans is enabled" do + # rubocop:disable Style/Semicolon + let(:client) { new_client(:cast_booleans => true) } + let(:id1) { client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES ( 1)'; client.last_id } + let(:id2) { client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES ( 0)'; client.last_id } + let(:id3) { client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES (-1)'; client.last_id } + # rubocop:enable Style/Semicolon + + after do + client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2},#{id3})" + end - @client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2},#{id3})" + it "should return TrueClass or FalseClass for a TINYINT value if :cast_booleans is enabled" do + query = client.prepare 'SELECT bool_cast_test FROM mysql2_test WHERE id = ?' + result1 = query.execute id1 + result2 = query.execute id2 + result3 = query.execute id3 + expect(result1.first['bool_cast_test']).to be true + expect(result2.first['bool_cast_test']).to be false + expect(result3.first['bool_cast_test']).to be true + end end - it "should return TrueClass or FalseClass for a BIT(1) value if :cast_booleans is enabled" do - @client.query 'INSERT INTO mysql2_test (single_bit_test) VALUES (1)' - id1 = @client.last_id - @client.query 'INSERT INTO mysql2_test (single_bit_test) VALUES (0)' - id2 = @client.last_id + context "cast booleans for BIT(1) if :cast_booleans is enabled" do + # rubocop:disable Style/Semicolon + let(:client) { new_client(:cast_booleans => true) } + let(:id1) { client.query 'INSERT INTO mysql2_test (single_bit_test) VALUES (1)'; client.last_id } + let(:id2) { client.query 'INSERT INTO mysql2_test (single_bit_test) VALUES (0)'; client.last_id } + # rubocop:enable Style/Semicolon - result1 = @client.query "SELECT single_bit_test FROM mysql2_test WHERE id = #{id1}", :cast_booleans => true - result2 = @client.query "SELECT single_bit_test FROM mysql2_test WHERE id = #{id2}", :cast_booleans => true - expect(result1.first['single_bit_test']).to be true - expect(result2.first['single_bit_test']).to be false + after do + client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2})" + end - @client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2})" + it "should return TrueClass or FalseClass for a BIT(1) value if :cast_booleans is enabled" do + query = client.prepare 'SELECT single_bit_test FROM mysql2_test WHERE id = ?' + result1 = query.execute id1 + result2 = query.execute id2 + expect(result1.first['single_bit_test']).to be true + expect(result2.first['single_bit_test']).to be false + end end it "should return Fixnum for a SMALLINT value" do @@ -460,39 +471,39 @@ def stmt_count it "should return DateTime when timestamp is < 1901-12-13 20:45:52" do # 1901-12-13T20:45:52 is the min for 32bit Ruby 1.8 - r = @client.query("SELECT CAST('1901-12-13 20:45:51' AS DATETIME) as test") + r = @client.prepare("SELECT CAST('1901-12-13 20:45:51' AS DATETIME) as test").execute expect(r.first['test']).to be_an_instance_of(klass) end it "should return DateTime when timestamp is > 2038-01-19T03:14:07" do # 2038-01-19T03:14:07 is the max for 32bit Ruby 1.8 - r = @client.query("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test") + r = @client.prepare("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test").execute expect(r.first['test']).to be_an_instance_of(klass) end elsif 1.size == 8 # 64bit if RUBY_VERSION =~ /1.8/ it "should return Time when timestamp is > 0138-12-31 11:59:59" do - r = @client.query("SELECT CAST('0139-1-1 00:00:00' AS DATETIME) as test") + r = @client.prepare("SELECT CAST('0139-1-1 00:00:00' AS DATETIME) as test").execute expect(r.first['test']).to be_an_instance_of(Time) end it "should return DateTime when timestamp is < 0139-1-1T00:00:00" do - r = @client.query("SELECT CAST('0138-12-31 11:59:59' AS DATETIME) as test") + r = @client.prepare("SELECT CAST('0138-12-31 11:59:59' AS DATETIME) as test").execute expect(r.first['test']).to be_an_instance_of(DateTime) end it "should return Time when timestamp is > 2038-01-19T03:14:07" do - r = @client.query("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test") + r = @client.prepare("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test").execute expect(r.first['test']).to be_an_instance_of(Time) end else it "should return Time when timestamp is < 1901-12-13 20:45:52" do - r = @client.query("SELECT CAST('1901-12-13 20:45:51' AS DATETIME) as test") + r = @client.prepare("SELECT CAST('1901-12-13 20:45:51' AS DATETIME) as test").execute expect(r.first['test']).to be_an_instance_of(Time) end it "should return Time when timestamp is > 2038-01-19T03:14:07" do - r = @client.query("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test") + r = @client.prepare("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test").execute expect(r.first['test']).to be_an_instance_of(Time) end end