@@ -18,10 +18,11 @@ VALUE cMysql2Client;
18
18
extern VALUE mMysql2 , cMysql2Error ;
19
19
static VALUE sym_id , sym_version , sym_async , sym_symbolize_keys , sym_as , sym_array , sym_stream ;
20
20
static ID intern_merge , intern_merge_bang , intern_error_number_eql , intern_sql_state_eql ;
21
+ static ID intern_brackets , intern_new ;
21
22
22
23
#ifndef HAVE_RB_HASH_DUP
23
- static VALUE rb_hash_dup (VALUE other ) {
24
- return rb_funcall (rb_cHash , rb_intern ( "[]" ) , 1 , other );
24
+ VALUE rb_hash_dup (VALUE other ) {
25
+ return rb_funcall (rb_cHash , intern_brackets , 1 , other );
25
26
}
26
27
#endif
27
28
@@ -30,25 +31,12 @@ static VALUE rb_hash_dup(VALUE other) {
30
31
rb_raise(cMysql2Error, "MySQL client is not initialized"); \
31
32
}
32
33
33
- #define REQUIRE_CONNECTED (wrapper ) \
34
- REQUIRE_INITIALIZED(wrapper) \
35
- if (!wrapper->connected && !wrapper->reconnect_enabled) { \
36
- rb_raise(cMysql2Error, "closed MySQL connection"); \
37
- }
38
-
39
34
#define REQUIRE_NOT_CONNECTED (wrapper ) \
40
35
REQUIRE_INITIALIZED(wrapper) \
41
36
if (wrapper->connected) { \
42
37
rb_raise(cMysql2Error, "MySQL connection is already open"); \
43
38
}
44
39
45
- #define MARK_CONN_INACTIVE (conn ) \
46
- wrapper->active_thread = Qnil;
47
-
48
- #define GET_CLIENT (self ) \
49
- mysql_client_wrapper *wrapper; \
50
- Data_Get_Struct(self, mysql_client_wrapper, wrapper)
51
-
52
40
/*
53
41
* compatability with mysql-connector-c, where LIBMYSQL_VERSION is the correct
54
42
* variable to use, but MYSQL_SERVER_VERSION gives the correct numbers when
@@ -136,7 +124,7 @@ static VALUE rb_raise_mysql2_error(mysql_client_wrapper *wrapper) {
136
124
rb_enc_associate (rb_sql_state , rb_usascii_encoding ());
137
125
#endif
138
126
139
- e = rb_funcall (cMysql2Error , rb_intern ( "new" ) , 2 , rb_error_msg , LONG2FIX (wrapper -> server_version ));
127
+ e = rb_funcall (cMysql2Error , intern_new , 2 , rb_error_msg , LONG2FIX (wrapper -> server_version ));
140
128
rb_funcall (e , intern_error_number_eql , 1 , UINT2NUM (mysql_errno (wrapper -> client )));
141
129
rb_funcall (e , intern_sql_state_eql , 1 , rb_sql_state );
142
130
rb_exc_raise (e );
@@ -247,6 +235,7 @@ static void rb_mysql_client_free(void *ptr) {
247
235
void decr_mysql2_client (mysql_client_wrapper * wrapper )
248
236
{
249
237
wrapper -> refcount -- ;
238
+
250
239
if (wrapper -> refcount == 0 ) {
251
240
nogvl_close (wrapper );
252
241
xfree (wrapper -> client );
@@ -267,6 +256,7 @@ static VALUE allocate(VALUE klass) {
267
256
wrapper -> initialized = 0 ; /* means that that the wrapper is initialized */
268
257
wrapper -> refcount = 1 ;
269
258
wrapper -> client = (MYSQL * )xmalloc (sizeof (MYSQL ));
259
+
270
260
return obj ;
271
261
}
272
262
@@ -415,7 +405,7 @@ static VALUE do_send_query(void *args) {
415
405
mysql_client_wrapper * wrapper = query_args -> wrapper ;
416
406
if ((VALUE )rb_thread_call_without_gvl (nogvl_send_query , args , RUBY_UBF_IO , 0 ) == Qfalse ) {
417
407
/* an error occurred, we're not active anymore */
418
- MARK_CONN_INACTIVE ( self ) ;
408
+ wrapper -> active_thread = Qnil ;
419
409
return rb_raise_mysql2_error (wrapper );
420
410
}
421
411
return Qnil ;
@@ -501,7 +491,7 @@ static VALUE rb_mysql_client_async_result(VALUE self) {
501
491
current = rb_hash_dup (rb_iv_get (self , "@current_query_options" ));
502
492
RB_GC_GUARD (current );
503
493
Check_Type (current , T_HASH );
504
- resultObj = rb_mysql_result_to_obj (self , wrapper -> encoding , current , result );
494
+ resultObj = rb_mysql_result_to_obj (self , wrapper -> encoding , current , result , NULL );
505
495
506
496
return resultObj ;
507
497
}
@@ -598,6 +588,25 @@ static VALUE finish_and_mark_inactive(void *args) {
598
588
}
599
589
#endif
600
590
591
+ void rb_mysql_client_set_active_thread (VALUE self ) {
592
+ VALUE thread_current = rb_thread_current ();
593
+ GET_CLIENT (self );
594
+
595
+ // see if this connection is still waiting on a result from a previous query
596
+ if (NIL_P (wrapper -> active_thread )) {
597
+ // mark this connection active
598
+ wrapper -> active_thread = thread_current ;
599
+ } else if (wrapper -> active_thread == thread_current ) {
600
+ rb_raise (cMysql2Error , "This connection is still waiting for a result, try again once you have the result" );
601
+ } else {
602
+ VALUE inspect = rb_inspect (wrapper -> active_thread );
603
+ const char * thr = StringValueCStr (inspect );
604
+
605
+ rb_raise (cMysql2Error , "This connection is in use by: %s" , thr );
606
+ RB_GC_GUARD (inspect );
607
+ }
608
+ }
609
+
601
610
/* call-seq:
602
611
* client.abandon_results!
603
612
*
@@ -641,7 +650,6 @@ static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) {
641
650
struct nogvl_send_query_args args ;
642
651
int async = 0 ;
643
652
VALUE opts , current ;
644
- VALUE thread_current = rb_thread_current ();
645
653
#ifdef HAVE_RUBY_ENCODING_H
646
654
rb_encoding * conn_enc ;
647
655
#endif
@@ -671,23 +679,10 @@ static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) {
671
679
#endif
672
680
args .sql_ptr = StringValuePtr (args .sql );
673
681
args .sql_len = RSTRING_LEN (args .sql );
674
-
675
- /* see if this connection is still waiting on a result from a previous query */
676
- if (NIL_P (wrapper -> active_thread )) {
677
- /* mark this connection active */
678
- wrapper -> active_thread = thread_current ;
679
- } else if (wrapper -> active_thread == thread_current ) {
680
- rb_raise (cMysql2Error , "This connection is still waiting for a result, try again once you have the result" );
681
- } else {
682
- VALUE inspect = rb_inspect (wrapper -> active_thread );
683
- const char * thr = StringValueCStr (inspect );
684
-
685
- rb_raise (cMysql2Error , "This connection is in use by: %s" , thr );
686
- RB_GC_GUARD (inspect );
687
- }
688
-
689
682
args .wrapper = wrapper ;
690
683
684
+ rb_mysql_client_set_active_thread (self );
685
+
691
686
#ifndef _WIN32
692
687
rb_rescue2 (do_send_query , (VALUE )& args , disconnect_and_raise , self , rb_eException , (VALUE )0 );
693
688
@@ -1080,7 +1075,7 @@ static VALUE rb_mysql_client_store_result(VALUE self)
1080
1075
current = rb_hash_dup (rb_iv_get (self , "@current_query_options" ));
1081
1076
RB_GC_GUARD (current );
1082
1077
Check_Type (current , T_HASH );
1083
- resultObj = rb_mysql_result_to_obj (self , wrapper -> encoding , current , result );
1078
+ resultObj = rb_mysql_result_to_obj (self , wrapper -> encoding , current , result , NULL );
1084
1079
1085
1080
return resultObj ;
1086
1081
}
@@ -1220,6 +1215,17 @@ static VALUE initialize_ext(VALUE self) {
1220
1215
return self ;
1221
1216
}
1222
1217
1218
+ /* call-seq: client.prepare # => Mysql2::Statement
1219
+ *
1220
+ * Create a new prepared statement.
1221
+ */
1222
+ static VALUE rb_mysql_client_prepare_statement (VALUE self , VALUE sql ) {
1223
+ GET_CLIENT (self );
1224
+ REQUIRE_CONNECTED (wrapper );
1225
+
1226
+ return rb_mysql_stmt_new (self , sql );
1227
+ }
1228
+
1223
1229
void init_mysql2_client () {
1224
1230
/* verify the libmysql we're about to use was the version we were built against
1225
1231
https://github.com/luislavena/mysql-gem/commit/a600a9c459597da0712f70f43736e24b484f8a99 */
@@ -1265,6 +1271,7 @@ void init_mysql2_client() {
1265
1271
rb_define_method (cMysql2Client , "async_result" , rb_mysql_client_async_result , 0 );
1266
1272
rb_define_method (cMysql2Client , "last_id" , rb_mysql_client_last_id , 0 );
1267
1273
rb_define_method (cMysql2Client , "affected_rows" , rb_mysql_client_affected_rows , 0 );
1274
+ rb_define_method (cMysql2Client , "prepare" , rb_mysql_client_prepare_statement , 1 );
1268
1275
rb_define_method (cMysql2Client , "thread_id" , rb_mysql_client_thread_id , 0 );
1269
1276
rb_define_method (cMysql2Client , "ping" , rb_mysql_client_ping , 0 );
1270
1277
rb_define_method (cMysql2Client , "select_db" , rb_mysql_client_select_db , 1 );
@@ -1299,6 +1306,8 @@ void init_mysql2_client() {
1299
1306
sym_array = ID2SYM (rb_intern ("array" ));
1300
1307
sym_stream = ID2SYM (rb_intern ("stream" ));
1301
1308
1309
+ intern_brackets = rb_intern ("[]" );
1310
+ intern_new = rb_intern ("new" );
1302
1311
intern_merge = rb_intern ("merge" );
1303
1312
intern_merge_bang = rb_intern ("merge!" );
1304
1313
intern_error_number_eql = rb_intern ("error_number=" );
0 commit comments