Wrap the MYSQL* again so we can:
1) let mysql_init/mysql_close take care of any/all allocation, thread state and freeing 2) for faster access to the encoding and active state variables for the connection
This commit is contained in:
parent
3239a449b9
commit
cebf9af068
@ -14,11 +14,13 @@ static ID intern_merge, intern_error_number_eql, intern_sql_state_eql;
|
||||
}
|
||||
|
||||
#define MARK_CONN_INACTIVE(conn) \
|
||||
rb_iv_set(conn, "@active", Qfalse);
|
||||
wrapper->active = 0;
|
||||
|
||||
#define GET_CLIENT(self) \
|
||||
MYSQL * client; \
|
||||
Data_Get_Struct(self, MYSQL, client);
|
||||
mysql_client_wrapper *wrapper; \
|
||||
MYSQL *client; \
|
||||
Data_Get_Struct(self, mysql_client_wrapper, wrapper); \
|
||||
client = &wrapper->client;
|
||||
|
||||
/*
|
||||
* used to pass all arguments to mysql_real_connect while inside
|
||||
@ -66,6 +68,13 @@ struct nogvl_send_query_args {
|
||||
* - mysql_ssl_set()
|
||||
*/
|
||||
|
||||
static void rb_mysql_client_mark(void * wrapper) {
|
||||
mysql_client_wrapper * w = wrapper;
|
||||
if (w) {
|
||||
rb_gc_mark(w->encoding);
|
||||
}
|
||||
}
|
||||
|
||||
static VALUE rb_raise_mysql2_error(MYSQL *client) {
|
||||
VALUE e = rb_exc_new2(cMysql2Error, mysql_error(client));
|
||||
rb_funcall(e, intern_error_number_eql, 1, INT2NUM(mysql_errno(client)));
|
||||
@ -78,7 +87,7 @@ static VALUE nogvl_init(void *ptr) {
|
||||
MYSQL * client = (MYSQL *)ptr;
|
||||
|
||||
/* may initialize embedded server and read /etc/services off disk */
|
||||
mysql_init(client);
|
||||
client = mysql_init(NULL);
|
||||
|
||||
return client ? Qtrue : Qfalse;
|
||||
}
|
||||
@ -96,7 +105,8 @@ static VALUE nogvl_connect(void *ptr) {
|
||||
}
|
||||
|
||||
static void rb_mysql_client_free(void * ptr) {
|
||||
MYSQL * client = (MYSQL *)ptr;
|
||||
mysql_client_wrapper * wrapper = (mysql_client_wrapper *)ptr;
|
||||
MYSQL * client = &wrapper->client;
|
||||
|
||||
/*
|
||||
* we'll send a QUIT message to the server, but that message is more of a
|
||||
@ -129,15 +139,12 @@ static VALUE nogvl_close(void * ptr) {
|
||||
}
|
||||
|
||||
static VALUE allocate(VALUE klass) {
|
||||
MYSQL * client;
|
||||
|
||||
return Data_Make_Struct(
|
||||
klass,
|
||||
MYSQL,
|
||||
NULL,
|
||||
rb_mysql_client_free,
|
||||
client
|
||||
);
|
||||
VALUE obj;
|
||||
mysql_client_wrapper * wrapper;
|
||||
obj = Data_Make_Struct(klass, mysql_client_wrapper, rb_mysql_client_mark, rb_mysql_client_free, wrapper);
|
||||
wrapper->encoding = Qnil;
|
||||
wrapper->active = 0;
|
||||
return obj;
|
||||
}
|
||||
|
||||
static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE port, VALUE database, VALUE socket) {
|
||||
@ -237,7 +244,9 @@ static VALUE rb_mysql_client_async_result(VALUE self) {
|
||||
rb_iv_set(resultObj, "@query_options", rb_obj_dup(rb_iv_get(self, "@query_options")));
|
||||
|
||||
#ifdef HAVE_RUBY_ENCODING_H
|
||||
rb_iv_set(resultObj, "@encoding", GET_ENCODING(self));
|
||||
mysql2_result_wrapper * result_wrapper;
|
||||
GetMysql2Result(resultObj, result_wrapper);
|
||||
result_wrapper->encoding = wrapper->encoding;
|
||||
#endif
|
||||
return resultObj;
|
||||
}
|
||||
@ -247,18 +256,17 @@ static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) {
|
||||
fd_set fdset;
|
||||
int fd, retval;
|
||||
int async = 0;
|
||||
VALUE opts, defaults, active;
|
||||
VALUE opts, defaults;
|
||||
int(*selector)(int, fd_set *, fd_set *, fd_set *, struct timeval *) = NULL;
|
||||
GET_CLIENT(self)
|
||||
|
||||
REQUIRE_OPEN_DB(client);
|
||||
args.mysql = client;
|
||||
|
||||
active = rb_iv_get(self, "@active");
|
||||
// see if this connection is still waiting on a result from a previous query
|
||||
if (NIL_P(active) || active == Qfalse) {
|
||||
if (wrapper->active == 0) {
|
||||
// mark this connection active
|
||||
rb_iv_set(self, "@active", Qtrue);
|
||||
wrapper->active = 1;
|
||||
} else {
|
||||
rb_raise(cMysql2Error, "This connection is still waiting for a result, try again once you have the result");
|
||||
}
|
||||
@ -276,7 +284,7 @@ static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) {
|
||||
}
|
||||
|
||||
#ifdef HAVE_RUBY_ENCODING_H
|
||||
rb_encoding *conn_enc = rb_to_encoding(GET_ENCODING(self));
|
||||
rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding);
|
||||
// ensure the string is in the encoding the connection is expecting
|
||||
args.sql = rb_str_export_to_enc(args.sql, conn_enc);
|
||||
#endif
|
||||
@ -323,7 +331,7 @@ static VALUE rb_mysql_client_escape(VALUE self, VALUE str) {
|
||||
Check_Type(str, T_STRING);
|
||||
#ifdef HAVE_RUBY_ENCODING_H
|
||||
rb_encoding *default_internal_enc = rb_default_internal_encoding();
|
||||
rb_encoding *conn_enc = rb_to_encoding(GET_ENCODING(self));
|
||||
rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding);
|
||||
// ensure the string is in the encoding the connection is expecting
|
||||
str = rb_str_export_to_enc(str, conn_enc);
|
||||
#endif
|
||||
@ -348,11 +356,12 @@ static VALUE rb_mysql_client_escape(VALUE self, VALUE str) {
|
||||
}
|
||||
}
|
||||
|
||||
static VALUE rb_mysql_client_info(RB_MYSQL_UNUSED VALUE self) {
|
||||
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(GET_ENCODING(self));
|
||||
rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding);
|
||||
#endif
|
||||
|
||||
rb_hash_aset(version, sym_id, LONG2NUM(mysql_get_client_version()));
|
||||
@ -372,7 +381,7 @@ static VALUE rb_mysql_client_server_info(VALUE self) {
|
||||
GET_CLIENT(self)
|
||||
#ifdef HAVE_RUBY_ENCODING_H
|
||||
rb_encoding *default_internal_enc = rb_default_internal_encoding();
|
||||
rb_encoding *conn_enc = rb_to_encoding(GET_ENCODING(self));
|
||||
rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding);
|
||||
#endif
|
||||
|
||||
REQUIRE_OPEN_DB(client);
|
||||
@ -446,14 +455,13 @@ static VALUE set_charset_name(VALUE self, VALUE value) {
|
||||
GET_CLIENT(self)
|
||||
|
||||
#ifdef HAVE_RUBY_ENCODING_H
|
||||
VALUE new_encoding, old_encoding;
|
||||
VALUE new_encoding;
|
||||
new_encoding = rb_funcall(cMysql2Client, intern_encoding_from_charset, 1, value);
|
||||
if (new_encoding == Qnil) {
|
||||
rb_raise(cMysql2Error, "Unsupported charset: '%s'", RSTRING_PTR(value));
|
||||
} else {
|
||||
old_encoding = rb_iv_get(self, "@encoding");
|
||||
if (old_encoding == Qnil) {
|
||||
rb_iv_set(self, "@encoding", new_encoding);
|
||||
if (wrapper->encoding == Qnil) {
|
||||
wrapper->encoding = new_encoding;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -31,4 +31,10 @@ rb_thread_blocking_region(
|
||||
|
||||
void init_mysql2_client();
|
||||
|
||||
typedef struct {
|
||||
VALUE encoding;
|
||||
short int active;
|
||||
MYSQL client;
|
||||
} mysql_client_wrapper;
|
||||
|
||||
#endif
|
@ -29,7 +29,4 @@
|
||||
#include <client.h>
|
||||
#include <result.h>
|
||||
|
||||
#define GET_ENCODING(self) \
|
||||
rb_iv_get(self, "@encoding")
|
||||
|
||||
#endif
|
||||
|
@ -20,6 +20,7 @@ static void rb_mysql_result_mark(void * wrapper) {
|
||||
if (w) {
|
||||
rb_gc_mark(w->fields);
|
||||
rb_gc_mark(w->rows);
|
||||
rb_gc_mark(w->encoding);
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,7 +66,7 @@ static VALUE rb_mysql_result_fetch_field(VALUE self, unsigned int idx, short int
|
||||
MYSQL_FIELD *field = NULL;
|
||||
#ifdef HAVE_RUBY_ENCODING_H
|
||||
rb_encoding *default_internal_enc = rb_default_internal_encoding();
|
||||
rb_encoding *conn_enc = rb_to_encoding(GET_ENCODING(self));
|
||||
rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding);
|
||||
#endif
|
||||
|
||||
field = mysql_fetch_field_direct(wrapper->result, idx);
|
||||
@ -97,13 +98,14 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
|
||||
unsigned int i = 0;
|
||||
unsigned long * fieldLengths;
|
||||
void * ptr;
|
||||
#ifdef HAVE_RUBY_ENCODING_H
|
||||
rb_encoding *default_internal_enc = rb_default_internal_encoding();
|
||||
rb_encoding *conn_enc = rb_to_encoding(GET_ENCODING(self));
|
||||
#endif
|
||||
|
||||
GetMysql2Result(self, 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
|
||||
|
||||
ptr = wrapper->result;
|
||||
row = (MYSQL_ROW)rb_thread_blocking_region(nogvl_fetch_row, ptr, RUBY_UBF_IO, 0);
|
||||
if (row == NULL) {
|
||||
@ -401,6 +403,7 @@ VALUE rb_mysql_result_to_obj(MYSQL_RES * r) {
|
||||
wrapper->result = r;
|
||||
wrapper->fields = Qnil;
|
||||
wrapper->rows = Qnil;
|
||||
wrapper->encoding = Qnil;
|
||||
rb_obj_call_init(obj, 0, NULL);
|
||||
return obj;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ VALUE rb_mysql_result_to_obj(MYSQL_RES * r);
|
||||
typedef struct {
|
||||
VALUE fields;
|
||||
VALUE rows;
|
||||
VALUE encoding;
|
||||
unsigned int numberOfFields;
|
||||
unsigned long numberOfRows;
|
||||
unsigned long lastRowProcessed;
|
||||
|
@ -12,7 +12,6 @@ module Mysql2
|
||||
|
||||
def initialize(opts = {})
|
||||
@query_options = @@default_query_options.dup
|
||||
@active = false
|
||||
|
||||
init_connection
|
||||
|
||||
@ -21,7 +20,6 @@ module Mysql2
|
||||
send(:"#{key}=", opts[key])
|
||||
end
|
||||
# force the encoding to utf8
|
||||
@encoding = nil
|
||||
self.charset_name = opts[:encoding] || 'utf8'
|
||||
|
||||
ssl_set(*opts.values_at(:sslkey, :sslcert, :sslca, :sslcapath, :sslciper))
|
||||
|
Loading…
Reference in New Issue
Block a user