add initial async query support
This commit is contained in:
parent
80a8602fbb
commit
7131752757
|
@ -125,7 +125,7 @@ static VALUE rb_mysql_client_new(int argc, VALUE * argv, VALUE klass) {
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE rb_mysql_client_init(VALUE self, int argc, VALUE * argv) {
|
static VALUE rb_mysql_client_init(int argc, VALUE * argv, VALUE self) {
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,11 +136,21 @@ void rb_mysql_client_free(void * client) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE rb_mysql_client_query(VALUE self, VALUE sql) {
|
static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) {
|
||||||
MYSQL * client;
|
MYSQL * client;
|
||||||
MYSQL_RES * result;
|
MYSQL_RES * result;
|
||||||
fd_set fdset;
|
fd_set fdset;
|
||||||
int fd, retval;
|
int fd, retval;
|
||||||
|
int async = 0;
|
||||||
|
VALUE sql, opts;
|
||||||
|
VALUE rb_async;
|
||||||
|
|
||||||
|
if (rb_scan_args(argc, argv, "11", &sql, &opts) == 2) {
|
||||||
|
if ((rb_async = rb_hash_aref(opts, sym_async)) != Qnil) {
|
||||||
|
async = rb_async == Qtrue ? 1 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Check_Type(sql, T_STRING);
|
Check_Type(sql, T_STRING);
|
||||||
|
|
||||||
GetMysql2Client(self, client);
|
GetMysql2Client(self, client);
|
||||||
|
@ -149,6 +159,7 @@ static VALUE rb_mysql_client_query(VALUE self, VALUE sql) {
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!async) {
|
||||||
// the below code is largely from do_mysql
|
// the below code is largely from do_mysql
|
||||||
// http://github.com/datamapper/do
|
// http://github.com/datamapper/do
|
||||||
fd = client->net.fd;
|
fd = client->net.fd;
|
||||||
|
@ -167,19 +178,10 @@ static VALUE rb_mysql_client_query(VALUE self, VALUE sql) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mysql_read_query_result(client) != 0) {
|
return rb_mysql_client_async_result(self);
|
||||||
rb_raise(cMysql2Error, "%s", mysql_error(client));
|
} else {
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = mysql_store_result(client);
|
|
||||||
if (result == NULL) {
|
|
||||||
if (mysql_field_count(client) != 0) {
|
|
||||||
rb_raise(cMysql2Error, "%s", mysql_error(client));
|
|
||||||
}
|
|
||||||
return Qnil;
|
|
||||||
}
|
|
||||||
return rb_mysql_result_to_obj(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE rb_mysql_client_escape(VALUE self, VALUE str) {
|
static VALUE rb_mysql_client_escape(VALUE self, VALUE str) {
|
||||||
|
@ -229,6 +231,27 @@ static VALUE rb_mysql_client_socket(VALUE self) {
|
||||||
return INT2NUM(client->net.fd);
|
return INT2NUM(client->net.fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE rb_mysql_client_async_result(VALUE self) {
|
||||||
|
MYSQL * client;
|
||||||
|
MYSQL_RES * result;
|
||||||
|
GetMysql2Client(self, client);
|
||||||
|
|
||||||
|
if (mysql_read_query_result(client) != 0) {
|
||||||
|
rb_raise(cMysql2Error, "%s", mysql_error(client));
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = mysql_store_result(client);
|
||||||
|
if (result == NULL) {
|
||||||
|
if (mysql_field_count(client) != 0) {
|
||||||
|
rb_raise(cMysql2Error, "%s", mysql_error(client));
|
||||||
|
}
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rb_mysql_result_to_obj(result);
|
||||||
|
}
|
||||||
|
|
||||||
/* Mysql2::Result */
|
/* Mysql2::Result */
|
||||||
static VALUE rb_mysql_result_to_obj(MYSQL_RES * r) {
|
static VALUE rb_mysql_result_to_obj(MYSQL_RES * r) {
|
||||||
VALUE obj;
|
VALUE obj;
|
||||||
|
@ -420,11 +443,12 @@ void Init_mysql2_ext() {
|
||||||
VALUE cMysql2Client = rb_define_class_under(mMysql2, "Client", rb_cObject);
|
VALUE cMysql2Client = rb_define_class_under(mMysql2, "Client", rb_cObject);
|
||||||
rb_define_singleton_method(cMysql2Client, "new", rb_mysql_client_new, -1);
|
rb_define_singleton_method(cMysql2Client, "new", rb_mysql_client_new, -1);
|
||||||
rb_define_method(cMysql2Client, "initialize", rb_mysql_client_init, -1);
|
rb_define_method(cMysql2Client, "initialize", rb_mysql_client_init, -1);
|
||||||
rb_define_method(cMysql2Client, "query", rb_mysql_client_query, 1);
|
rb_define_method(cMysql2Client, "query", rb_mysql_client_query, -1);
|
||||||
rb_define_method(cMysql2Client, "escape", rb_mysql_client_escape, 1);
|
rb_define_method(cMysql2Client, "escape", rb_mysql_client_escape, 1);
|
||||||
rb_define_method(cMysql2Client, "info", rb_mysql_client_info, 0);
|
rb_define_method(cMysql2Client, "info", rb_mysql_client_info, 0);
|
||||||
rb_define_method(cMysql2Client, "server_info", rb_mysql_client_server_info, 0);
|
rb_define_method(cMysql2Client, "server_info", rb_mysql_client_server_info, 0);
|
||||||
rb_define_method(cMysql2Client, "socket", rb_mysql_client_socket, 0);
|
rb_define_method(cMysql2Client, "socket", rb_mysql_client_socket, 0);
|
||||||
|
rb_define_method(cMysql2Client, "async_result", rb_mysql_client_async_result, 0);
|
||||||
|
|
||||||
cMysql2Error = rb_define_class_under(mMysql2, "Error", rb_eStandardError);
|
cMysql2Error = rb_define_class_under(mMysql2, "Error", rb_eStandardError);
|
||||||
|
|
||||||
|
@ -453,6 +477,7 @@ void Init_mysql2_ext() {
|
||||||
sym_sslca = ID2SYM(rb_intern("sslca"));
|
sym_sslca = ID2SYM(rb_intern("sslca"));
|
||||||
sym_sslcapath = ID2SYM(rb_intern("sslcapath"));
|
sym_sslcapath = ID2SYM(rb_intern("sslcapath"));
|
||||||
sym_sslcipher = ID2SYM(rb_intern("sslcipher"));
|
sym_sslcipher = ID2SYM(rb_intern("sslcipher"));
|
||||||
|
sym_async = ID2SYM(rb_intern("async"));
|
||||||
|
|
||||||
#ifdef HAVE_RUBY_ENCODING_H
|
#ifdef HAVE_RUBY_ENCODING_H
|
||||||
utf8Encoding = rb_enc_find_index("UTF-8");
|
utf8Encoding = rb_enc_find_index("UTF-8");
|
||||||
|
|
|
@ -28,20 +28,21 @@ VALUE cMysql2Error;
|
||||||
#define GetMysql2Client(obj, sval) (sval = (MYSQL*)DATA_PTR(obj));
|
#define GetMysql2Client(obj, sval) (sval = (MYSQL*)DATA_PTR(obj));
|
||||||
static ID sym_socket, sym_host, sym_port, sym_username, sym_password,
|
static ID sym_socket, sym_host, sym_port, sym_username, sym_password,
|
||||||
sym_database, sym_reconnect, sym_connect_timeout, sym_id, sym_version,
|
sym_database, sym_reconnect, sym_connect_timeout, sym_id, sym_version,
|
||||||
sym_sslkey, sym_sslcert, sym_sslca, sym_sslcapath, sym_sslcipher;
|
sym_sslkey, sym_sslcert, sym_sslca, sym_sslcapath, sym_sslcipher,
|
||||||
|
sym_symbolize_keys, sym_async;
|
||||||
static VALUE rb_mysql_client_new(int argc, VALUE * argv, VALUE klass);
|
static VALUE rb_mysql_client_new(int argc, VALUE * argv, VALUE klass);
|
||||||
static VALUE rb_mysql_client_init(VALUE self, int argc, VALUE * argv);
|
static VALUE rb_mysql_client_init(int argc, VALUE * argv, VALUE self);
|
||||||
static VALUE rb_mysql_client_query(VALUE self, VALUE query);
|
static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self);
|
||||||
static VALUE rb_mysql_client_escape(VALUE self, VALUE str);
|
static VALUE rb_mysql_client_escape(VALUE self, VALUE str);
|
||||||
static VALUE rb_mysql_client_info(VALUE self);
|
static VALUE rb_mysql_client_info(VALUE self);
|
||||||
static VALUE rb_mysql_client_server_info(VALUE self);
|
static VALUE rb_mysql_client_server_info(VALUE self);
|
||||||
static VALUE rb_mysql_client_socket(VALUE self);
|
static VALUE rb_mysql_client_socket(VALUE self);
|
||||||
|
static VALUE rb_mysql_client_async_result(VALUE self);
|
||||||
void rb_mysql_client_free(void * client);
|
void rb_mysql_client_free(void * client);
|
||||||
|
|
||||||
/* Mysql2::Result */
|
/* Mysql2::Result */
|
||||||
#define GetMysql2Result(obj, sval) (sval = (MYSQL_RES*)DATA_PTR(obj));
|
#define GetMysql2Result(obj, sval) (sval = (MYSQL_RES*)DATA_PTR(obj));
|
||||||
VALUE cMysql2Result;
|
VALUE cMysql2Result;
|
||||||
static ID sym_symbolize_keys;
|
|
||||||
static VALUE rb_mysql_result_to_obj(MYSQL_RES * res);
|
static VALUE rb_mysql_result_to_obj(MYSQL_RES * res);
|
||||||
static VALUE rb_mysql_result_fetch_row(int argc, VALUE * argv, VALUE self);
|
static VALUE rb_mysql_result_fetch_row(int argc, VALUE * argv, VALUE self);
|
||||||
static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self);
|
static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self);
|
||||||
|
|
|
@ -6,6 +6,11 @@ describe Mysql2::Client do
|
||||||
@client = Mysql2::Client.new
|
@client = Mysql2::Client.new
|
||||||
end
|
end
|
||||||
|
|
||||||
|
after(:each) do
|
||||||
|
# forcefully clean up old connections
|
||||||
|
GC.start
|
||||||
|
end
|
||||||
|
|
||||||
it "should be able to connect via SSL options" do
|
it "should be able to connect via SSL options" do
|
||||||
pending("DON'T WORRY, THIS TEST PASSES :) - but is machine-specific. You need to have MySQL running with SSL configured and enabled. Then update the paths in this test to your needs and remove the pending state.")
|
pending("DON'T WORRY, THIS TEST PASSES :) - but is machine-specific. You need to have MySQL running with SSL configured and enabled. Then update the paths in this test to your needs and remove the pending state.")
|
||||||
ssl_client = nil
|
ssl_client = nil
|
||||||
|
@ -90,4 +95,25 @@ describe Mysql2::Client do
|
||||||
good_client = Mysql2::Client.new
|
good_client = Mysql2::Client.new
|
||||||
}.should_not raise_error(Mysql2::Error)
|
}.should_not raise_error(Mysql2::Error)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "evented async queries should be supported" do
|
||||||
|
# should immediately return nil
|
||||||
|
@client.query("SELECT sleep(0.1)", :async => true).should eql(nil)
|
||||||
|
|
||||||
|
io_wrapper = IO.for_fd(@client.socket)
|
||||||
|
loops = 0
|
||||||
|
loop do
|
||||||
|
if IO.select([io_wrapper], nil, nil, 0.05)
|
||||||
|
break
|
||||||
|
else
|
||||||
|
loops += 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# make sure we waited some period of time
|
||||||
|
(loops >= 1).should be_true
|
||||||
|
|
||||||
|
result = @client.async_result
|
||||||
|
result.class.should eql(Mysql2::Result)
|
||||||
|
end
|
||||||
end
|
end
|
Loading…
Reference in New Issue