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) \
|
#define MARK_CONN_INACTIVE(conn) \
|
||||||
rb_iv_set(conn, "@active", Qfalse);
|
wrapper->active = 0;
|
||||||
|
|
||||||
#define GET_CLIENT(self) \
|
#define GET_CLIENT(self) \
|
||||||
|
mysql_client_wrapper *wrapper; \
|
||||||
MYSQL *client; \
|
MYSQL *client; \
|
||||||
Data_Get_Struct(self, MYSQL, client);
|
Data_Get_Struct(self, mysql_client_wrapper, wrapper); \
|
||||||
|
client = &wrapper->client;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* used to pass all arguments to mysql_real_connect while inside
|
* used to pass all arguments to mysql_real_connect while inside
|
||||||
@ -66,6 +68,13 @@ struct nogvl_send_query_args {
|
|||||||
* - mysql_ssl_set()
|
* - 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) {
|
static VALUE rb_raise_mysql2_error(MYSQL *client) {
|
||||||
VALUE e = rb_exc_new2(cMysql2Error, mysql_error(client));
|
VALUE e = rb_exc_new2(cMysql2Error, mysql_error(client));
|
||||||
rb_funcall(e, intern_error_number_eql, 1, INT2NUM(mysql_errno(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;
|
MYSQL * client = (MYSQL *)ptr;
|
||||||
|
|
||||||
/* may initialize embedded server and read /etc/services off disk */
|
/* may initialize embedded server and read /etc/services off disk */
|
||||||
mysql_init(client);
|
client = mysql_init(NULL);
|
||||||
|
|
||||||
return client ? Qtrue : Qfalse;
|
return client ? Qtrue : Qfalse;
|
||||||
}
|
}
|
||||||
@ -96,7 +105,8 @@ static VALUE nogvl_connect(void *ptr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void rb_mysql_client_free(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
|
* 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) {
|
static VALUE allocate(VALUE klass) {
|
||||||
MYSQL * client;
|
VALUE obj;
|
||||||
|
mysql_client_wrapper * wrapper;
|
||||||
return Data_Make_Struct(
|
obj = Data_Make_Struct(klass, mysql_client_wrapper, rb_mysql_client_mark, rb_mysql_client_free, wrapper);
|
||||||
klass,
|
wrapper->encoding = Qnil;
|
||||||
MYSQL,
|
wrapper->active = 0;
|
||||||
NULL,
|
return obj;
|
||||||
rb_mysql_client_free,
|
|
||||||
client
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE port, VALUE database, VALUE socket) {
|
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")));
|
rb_iv_set(resultObj, "@query_options", rb_obj_dup(rb_iv_get(self, "@query_options")));
|
||||||
|
|
||||||
#ifdef HAVE_RUBY_ENCODING_H
|
#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
|
#endif
|
||||||
return resultObj;
|
return resultObj;
|
||||||
}
|
}
|
||||||
@ -247,18 +256,17 @@ static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) {
|
|||||||
fd_set fdset;
|
fd_set fdset;
|
||||||
int fd, retval;
|
int fd, retval;
|
||||||
int async = 0;
|
int async = 0;
|
||||||
VALUE opts, defaults, active;
|
VALUE opts, defaults;
|
||||||
int(*selector)(int, fd_set *, fd_set *, fd_set *, struct timeval *) = NULL;
|
int(*selector)(int, fd_set *, fd_set *, fd_set *, struct timeval *) = NULL;
|
||||||
GET_CLIENT(self)
|
GET_CLIENT(self)
|
||||||
|
|
||||||
REQUIRE_OPEN_DB(client);
|
REQUIRE_OPEN_DB(client);
|
||||||
args.mysql = client;
|
args.mysql = client;
|
||||||
|
|
||||||
active = rb_iv_get(self, "@active");
|
|
||||||
// see if this connection is still waiting on a result from a previous query
|
// 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
|
// mark this connection active
|
||||||
rb_iv_set(self, "@active", Qtrue);
|
wrapper->active = 1;
|
||||||
} else {
|
} else {
|
||||||
rb_raise(cMysql2Error, "This connection is still waiting for a result, try again once you have the result");
|
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
|
#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
|
// ensure the string is in the encoding the connection is expecting
|
||||||
args.sql = rb_str_export_to_enc(args.sql, conn_enc);
|
args.sql = rb_str_export_to_enc(args.sql, conn_enc);
|
||||||
#endif
|
#endif
|
||||||
@ -323,7 +331,7 @@ static VALUE rb_mysql_client_escape(VALUE self, VALUE str) {
|
|||||||
Check_Type(str, T_STRING);
|
Check_Type(str, T_STRING);
|
||||||
#ifdef HAVE_RUBY_ENCODING_H
|
#ifdef HAVE_RUBY_ENCODING_H
|
||||||
rb_encoding *default_internal_enc = rb_default_internal_encoding();
|
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
|
// ensure the string is in the encoding the connection is expecting
|
||||||
str = rb_str_export_to_enc(str, conn_enc);
|
str = rb_str_export_to_enc(str, conn_enc);
|
||||||
#endif
|
#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;
|
VALUE version = rb_hash_new(), client_info;
|
||||||
|
GET_CLIENT(self);
|
||||||
#ifdef HAVE_RUBY_ENCODING_H
|
#ifdef HAVE_RUBY_ENCODING_H
|
||||||
rb_encoding *default_internal_enc = rb_default_internal_encoding();
|
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
|
#endif
|
||||||
|
|
||||||
rb_hash_aset(version, sym_id, LONG2NUM(mysql_get_client_version()));
|
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)
|
GET_CLIENT(self)
|
||||||
#ifdef HAVE_RUBY_ENCODING_H
|
#ifdef HAVE_RUBY_ENCODING_H
|
||||||
rb_encoding *default_internal_enc = rb_default_internal_encoding();
|
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
|
#endif
|
||||||
|
|
||||||
REQUIRE_OPEN_DB(client);
|
REQUIRE_OPEN_DB(client);
|
||||||
@ -446,14 +455,13 @@ static VALUE set_charset_name(VALUE self, VALUE value) {
|
|||||||
GET_CLIENT(self)
|
GET_CLIENT(self)
|
||||||
|
|
||||||
#ifdef HAVE_RUBY_ENCODING_H
|
#ifdef HAVE_RUBY_ENCODING_H
|
||||||
VALUE new_encoding, old_encoding;
|
VALUE new_encoding;
|
||||||
new_encoding = rb_funcall(cMysql2Client, intern_encoding_from_charset, 1, value);
|
new_encoding = rb_funcall(cMysql2Client, intern_encoding_from_charset, 1, value);
|
||||||
if (new_encoding == Qnil) {
|
if (new_encoding == Qnil) {
|
||||||
rb_raise(cMysql2Error, "Unsupported charset: '%s'", RSTRING_PTR(value));
|
rb_raise(cMysql2Error, "Unsupported charset: '%s'", RSTRING_PTR(value));
|
||||||
} else {
|
} else {
|
||||||
old_encoding = rb_iv_get(self, "@encoding");
|
if (wrapper->encoding == Qnil) {
|
||||||
if (old_encoding == Qnil) {
|
wrapper->encoding = new_encoding;
|
||||||
rb_iv_set(self, "@encoding", new_encoding);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,4 +31,10 @@ rb_thread_blocking_region(
|
|||||||
|
|
||||||
void init_mysql2_client();
|
void init_mysql2_client();
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
VALUE encoding;
|
||||||
|
short int active;
|
||||||
|
MYSQL client;
|
||||||
|
} mysql_client_wrapper;
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -29,7 +29,4 @@
|
|||||||
#include <client.h>
|
#include <client.h>
|
||||||
#include <result.h>
|
#include <result.h>
|
||||||
|
|
||||||
#define GET_ENCODING(self) \
|
|
||||||
rb_iv_get(self, "@encoding")
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,6 +20,7 @@ static void rb_mysql_result_mark(void * wrapper) {
|
|||||||
if (w) {
|
if (w) {
|
||||||
rb_gc_mark(w->fields);
|
rb_gc_mark(w->fields);
|
||||||
rb_gc_mark(w->rows);
|
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;
|
MYSQL_FIELD *field = NULL;
|
||||||
#ifdef HAVE_RUBY_ENCODING_H
|
#ifdef HAVE_RUBY_ENCODING_H
|
||||||
rb_encoding *default_internal_enc = rb_default_internal_encoding();
|
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
|
#endif
|
||||||
|
|
||||||
field = mysql_fetch_field_direct(wrapper->result, idx);
|
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 int i = 0;
|
||||||
unsigned long * fieldLengths;
|
unsigned long * fieldLengths;
|
||||||
void * ptr;
|
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);
|
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;
|
ptr = wrapper->result;
|
||||||
row = (MYSQL_ROW)rb_thread_blocking_region(nogvl_fetch_row, ptr, RUBY_UBF_IO, 0);
|
row = (MYSQL_ROW)rb_thread_blocking_region(nogvl_fetch_row, ptr, RUBY_UBF_IO, 0);
|
||||||
if (row == NULL) {
|
if (row == NULL) {
|
||||||
@ -401,6 +403,7 @@ VALUE rb_mysql_result_to_obj(MYSQL_RES * r) {
|
|||||||
wrapper->result = r;
|
wrapper->result = r;
|
||||||
wrapper->fields = Qnil;
|
wrapper->fields = Qnil;
|
||||||
wrapper->rows = Qnil;
|
wrapper->rows = Qnil;
|
||||||
|
wrapper->encoding = Qnil;
|
||||||
rb_obj_call_init(obj, 0, NULL);
|
rb_obj_call_init(obj, 0, NULL);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ VALUE rb_mysql_result_to_obj(MYSQL_RES * r);
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
VALUE fields;
|
VALUE fields;
|
||||||
VALUE rows;
|
VALUE rows;
|
||||||
|
VALUE encoding;
|
||||||
unsigned int numberOfFields;
|
unsigned int numberOfFields;
|
||||||
unsigned long numberOfRows;
|
unsigned long numberOfRows;
|
||||||
unsigned long lastRowProcessed;
|
unsigned long lastRowProcessed;
|
||||||
|
@ -12,7 +12,6 @@ module Mysql2
|
|||||||
|
|
||||||
def initialize(opts = {})
|
def initialize(opts = {})
|
||||||
@query_options = @@default_query_options.dup
|
@query_options = @@default_query_options.dup
|
||||||
@active = false
|
|
||||||
|
|
||||||
init_connection
|
init_connection
|
||||||
|
|
||||||
@ -21,7 +20,6 @@ module Mysql2
|
|||||||
send(:"#{key}=", opts[key])
|
send(:"#{key}=", opts[key])
|
||||||
end
|
end
|
||||||
# force the encoding to utf8
|
# force the encoding to utf8
|
||||||
@encoding = nil
|
|
||||||
self.charset_name = opts[:encoding] || 'utf8'
|
self.charset_name = opts[:encoding] || 'utf8'
|
||||||
|
|
||||||
ssl_set(*opts.values_at(:sslkey, :sslcert, :sslca, :sslcapath, :sslciper))
|
ssl_set(*opts.values_at(:sslkey, :sslcert, :sslca, :sslcapath, :sslciper))
|
||||||
|
Loading…
Reference in New Issue
Block a user