Skip to content

Commit b6cbf17

Browse files
authored
Merge pull request #903 from sodabrew/statement_specs_prepare
Cast the BIT(1) type when :cast_booleans is true for prepared statements
2 parents cffb76d + e52fc0a commit b6cbf17

File tree

3 files changed

+52
-35
lines changed

3 files changed

+52
-35
lines changed

ext/mysql2/result.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,13 @@ static VALUE rb_mysql_result_fetch_row_stmt(VALUE self, MYSQL_FIELD * fields, co
405405
val = INT2NUM(*((signed char*)result_buffer->buffer));
406406
}
407407
break;
408+
case MYSQL_TYPE_BIT: /* BIT field (MySQL 5.0.3 and up) */
409+
if (args->castBool && fields[i].length == 1) {
410+
val = (*((unsigned char*)result_buffer->buffer) != 0) ? Qtrue : Qfalse;
411+
}else{
412+
val = rb_str_new(result_buffer->buffer, *(result_buffer->length));
413+
}
414+
break;
408415
case MYSQL_TYPE_SHORT: // short int
409416
if (result_buffer->is_unsigned) {
410417
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
494501
case MYSQL_TYPE_BLOB: // char[]
495502
case MYSQL_TYPE_MEDIUM_BLOB: // char[]
496503
case MYSQL_TYPE_LONG_BLOB: // char[]
497-
case MYSQL_TYPE_BIT: // char[]
498504
case MYSQL_TYPE_SET: // char[]
499505
case MYSQL_TYPE_ENUM: // char[]
500506
case MYSQL_TYPE_GEOMETRY: // char[]

spec/mysql2/client_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ def run_gc
604604
end
605605

606606
it "should handle Timeouts without leaving the connection hanging if reconnect is true" do
607-
if RUBY_PLATFORM.include?('darwin') && Mysql2::Client.server_info.fetch(:version).start_with?('5.5')
607+
if RUBY_PLATFORM.include?('darwin') && @client.server_info.fetch(:version).start_with?('5.5')
608608
pending('MySQL 5.5 on OSX is afflicted by an unknown bug that breaks this test. See #633 and #634.')
609609
end
610610

@@ -615,7 +615,7 @@ def run_gc
615615
end
616616

617617
it "should handle Timeouts without leaving the connection hanging if reconnect is set to true after construction" do
618-
if RUBY_PLATFORM.include?('darwin') && Mysql2::Client.server_info.fetch(:version).start_with?('5.5')
618+
if RUBY_PLATFORM.include?('darwin') && @client.server_info.fetch(:version).start_with?('5.5')
619619
pending('MySQL 5.5 on OSX is afflicted by an unknown bug that breaks this test. See #633 and #634.')
620620
end
621621

spec/mysql2/statement_spec.rb

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -374,36 +374,47 @@ def stmt_count
374374
expect(@test_result['tiny_int_test']).to eql(1)
375375
end
376376

377-
it "should return TrueClass or FalseClass for a TINYINT value if :cast_booleans is enabled" do
378-
@client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES (1)'
379-
id1 = @client.last_id
380-
@client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES (0)'
381-
id2 = @client.last_id
382-
@client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES (-1)'
383-
id3 = @client.last_id
384-
385-
result1 = @client.query 'SELECT bool_cast_test FROM mysql2_test WHERE bool_cast_test = 1 LIMIT 1', :cast_booleans => true
386-
result2 = @client.query 'SELECT bool_cast_test FROM mysql2_test WHERE bool_cast_test = 0 LIMIT 1', :cast_booleans => true
387-
result3 = @client.query 'SELECT bool_cast_test FROM mysql2_test WHERE bool_cast_test = -1 LIMIT 1', :cast_booleans => true
388-
expect(result1.first['bool_cast_test']).to be true
389-
expect(result2.first['bool_cast_test']).to be false
390-
expect(result3.first['bool_cast_test']).to be true
377+
context "cast booleans for TINYINY if :cast_booleans is enabled" do
378+
# rubocop:disable Style/Semicolon
379+
let(:client) { new_client(:cast_booleans => true) }
380+
let(:id1) { client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES ( 1)'; client.last_id }
381+
let(:id2) { client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES ( 0)'; client.last_id }
382+
let(:id3) { client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES (-1)'; client.last_id }
383+
# rubocop:enable Style/Semicolon
384+
385+
after do
386+
client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2},#{id3})"
387+
end
391388

392-
@client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2},#{id3})"
389+
it "should return TrueClass or FalseClass for a TINYINT value if :cast_booleans is enabled" do
390+
query = client.prepare 'SELECT bool_cast_test FROM mysql2_test WHERE id = ?'
391+
result1 = query.execute id1
392+
result2 = query.execute id2
393+
result3 = query.execute id3
394+
expect(result1.first['bool_cast_test']).to be true
395+
expect(result2.first['bool_cast_test']).to be false
396+
expect(result3.first['bool_cast_test']).to be true
397+
end
393398
end
394399

395-
it "should return TrueClass or FalseClass for a BIT(1) value if :cast_booleans is enabled" do
396-
@client.query 'INSERT INTO mysql2_test (single_bit_test) VALUES (1)'
397-
id1 = @client.last_id
398-
@client.query 'INSERT INTO mysql2_test (single_bit_test) VALUES (0)'
399-
id2 = @client.last_id
400+
context "cast booleans for BIT(1) if :cast_booleans is enabled" do
401+
# rubocop:disable Style/Semicolon
402+
let(:client) { new_client(:cast_booleans => true) }
403+
let(:id1) { client.query 'INSERT INTO mysql2_test (single_bit_test) VALUES (1)'; client.last_id }
404+
let(:id2) { client.query 'INSERT INTO mysql2_test (single_bit_test) VALUES (0)'; client.last_id }
405+
# rubocop:enable Style/Semicolon
400406

401-
result1 = @client.query "SELECT single_bit_test FROM mysql2_test WHERE id = #{id1}", :cast_booleans => true
402-
result2 = @client.query "SELECT single_bit_test FROM mysql2_test WHERE id = #{id2}", :cast_booleans => true
403-
expect(result1.first['single_bit_test']).to be true
404-
expect(result2.first['single_bit_test']).to be false
407+
after do
408+
client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2})"
409+
end
405410

406-
@client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2})"
411+
it "should return TrueClass or FalseClass for a BIT(1) value if :cast_booleans is enabled" do
412+
query = client.prepare 'SELECT single_bit_test FROM mysql2_test WHERE id = ?'
413+
result1 = query.execute id1
414+
result2 = query.execute id2
415+
expect(result1.first['single_bit_test']).to be true
416+
expect(result2.first['single_bit_test']).to be false
417+
end
407418
end
408419

409420
it "should return Fixnum for a SMALLINT value" do
@@ -460,39 +471,39 @@ def stmt_count
460471

461472
it "should return DateTime when timestamp is < 1901-12-13 20:45:52" do
462473
# 1901-12-13T20:45:52 is the min for 32bit Ruby 1.8
463-
r = @client.query("SELECT CAST('1901-12-13 20:45:51' AS DATETIME) as test")
474+
r = @client.prepare("SELECT CAST('1901-12-13 20:45:51' AS DATETIME) as test").execute
464475
expect(r.first['test']).to be_an_instance_of(klass)
465476
end
466477

467478
it "should return DateTime when timestamp is > 2038-01-19T03:14:07" do
468479
# 2038-01-19T03:14:07 is the max for 32bit Ruby 1.8
469-
r = @client.query("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test")
480+
r = @client.prepare("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test").execute
470481
expect(r.first['test']).to be_an_instance_of(klass)
471482
end
472483
elsif 1.size == 8 # 64bit
473484
if RUBY_VERSION =~ /1.8/
474485
it "should return Time when timestamp is > 0138-12-31 11:59:59" do
475-
r = @client.query("SELECT CAST('0139-1-1 00:00:00' AS DATETIME) as test")
486+
r = @client.prepare("SELECT CAST('0139-1-1 00:00:00' AS DATETIME) as test").execute
476487
expect(r.first['test']).to be_an_instance_of(Time)
477488
end
478489

479490
it "should return DateTime when timestamp is < 0139-1-1T00:00:00" do
480-
r = @client.query("SELECT CAST('0138-12-31 11:59:59' AS DATETIME) as test")
491+
r = @client.prepare("SELECT CAST('0138-12-31 11:59:59' AS DATETIME) as test").execute
481492
expect(r.first['test']).to be_an_instance_of(DateTime)
482493
end
483494

484495
it "should return Time when timestamp is > 2038-01-19T03:14:07" do
485-
r = @client.query("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test")
496+
r = @client.prepare("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test").execute
486497
expect(r.first['test']).to be_an_instance_of(Time)
487498
end
488499
else
489500
it "should return Time when timestamp is < 1901-12-13 20:45:52" do
490-
r = @client.query("SELECT CAST('1901-12-13 20:45:51' AS DATETIME) as test")
501+
r = @client.prepare("SELECT CAST('1901-12-13 20:45:51' AS DATETIME) as test").execute
491502
expect(r.first['test']).to be_an_instance_of(Time)
492503
end
493504

494505
it "should return Time when timestamp is > 2038-01-19T03:14:07" do
495-
r = @client.query("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test")
506+
r = @client.prepare("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test").execute
496507
expect(r.first['test']).to be_an_instance_of(Time)
497508
end
498509
end

0 commit comments

Comments
 (0)