mysql2 0.1.9 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/CHANGELOG.md +12 -1
- data/README.rdoc +69 -5
- data/Rakefile +4 -6
- data/VERSION +1 -1
- data/benchmark/active_record.rb +3 -0
- data/benchmark/allocations.rb +33 -0
- data/benchmark/escape.rb +24 -22
- data/benchmark/query_with_mysql_casting.rb +2 -2
- data/benchmark/query_without_mysql_casting.rb +2 -2
- data/benchmark/setup_db.rb +6 -2
- data/benchmark/thread_alone.rb +20 -0
- data/examples/threaded.rb +20 -0
- data/ext/mysql2/client.c +540 -0
- data/ext/mysql2/client.h +40 -0
- data/ext/mysql2/extconf.rb +6 -4
- data/ext/mysql2/mysql2_ext.c +3 -487
- data/ext/mysql2/mysql2_ext.h +1 -67
- data/ext/mysql2/result.c +151 -43
- data/ext/mysql2/result.h +13 -0
- data/lib/active_record/connection_adapters/em_mysql2_adapter.rb +14 -10
- data/lib/mysql2.rb +1 -1
- data/lib/mysql2/client.rb +17 -1
- data/mysql2.gemspec +14 -9
- data/spec/mysql2/client_spec.rb +50 -12
- data/spec/mysql2/result_spec.rb +25 -66
- data/spec/spec_helper.rb +62 -0
- data/tasks/benchmarks.rake +8 -0
- data/tasks/compile.rake +19 -0
- data/tasks/vendor_mysql.rake +41 -0
- metadata +14 -9
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +0 -598
- data/lib/sequel/adapters/mysql2.rb +0 -237
- data/spec/active_record/active_record_spec.rb +0 -149
data/ext/mysql2/mysql2_ext.h
CHANGED
@@ -26,73 +26,7 @@
|
|
26
26
|
#define RB_MYSQL_UNUSED
|
27
27
|
#endif
|
28
28
|
|
29
|
+
#include <client.h>
|
29
30
|
#include <result.h>
|
30
31
|
|
31
|
-
extern VALUE mMysql2;
|
32
|
-
|
33
|
-
/* Mysql2::Error */
|
34
|
-
extern VALUE cMysql2Error;
|
35
|
-
|
36
|
-
/* Mysql2::Result */
|
37
|
-
typedef struct {
|
38
|
-
VALUE fields;
|
39
|
-
VALUE rows;
|
40
|
-
unsigned int numberOfFields;
|
41
|
-
unsigned long numberOfRows;
|
42
|
-
unsigned long lastRowProcessed;
|
43
|
-
short int resultFreed;
|
44
|
-
MYSQL_RES *result;
|
45
|
-
} mysql2_result_wrapper;
|
46
|
-
#define GetMysql2Result(obj, sval) (sval = (mysql2_result_wrapper*)DATA_PTR(obj));
|
47
|
-
|
48
|
-
/*
|
49
|
-
* used to pass all arguments to mysql_real_connect while inside
|
50
|
-
* rb_thread_blocking_region
|
51
|
-
*/
|
52
|
-
struct nogvl_connect_args {
|
53
|
-
MYSQL *mysql;
|
54
|
-
const char *host;
|
55
|
-
const char *user;
|
56
|
-
const char *passwd;
|
57
|
-
const char *db;
|
58
|
-
unsigned int port;
|
59
|
-
const char *unix_socket;
|
60
|
-
unsigned long client_flag;
|
61
|
-
};
|
62
|
-
|
63
|
-
/*
|
64
|
-
* used to pass all arguments to mysql_send_query while inside
|
65
|
-
* rb_thread_blocking_region
|
66
|
-
*/
|
67
|
-
struct nogvl_send_query_args {
|
68
|
-
MYSQL *mysql;
|
69
|
-
VALUE sql;
|
70
|
-
};
|
71
|
-
|
72
|
-
/*
|
73
|
-
* partial emulation of the 1.9 rb_thread_blocking_region under 1.8,
|
74
|
-
* this is enough for dealing with blocking I/O functions in the
|
75
|
-
* presence of threads.
|
76
|
-
*/
|
77
|
-
#ifndef HAVE_RB_THREAD_BLOCKING_REGION
|
78
|
-
# include <rubysig.h>
|
79
|
-
# define RUBY_UBF_IO ((rb_unblock_function_t *)-1)
|
80
|
-
typedef void rb_unblock_function_t(void *);
|
81
|
-
typedef VALUE rb_blocking_function_t(void *);
|
82
|
-
static VALUE
|
83
|
-
rb_thread_blocking_region(
|
84
|
-
rb_blocking_function_t *func, void *data1,
|
85
|
-
RB_MYSQL_UNUSED rb_unblock_function_t *ubf,
|
86
|
-
RB_MYSQL_UNUSED void *data2)
|
87
|
-
{
|
88
|
-
VALUE rv;
|
89
|
-
|
90
|
-
TRAP_BEG;
|
91
|
-
rv = func(data1);
|
92
|
-
TRAP_END;
|
93
|
-
|
94
|
-
return rv;
|
95
|
-
}
|
96
|
-
#endif /* ! HAVE_RB_THREAD_BLOCKING_REGION */
|
97
|
-
|
98
32
|
#endif
|
data/ext/mysql2/result.c
CHANGED
@@ -4,19 +4,24 @@
|
|
4
4
|
rb_encoding *binaryEncoding;
|
5
5
|
#endif
|
6
6
|
|
7
|
-
ID sym_symbolize_keys;
|
8
|
-
ID intern_new, intern_utc, intern_encoding_from_charset_code;
|
9
|
-
|
10
|
-
VALUE cBigDecimal, cDate, cDateTime;
|
11
7
|
VALUE cMysql2Result;
|
12
|
-
|
8
|
+
VALUE cBigDecimal, cDate, cDateTime;
|
9
|
+
VALUE opt_decimal_zero, opt_float_zero, opt_time_year, opt_time_month;
|
10
|
+
extern VALUE mMysql2, cMysql2Client, cMysql2Error;
|
11
|
+
static VALUE intern_encoding_from_charset;
|
12
|
+
static ID intern_new, intern_utc, intern_local, intern_encoding_from_charset_code,
|
13
|
+
intern_localtime;
|
14
|
+
static ID sym_symbolize_keys, sym_as, sym_array, sym_database_timezone, sym_application_timezone,
|
15
|
+
sym_local, sym_utc, sym_cast_booleans;
|
16
|
+
static ID intern_merge;
|
13
17
|
|
14
18
|
static void rb_mysql_result_mark(void * wrapper) {
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
19
|
+
mysql2_result_wrapper * w = wrapper;
|
20
|
+
if (w) {
|
21
|
+
rb_gc_mark(w->fields);
|
22
|
+
rb_gc_mark(w->rows);
|
23
|
+
rb_gc_mark(w->encoding);
|
24
|
+
}
|
20
25
|
}
|
21
26
|
|
22
27
|
/* this may be called manually or during GC */
|
@@ -61,7 +66,7 @@ static VALUE rb_mysql_result_fetch_field(VALUE self, unsigned int idx, short int
|
|
61
66
|
MYSQL_FIELD *field = NULL;
|
62
67
|
#ifdef HAVE_RUBY_ENCODING_H
|
63
68
|
rb_encoding *default_internal_enc = rb_default_internal_encoding();
|
64
|
-
rb_encoding *conn_enc = rb_to_encoding(
|
69
|
+
rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding);
|
65
70
|
#endif
|
66
71
|
|
67
72
|
field = mysql_fetch_field_direct(wrapper->result, idx);
|
@@ -85,27 +90,21 @@ static VALUE rb_mysql_result_fetch_field(VALUE self, unsigned int idx, short int
|
|
85
90
|
return rb_field;
|
86
91
|
}
|
87
92
|
|
88
|
-
static VALUE rb_mysql_result_fetch_row(
|
89
|
-
VALUE
|
93
|
+
static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezone, int symbolizeKeys, int asArray, int castBool) {
|
94
|
+
VALUE rowVal;
|
90
95
|
mysql2_result_wrapper * wrapper;
|
91
96
|
MYSQL_ROW row;
|
92
97
|
MYSQL_FIELD * fields = NULL;
|
93
|
-
unsigned int i = 0
|
98
|
+
unsigned int i = 0;
|
94
99
|
unsigned long * fieldLengths;
|
95
100
|
void * ptr;
|
96
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
97
|
-
rb_encoding *default_internal_enc = rb_default_internal_encoding();
|
98
|
-
rb_encoding *conn_enc = rb_to_encoding(rb_iv_get(self, "@encoding"));
|
99
|
-
#endif
|
100
101
|
|
101
102
|
GetMysql2Result(self, wrapper);
|
102
103
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
}
|
108
|
-
}
|
104
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
105
|
+
rb_encoding *default_internal_enc = rb_default_internal_encoding();
|
106
|
+
rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding);
|
107
|
+
#endif
|
109
108
|
|
110
109
|
ptr = wrapper->result;
|
111
110
|
row = (MYSQL_ROW)rb_thread_blocking_region(nogvl_fetch_row, ptr, RUBY_UBF_IO, 0);
|
@@ -113,7 +112,11 @@ static VALUE rb_mysql_result_fetch_row(int argc, VALUE * argv, VALUE self) {
|
|
113
112
|
return Qnil;
|
114
113
|
}
|
115
114
|
|
116
|
-
|
115
|
+
if (asArray) {
|
116
|
+
rowVal = rb_ary_new2(wrapper->numberOfFields);
|
117
|
+
} else {
|
118
|
+
rowVal = rb_hash_new();
|
119
|
+
}
|
117
120
|
fields = mysql_fetch_fields(wrapper->result);
|
118
121
|
fieldLengths = mysql_fetch_lengths(wrapper->result);
|
119
122
|
if (wrapper->fields == Qnil) {
|
@@ -133,6 +136,10 @@ static VALUE rb_mysql_result_fetch_row(int argc, VALUE * argv, VALUE self) {
|
|
133
136
|
val = rb_str_new(row[i], fieldLengths[i]);
|
134
137
|
break;
|
135
138
|
case MYSQL_TYPE_TINY: // TINYINT field
|
139
|
+
if (castBool && fields[i].length == 1) {
|
140
|
+
val = *row[i] == '1' ? Qtrue : Qfalse;
|
141
|
+
break;
|
142
|
+
}
|
136
143
|
case MYSQL_TYPE_SHORT: // SMALLINT field
|
137
144
|
case MYSQL_TYPE_LONG: // INTEGER field
|
138
145
|
case MYSQL_TYPE_INT24: // MEDIUMINT field
|
@@ -142,16 +149,34 @@ static VALUE rb_mysql_result_fetch_row(int argc, VALUE * argv, VALUE self) {
|
|
142
149
|
break;
|
143
150
|
case MYSQL_TYPE_DECIMAL: // DECIMAL or NUMERIC field
|
144
151
|
case MYSQL_TYPE_NEWDECIMAL: // Precision math DECIMAL or NUMERIC field (MySQL 5.0.3 and up)
|
145
|
-
|
152
|
+
if (strtod(row[i], NULL) == 0.000000){
|
153
|
+
val = rb_funcall(cBigDecimal, intern_new, 1, opt_decimal_zero);
|
154
|
+
}else{
|
155
|
+
val = rb_funcall(cBigDecimal, intern_new, 1, rb_str_new(row[i], fieldLengths[i]));
|
156
|
+
}
|
146
157
|
break;
|
147
158
|
case MYSQL_TYPE_FLOAT: // FLOAT field
|
148
|
-
case MYSQL_TYPE_DOUBLE: // DOUBLE or REAL field
|
149
|
-
|
159
|
+
case MYSQL_TYPE_DOUBLE: { // DOUBLE or REAL field
|
160
|
+
double column_to_double;
|
161
|
+
column_to_double = strtod(row[i], NULL);
|
162
|
+
if (column_to_double == 0.000000){
|
163
|
+
val = opt_float_zero;
|
164
|
+
}else{
|
165
|
+
val = rb_float_new(column_to_double);
|
166
|
+
}
|
150
167
|
break;
|
168
|
+
}
|
151
169
|
case MYSQL_TYPE_TIME: { // TIME field
|
152
170
|
int hour, min, sec, tokens;
|
153
171
|
tokens = sscanf(row[i], "%2d:%2d:%2d", &hour, &min, &sec);
|
154
|
-
val = rb_funcall(rb_cTime,
|
172
|
+
val = rb_funcall(rb_cTime, db_timezone, 6, opt_time_year, opt_time_month, opt_time_month, INT2NUM(hour), INT2NUM(min), INT2NUM(sec));
|
173
|
+
if (!NIL_P(app_timezone)) {
|
174
|
+
if (app_timezone == intern_local) {
|
175
|
+
val = rb_funcall(val, intern_localtime, 0);
|
176
|
+
} else { // utc
|
177
|
+
val = rb_funcall(val, intern_utc, 0);
|
178
|
+
}
|
179
|
+
}
|
155
180
|
break;
|
156
181
|
}
|
157
182
|
case MYSQL_TYPE_TIMESTAMP: // TIMESTAMP field
|
@@ -165,7 +190,14 @@ static VALUE rb_mysql_result_fetch_row(int argc, VALUE * argv, VALUE self) {
|
|
165
190
|
rb_raise(cMysql2Error, "Invalid date: %s", row[i]);
|
166
191
|
val = Qnil;
|
167
192
|
} else {
|
168
|
-
val = rb_funcall(rb_cTime,
|
193
|
+
val = rb_funcall(rb_cTime, db_timezone, 6, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec));
|
194
|
+
if (!NIL_P(app_timezone)) {
|
195
|
+
if (app_timezone == intern_local) {
|
196
|
+
val = rb_funcall(val, intern_localtime, 0);
|
197
|
+
} else { // utc
|
198
|
+
val = rb_funcall(val, intern_utc, 0);
|
199
|
+
}
|
200
|
+
}
|
169
201
|
}
|
170
202
|
}
|
171
203
|
break;
|
@@ -220,20 +252,35 @@ static VALUE rb_mysql_result_fetch_row(int argc, VALUE * argv, VALUE self) {
|
|
220
252
|
#endif
|
221
253
|
break;
|
222
254
|
}
|
223
|
-
|
255
|
+
if (asArray) {
|
256
|
+
rb_ary_push(rowVal, val);
|
257
|
+
} else {
|
258
|
+
rb_hash_aset(rowVal, field, val);
|
259
|
+
}
|
224
260
|
} else {
|
225
|
-
|
261
|
+
if (asArray) {
|
262
|
+
rb_ary_push(rowVal, Qnil);
|
263
|
+
} else {
|
264
|
+
rb_hash_aset(rowVal, field, Qnil);
|
265
|
+
}
|
226
266
|
}
|
227
267
|
}
|
228
|
-
return
|
268
|
+
return rowVal;
|
229
269
|
}
|
230
270
|
|
231
271
|
static VALUE rb_mysql_result_fetch_fields(VALUE self) {
|
232
272
|
mysql2_result_wrapper * wrapper;
|
233
273
|
unsigned int i = 0;
|
274
|
+
short int symbolizeKeys = 0;
|
275
|
+
VALUE defaults;
|
234
276
|
|
235
277
|
GetMysql2Result(self, wrapper);
|
236
278
|
|
279
|
+
defaults = rb_iv_get(self, "@query_options");
|
280
|
+
if (rb_hash_aref(defaults, sym_symbolize_keys) == Qtrue) {
|
281
|
+
symbolizeKeys = 1;
|
282
|
+
}
|
283
|
+
|
237
284
|
if (wrapper->fields == Qnil) {
|
238
285
|
wrapper->numberOfFields = mysql_num_fields(wrapper->result);
|
239
286
|
wrapper->fields = rb_ary_new2(wrapper->numberOfFields);
|
@@ -241,7 +288,7 @@ static VALUE rb_mysql_result_fetch_fields(VALUE self) {
|
|
241
288
|
|
242
289
|
if (RARRAY_LEN(wrapper->fields) != wrapper->numberOfFields) {
|
243
290
|
for (i=0; i<wrapper->numberOfFields; i++) {
|
244
|
-
rb_mysql_result_fetch_field(self, i,
|
291
|
+
rb_mysql_result_fetch_field(self, i, symbolizeKeys);
|
245
292
|
}
|
246
293
|
}
|
247
294
|
|
@@ -249,18 +296,59 @@ static VALUE rb_mysql_result_fetch_fields(VALUE self) {
|
|
249
296
|
}
|
250
297
|
|
251
298
|
static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
|
252
|
-
VALUE opts, block;
|
299
|
+
VALUE defaults, opts, block;
|
300
|
+
ID db_timezone, app_timezone, dbTz, appTz;
|
253
301
|
mysql2_result_wrapper * wrapper;
|
254
302
|
unsigned long i;
|
303
|
+
int symbolizeKeys = 0, asArray = 0, castBool = 0;
|
255
304
|
|
256
305
|
GetMysql2Result(self, wrapper);
|
257
306
|
|
258
|
-
|
307
|
+
defaults = rb_iv_get(self, "@query_options");
|
308
|
+
if (rb_scan_args(argc, argv, "01&", &opts, &block) == 1) {
|
309
|
+
opts = rb_funcall(defaults, intern_merge, 1, opts);
|
310
|
+
} else {
|
311
|
+
opts = defaults;
|
312
|
+
}
|
313
|
+
|
314
|
+
if (rb_hash_aref(opts, sym_symbolize_keys) == Qtrue) {
|
315
|
+
symbolizeKeys = 1;
|
316
|
+
}
|
317
|
+
|
318
|
+
if (rb_hash_aref(opts, sym_as) == sym_array) {
|
319
|
+
asArray = 1;
|
320
|
+
}
|
321
|
+
|
322
|
+
if (rb_hash_aref(opts, sym_cast_booleans) == Qtrue) {
|
323
|
+
castBool = 1;
|
324
|
+
}
|
325
|
+
|
326
|
+
dbTz = rb_hash_aref(opts, sym_database_timezone);
|
327
|
+
if (dbTz == sym_local) {
|
328
|
+
db_timezone = intern_local;
|
329
|
+
} else if (dbTz == sym_utc) {
|
330
|
+
db_timezone = intern_utc;
|
331
|
+
} else {
|
332
|
+
if (!NIL_P(dbTz)) {
|
333
|
+
rb_warn(":database_timezone option must be :utc or :local - defaulting to :local");
|
334
|
+
}
|
335
|
+
db_timezone = intern_local;
|
336
|
+
}
|
337
|
+
|
338
|
+
appTz = rb_hash_aref(opts, sym_application_timezone);
|
339
|
+
if (appTz == sym_local) {
|
340
|
+
app_timezone = intern_local;
|
341
|
+
} else if (appTz == sym_utc) {
|
342
|
+
app_timezone = intern_utc;
|
343
|
+
} else {
|
344
|
+
app_timezone = Qnil;
|
345
|
+
}
|
259
346
|
|
260
347
|
if (wrapper->lastRowProcessed == 0) {
|
261
348
|
wrapper->numberOfRows = mysql_num_rows(wrapper->result);
|
262
349
|
if (wrapper->numberOfRows == 0) {
|
263
|
-
|
350
|
+
wrapper->rows = rb_ary_new();
|
351
|
+
return wrapper->rows;
|
264
352
|
}
|
265
353
|
wrapper->rows = rb_ary_new2(wrapper->numberOfRows);
|
266
354
|
}
|
@@ -279,7 +367,7 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
|
|
279
367
|
if (i < rowsProcessed) {
|
280
368
|
row = rb_ary_entry(wrapper->rows, i);
|
281
369
|
} else {
|
282
|
-
row = rb_mysql_result_fetch_row(
|
370
|
+
row = rb_mysql_result_fetch_row(self, db_timezone, app_timezone, symbolizeKeys, asArray, castBool);
|
283
371
|
rb_ary_store(wrapper->rows, i, row);
|
284
372
|
wrapper->lastRowProcessed++;
|
285
373
|
}
|
@@ -315,12 +403,12 @@ VALUE rb_mysql_result_to_obj(MYSQL_RES * r) {
|
|
315
403
|
wrapper->result = r;
|
316
404
|
wrapper->fields = Qnil;
|
317
405
|
wrapper->rows = Qnil;
|
406
|
+
wrapper->encoding = Qnil;
|
318
407
|
rb_obj_call_init(obj, 0, NULL);
|
319
408
|
return obj;
|
320
409
|
}
|
321
410
|
|
322
|
-
void init_mysql2_result()
|
323
|
-
{
|
411
|
+
void init_mysql2_result() {
|
324
412
|
cBigDecimal = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
|
325
413
|
cDate = rb_const_get(rb_cObject, rb_intern("Date"));
|
326
414
|
cDateTime = rb_const_get(rb_cObject, rb_intern("DateTime"));
|
@@ -329,11 +417,31 @@ void init_mysql2_result()
|
|
329
417
|
rb_define_method(cMysql2Result, "each", rb_mysql_result_each, -1);
|
330
418
|
rb_define_method(cMysql2Result, "fields", rb_mysql_result_fetch_fields, 0);
|
331
419
|
|
332
|
-
|
333
|
-
intern_new = rb_intern("new");
|
334
|
-
intern_utc = rb_intern("utc");
|
420
|
+
intern_encoding_from_charset = rb_intern("encoding_from_charset");
|
335
421
|
intern_encoding_from_charset_code = rb_intern("encoding_from_charset_code");
|
336
422
|
|
423
|
+
intern_new = rb_intern("new");
|
424
|
+
intern_utc = rb_intern("utc");
|
425
|
+
intern_local = rb_intern("local");
|
426
|
+
intern_merge = rb_intern("merge");
|
427
|
+
intern_localtime = rb_intern("localtime");
|
428
|
+
|
429
|
+
sym_symbolize_keys = ID2SYM(rb_intern("symbolize_keys"));
|
430
|
+
sym_as = ID2SYM(rb_intern("as"));
|
431
|
+
sym_array = ID2SYM(rb_intern("array"));
|
432
|
+
sym_local = ID2SYM(rb_intern("local"));
|
433
|
+
sym_utc = ID2SYM(rb_intern("utc"));
|
434
|
+
sym_cast_booleans = ID2SYM(rb_intern("cast_booleans"));
|
435
|
+
sym_database_timezone = ID2SYM(rb_intern("database_timezone"));
|
436
|
+
sym_application_timezone = ID2SYM(rb_intern("application_timezone"));
|
437
|
+
|
438
|
+
rb_global_variable(&opt_decimal_zero); //never GC
|
439
|
+
opt_decimal_zero = rb_str_new2("0.0");
|
440
|
+
rb_global_variable(&opt_float_zero);
|
441
|
+
opt_float_zero = rb_float_new((double)0);
|
442
|
+
opt_time_year = INT2NUM(2000);
|
443
|
+
opt_time_month = INT2NUM(1);
|
444
|
+
|
337
445
|
#ifdef HAVE_RUBY_ENCODING_H
|
338
446
|
binaryEncoding = rb_enc_find("binary");
|
339
447
|
#endif
|
data/ext/mysql2/result.h
CHANGED
@@ -4,4 +4,17 @@
|
|
4
4
|
void init_mysql2_result();
|
5
5
|
VALUE rb_mysql_result_to_obj(MYSQL_RES * r);
|
6
6
|
|
7
|
+
typedef struct {
|
8
|
+
VALUE fields;
|
9
|
+
VALUE rows;
|
10
|
+
VALUE encoding;
|
11
|
+
unsigned int numberOfFields;
|
12
|
+
unsigned long numberOfRows;
|
13
|
+
unsigned long lastRowProcessed;
|
14
|
+
short int resultFreed;
|
15
|
+
MYSQL_RES *result;
|
16
|
+
} mysql2_result_wrapper;
|
17
|
+
|
18
|
+
#define GetMysql2Result(obj, sval) (sval = (mysql2_result_wrapper*)DATA_PTR(obj));
|
19
|
+
|
7
20
|
#endif
|
@@ -42,17 +42,21 @@ module Mysql2
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def query(sql, opts={})
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
45
|
+
if EM.reactor_running?
|
46
|
+
super(sql, opts.merge(:async => true))
|
47
|
+
deferable = ::EM::DefaultDeferrable.new
|
48
|
+
::EM.watch(self.socket, Watcher, self, deferable).notify_readable = true
|
49
|
+
fiber = Fiber.current
|
50
|
+
deferable.callback do |result|
|
51
|
+
fiber.resume(result)
|
52
|
+
end
|
53
|
+
deferable.errback do |err|
|
54
|
+
fiber.resume(err)
|
55
|
+
end
|
56
|
+
Fiber.yield
|
57
|
+
else
|
58
|
+
super(sql, opts)
|
54
59
|
end
|
55
|
-
Fiber.yield
|
56
60
|
end
|
57
61
|
end
|
58
62
|
end
|
data/lib/mysql2.rb
CHANGED