From a17ba07c759581e6babd3d87685019bf1b11ae97 Mon Sep 17 00:00:00 2001 From: Brian Lopez Date: Wed, 6 Oct 2010 10:33:52 -0700 Subject: [PATCH] a couple of minor updates to connection management with some specs --- ext/mysql2/client.c | 13 +++++--- spec/mysql2/client_spec.rb | 65 ++++++++++++++++++++++++++++---------- 2 files changed, 58 insertions(+), 20 deletions(-) diff --git a/ext/mysql2/client.c b/ext/mysql2/client.c index 71d5c1a..f55daff 100644 --- a/ext/mysql2/client.c +++ b/ext/mysql2/client.c @@ -186,7 +186,9 @@ static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE po static VALUE rb_mysql_client_close(VALUE self) { GET_CLIENT(self); - rb_thread_blocking_region(nogvl_close, wrapper, RUBY_UBF_IO, 0); + if (!wrapper->closed) { + rb_thread_blocking_region(nogvl_close, wrapper, RUBY_UBF_IO, 0); + } return Qnil; } @@ -335,6 +337,7 @@ static VALUE rb_mysql_client_escape(VALUE self, VALUE str) { unsigned long newLen, oldLen; GET_CLIENT(self); + REQUIRE_OPEN_DB(wrapper); Check_Type(str, T_STRING); #ifdef HAVE_RUBY_ENCODING_H rb_encoding *default_internal_enc = rb_default_internal_encoding(); @@ -346,7 +349,6 @@ static VALUE rb_mysql_client_escape(VALUE self, VALUE str) { oldLen = RSTRING_LEN(str); newStr = rb_str_new(0, oldLen*2+1); - REQUIRE_OPEN_DB(wrapper); newLen = mysql_real_escape_string(wrapper->client, RSTRING_PTR(newStr), StringValuePtr(str), oldLen); if (newLen == oldLen) { // no need to return a new ruby string if nothing changed @@ -366,6 +368,7 @@ static VALUE rb_mysql_client_escape(VALUE self, VALUE str) { static VALUE rb_mysql_client_info(VALUE self) { VALUE version = rb_hash_new(), client_info; GET_CLIENT(self); + #ifdef HAVE_RUBY_ENCODING_H rb_encoding *default_internal_enc = rb_default_internal_encoding(); rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding); @@ -386,13 +389,13 @@ static VALUE rb_mysql_client_info(VALUE self) { static VALUE rb_mysql_client_server_info(VALUE self) { VALUE version, server_info; GET_CLIENT(self); + + REQUIRE_OPEN_DB(wrapper); #ifdef HAVE_RUBY_ENCODING_H rb_encoding *default_internal_enc = rb_default_internal_encoding(); rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding); #endif - REQUIRE_OPEN_DB(wrapper); - version = rb_hash_new(); rb_hash_aset(version, sym_id, LONG2FIX(mysql_get_server_version(wrapper->client))); server_info = rb_str_new2(mysql_get_server_info(wrapper->client)); @@ -408,11 +411,13 @@ static VALUE rb_mysql_client_server_info(VALUE self) { static VALUE rb_mysql_client_socket(VALUE self) { GET_CLIENT(self); + REQUIRE_OPEN_DB(wrapper); return INT2NUM(wrapper->client->net.fd); } static VALUE rb_mysql_client_last_id(VALUE self) { GET_CLIENT(self); + REQUIRE_OPEN_DB(wrapper); return ULL2NUM(mysql_insert_id(wrapper->client)); } diff --git a/spec/mysql2/client_spec.rb b/spec/mysql2/client_spec.rb index cad599e..304a39f 100644 --- a/spec/mysql2/client_spec.rb +++ b/spec/mysql2/client_spec.rb @@ -71,6 +71,9 @@ describe Mysql2::Client do it "should be able to close properly" do @client.close.should be_nil + lambda { + @client.query "SELECT 1" + }.should raise_error(Mysql2::Error) end it "should respond to #query" do @@ -103,6 +106,13 @@ describe Mysql2::Client do }.should raise_error(Mysql2::Error) end + it "should require an open connection" do + @client.close + lambda { + @client.query "SELECT 1" + }.should raise_error(Mysql2::Error) + end + # XXX this test is not deterministic (because Unix signal handling is not) # and may fail on a loaded system if RUBY_PLATFORM !~ /mingw|mswin/ @@ -137,25 +147,34 @@ describe Mysql2::Client do @client.should respond_to(:escape) end - it "#escape should return a new SQL-escape version of the passed string" do - @client.escape("abc'def\"ghi\0jkl%mno").should eql("abc\\'def\\\"ghi\\0jkl%mno") - end + context "#escape" do + it "should return a new SQL-escape version of the passed string" do + @client.escape("abc'def\"ghi\0jkl%mno").should eql("abc\\'def\\\"ghi\\0jkl%mno") + end - it "#escape should return the passed string if nothing was escaped" do - str = "plain" - @client.escape(str).object_id.should eql(str.object_id) - end + it "should return the passed string if nothing was escaped" do + str = "plain" + @client.escape(str).object_id.should eql(str.object_id) + end - it "#escape should not overflow the thread stack" do - lambda { - Thread.new { @client.escape("'" * 256 * 1024) }.join - }.should_not raise_error(SystemStackError) - end + it "should not overflow the thread stack" do + lambda { + Thread.new { @client.escape("'" * 256 * 1024) }.join + }.should_not raise_error(SystemStackError) + end - it "#escape should not overflow the process stack" do - lambda { - Thread.new { @client.escape("'" * 1024 * 1024 * 4) }.join - }.should_not raise_error(SystemStackError) + it "should not overflow the process stack" do + lambda { + Thread.new { @client.escape("'" * 1024 * 1024 * 4) }.join + }.should_not raise_error(SystemStackError) + end + + it "should require an open connection" do + @client.close + lambda { + @client.escape "" + }.should raise_error(Mysql2::Error) + end end it "should respond to #info" do @@ -203,6 +222,13 @@ describe Mysql2::Client do server_info[:version].class.should eql(String) end + it "#server_info should require an open connection" do + @client.close + lambda { + @client.server_info + }.should raise_error(Mysql2::Error) + end + if defined? Encoding context "strings returned by #server_info" do it "should default to the connection's encoding if Encoding.default_internal is nil" do @@ -231,6 +257,13 @@ describe Mysql2::Client do @client.socket.should_not eql(0) end + it "#socket should require an open connection" do + @client.close + lambda { + @client.socket + }.should raise_error(Mysql2::Error) + end + it "should raise a Mysql2::Error exception upon connection failure" do lambda { bad_client = Mysql2::Client.new :host => "dfjhdi9wrhw", :username => 'asdfasdf8d2h'