mysql2 0.1.9 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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