mysql2 0.4.10 → 0.5.1
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.
- checksums.yaml +4 -4
- data/README.md +23 -6
- data/examples/eventmachine.rb +0 -2
- data/examples/threaded.rb +2 -4
- data/ext/mysql2/client.c +100 -51
- data/ext/mysql2/client.h +1 -39
- data/ext/mysql2/extconf.rb +23 -20
- data/ext/mysql2/mysql2_ext.c +2 -1
- data/ext/mysql2/mysql2_ext.h +8 -4
- data/ext/mysql2/result.c +15 -75
- data/ext/mysql2/result.h +2 -3
- data/ext/mysql2/statement.c +78 -71
- data/ext/mysql2/statement.h +0 -2
- data/ext/mysql2/wait_for_single_fd.h +2 -1
- data/lib/mysql2.rb +14 -15
- data/lib/mysql2/client.rb +33 -27
- data/lib/mysql2/em.rb +2 -4
- data/lib/mysql2/error.rb +49 -20
- data/lib/mysql2/result.rb +2 -0
- data/lib/mysql2/statement.rb +3 -9
- data/lib/mysql2/version.rb +1 -1
- data/spec/em/em_spec.rb +5 -6
- data/spec/mysql2/client_spec.rb +206 -173
- data/spec/mysql2/error_spec.rb +0 -4
- data/spec/mysql2/result_spec.rb +94 -154
- data/spec/mysql2/statement_spec.rb +105 -169
- data/spec/spec_helper.rb +6 -2
- data/support/mysql_enc_to_ruby.rb +2 -2
- data/support/ruby_enc_to_mysql.rb +5 -5
- metadata +6 -5
data/ext/mysql2/result.h
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
#ifndef MYSQL2_RESULT_H
|
2
2
|
#define MYSQL2_RESULT_H
|
3
|
-
#include <stdbool.h>
|
4
3
|
|
5
4
|
void init_mysql2_result(void);
|
6
5
|
VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_RES *r, VALUE statement);
|
@@ -22,8 +21,8 @@ typedef struct {
|
|
22
21
|
mysql_client_wrapper *client_wrapper;
|
23
22
|
/* statement result bind buffers */
|
24
23
|
MYSQL_BIND *result_buffers;
|
25
|
-
|
26
|
-
|
24
|
+
my_bool *is_null;
|
25
|
+
my_bool *error;
|
27
26
|
unsigned long *length;
|
28
27
|
} mysql2_result_wrapper;
|
29
28
|
|
data/ext/mysql2/statement.c
CHANGED
@@ -1,12 +1,9 @@
|
|
1
1
|
#include <mysql2_ext.h>
|
2
2
|
|
3
|
-
VALUE
|
4
|
-
|
5
|
-
static VALUE sym_stream, intern_new_with_args, intern_each, intern_to_s;
|
3
|
+
extern VALUE mMysql2, cMysql2Error;
|
4
|
+
static VALUE cMysql2Statement, cBigDecimal, cDateTime, cDate;
|
5
|
+
static VALUE sym_stream, intern_new_with_args, intern_each, intern_to_s, intern_merge_bang;
|
6
6
|
static VALUE intern_sec_fraction, intern_usec, intern_sec, intern_min, intern_hour, intern_day, intern_month, intern_year;
|
7
|
-
#ifndef HAVE_RB_BIG_CMP
|
8
|
-
static ID id_cmp;
|
9
|
-
#endif
|
10
7
|
|
11
8
|
#define GET_STATEMENT(self) \
|
12
9
|
mysql_stmt_wrapper *stmt_wrapper; \
|
@@ -21,7 +18,7 @@ static void rb_mysql_stmt_mark(void * ptr) {
|
|
21
18
|
rb_gc_mark(stmt_wrapper->client);
|
22
19
|
}
|
23
20
|
|
24
|
-
static void *nogvl_stmt_close(void *
|
21
|
+
static void *nogvl_stmt_close(void *ptr) {
|
25
22
|
mysql_stmt_wrapper *stmt_wrapper = ptr;
|
26
23
|
if (stmt_wrapper->stmt) {
|
27
24
|
mysql_stmt_close(stmt_wrapper->stmt);
|
@@ -30,7 +27,7 @@ static void *nogvl_stmt_close(void * ptr) {
|
|
30
27
|
return NULL;
|
31
28
|
}
|
32
29
|
|
33
|
-
static void rb_mysql_stmt_free(void *
|
30
|
+
static void rb_mysql_stmt_free(void *ptr) {
|
34
31
|
mysql_stmt_wrapper *stmt_wrapper = ptr;
|
35
32
|
decr_mysql2_stmt(stmt_wrapper);
|
36
33
|
}
|
@@ -50,7 +47,6 @@ void rb_raise_mysql2_stmt_error(mysql_stmt_wrapper *stmt_wrapper) {
|
|
50
47
|
VALUE rb_error_msg = rb_str_new2(mysql_stmt_error(stmt_wrapper->stmt));
|
51
48
|
VALUE rb_sql_state = rb_tainted_str_new2(mysql_stmt_sqlstate(stmt_wrapper->stmt));
|
52
49
|
|
53
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
54
50
|
rb_encoding *conn_enc;
|
55
51
|
conn_enc = rb_to_encoding(wrapper->encoding);
|
56
52
|
|
@@ -62,7 +58,6 @@ void rb_raise_mysql2_stmt_error(mysql_stmt_wrapper *stmt_wrapper) {
|
|
62
58
|
rb_error_msg = rb_str_export_to_enc(rb_error_msg, default_internal_enc);
|
63
59
|
rb_sql_state = rb_str_export_to_enc(rb_sql_state, default_internal_enc);
|
64
60
|
}
|
65
|
-
#endif
|
66
61
|
|
67
62
|
e = rb_funcall(cMysql2Error, intern_new_with_args, 4,
|
68
63
|
rb_error_msg,
|
@@ -96,9 +91,7 @@ static void *nogvl_prepare_statement(void *ptr) {
|
|
96
91
|
VALUE rb_mysql_stmt_new(VALUE rb_client, VALUE sql) {
|
97
92
|
mysql_stmt_wrapper *stmt_wrapper;
|
98
93
|
VALUE rb_stmt;
|
99
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
100
94
|
rb_encoding *conn_enc;
|
101
|
-
#endif
|
102
95
|
|
103
96
|
Check_Type(sql, T_STRING);
|
104
97
|
|
@@ -114,9 +107,7 @@ VALUE rb_mysql_stmt_new(VALUE rb_client, VALUE sql) {
|
|
114
107
|
{
|
115
108
|
GET_CLIENT(rb_client);
|
116
109
|
stmt_wrapper->stmt = mysql_stmt_init(wrapper->client);
|
117
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
118
110
|
conn_enc = rb_to_encoding(wrapper->encoding);
|
119
|
-
#endif
|
120
111
|
}
|
121
112
|
if (stmt_wrapper->stmt == NULL) {
|
122
113
|
rb_raise(cMysql2Error, "Unable to initialize prepared statement: out of memory");
|
@@ -124,7 +115,7 @@ VALUE rb_mysql_stmt_new(VALUE rb_client, VALUE sql) {
|
|
124
115
|
|
125
116
|
// set STMT_ATTR_UPDATE_MAX_LENGTH attr
|
126
117
|
{
|
127
|
-
|
118
|
+
my_bool truth = 1;
|
128
119
|
if (mysql_stmt_attr_set(stmt_wrapper->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &truth)) {
|
129
120
|
rb_raise(cMysql2Error, "Unable to initialize prepared statement: set STMT_ATTR_UPDATE_MAX_LENGTH");
|
130
121
|
}
|
@@ -134,11 +125,8 @@ VALUE rb_mysql_stmt_new(VALUE rb_client, VALUE sql) {
|
|
134
125
|
{
|
135
126
|
struct nogvl_prepare_statement_args args;
|
136
127
|
args.stmt = stmt_wrapper->stmt;
|
137
|
-
args.sql = sql;
|
138
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
139
128
|
// ensure the string is in the encoding the connection is expecting
|
140
|
-
args.sql = rb_str_export_to_enc(
|
141
|
-
#endif
|
129
|
+
args.sql = rb_str_export_to_enc(sql, conn_enc);
|
142
130
|
args.sql_ptr = RSTRING_PTR(sql);
|
143
131
|
args.sql_len = RSTRING_LEN(sql);
|
144
132
|
|
@@ -154,7 +142,7 @@ VALUE rb_mysql_stmt_new(VALUE rb_client, VALUE sql) {
|
|
154
142
|
*
|
155
143
|
* Returns the number of parameters the prepared statement expects.
|
156
144
|
*/
|
157
|
-
static VALUE
|
145
|
+
static VALUE rb_mysql_stmt_param_count(VALUE self) {
|
158
146
|
GET_STATEMENT(self);
|
159
147
|
|
160
148
|
return ULL2NUM(mysql_stmt_param_count(stmt_wrapper->stmt));
|
@@ -164,13 +152,13 @@ static VALUE param_count(VALUE self) {
|
|
164
152
|
*
|
165
153
|
* Returns the number of fields the prepared statement returns.
|
166
154
|
*/
|
167
|
-
static VALUE
|
155
|
+
static VALUE rb_mysql_stmt_field_count(VALUE self) {
|
168
156
|
GET_STATEMENT(self);
|
169
157
|
|
170
158
|
return UINT2NUM(mysql_stmt_field_count(stmt_wrapper->stmt));
|
171
159
|
}
|
172
160
|
|
173
|
-
static void *
|
161
|
+
static void *nogvl_stmt_execute(void *ptr) {
|
174
162
|
MYSQL_STMT *stmt = ptr;
|
175
163
|
|
176
164
|
if (mysql_stmt_execute(stmt)) {
|
@@ -196,7 +184,7 @@ static void set_buffer_for_string(MYSQL_BIND* bind_buffer, unsigned long *length
|
|
196
184
|
* the buffer is a Ruby string pointer and not our memory to manage.
|
197
185
|
*/
|
198
186
|
#define FREE_BINDS \
|
199
|
-
for (i = 0; i <
|
187
|
+
for (i = 0; i < bind_count; i++) { \
|
200
188
|
if (bind_buffers[i].buffer && NIL_P(params_enc[i])) { \
|
201
189
|
xfree(bind_buffers[i].buffer); \
|
202
190
|
} \
|
@@ -211,6 +199,8 @@ static int my_big2ll(VALUE bignum, LONG_LONG *ptr)
|
|
211
199
|
{
|
212
200
|
unsigned LONG_LONG num;
|
213
201
|
size_t len;
|
202
|
+
// rb_absint_size was added in 2.1.0. See:
|
203
|
+
// https://github.com/ruby/ruby/commit/9fea875
|
214
204
|
#ifdef HAVE_RB_ABSINT_SIZE
|
215
205
|
int nlz_bits = 0;
|
216
206
|
len = rb_absint_size(bignum, &nlz_bits);
|
@@ -229,16 +219,15 @@ static int my_big2ll(VALUE bignum, LONG_LONG *ptr)
|
|
229
219
|
#ifdef HAVE_RB_ABSINT_SIZE
|
230
220
|
nlz_bits == 0 &&
|
231
221
|
#endif
|
222
|
+
// rb_absint_singlebit_p was added in 2.1.0. See:
|
223
|
+
// https://github.com/ruby/ruby/commit/e5ff9d5
|
232
224
|
#if defined(HAVE_RB_ABSINT_SIZE) && defined(HAVE_RB_ABSINT_SINGLEBIT_P)
|
233
225
|
/* Optimized to avoid object allocation for Ruby 2.1+
|
234
226
|
* only -0x8000000000000000 is safe if `len == 8 && nlz_bits == 0`
|
235
227
|
*/
|
236
228
|
!rb_absint_singlebit_p(bignum)
|
237
|
-
#elif defined(HAVE_RB_BIG_CMP)
|
238
|
-
rb_big_cmp(bignum, LL2NUM(LLONG_MIN)) == INT2FIX(-1)
|
239
229
|
#else
|
240
|
-
|
241
|
-
rb_funcall(bignum, id_cmp, 1, LL2NUM(LLONG_MIN)) == INT2FIX(-1)
|
230
|
+
rb_big_cmp(bignum, LL2NUM(LLONG_MIN)) == INT2FIX(-1)
|
242
231
|
#endif
|
243
232
|
) {
|
244
233
|
goto overflow;
|
@@ -254,44 +243,45 @@ overflow:
|
|
254
243
|
*
|
255
244
|
* Executes the current prepared statement, returns +result+.
|
256
245
|
*/
|
257
|
-
static VALUE
|
246
|
+
static VALUE rb_mysql_stmt_execute(int argc, VALUE *argv, VALUE self) {
|
258
247
|
MYSQL_BIND *bind_buffers = NULL;
|
259
248
|
unsigned long *length_buffers = NULL;
|
260
249
|
unsigned long bind_count;
|
261
|
-
long i;
|
250
|
+
unsigned long i;
|
262
251
|
MYSQL_STMT *stmt;
|
263
252
|
MYSQL_RES *metadata;
|
253
|
+
VALUE opts;
|
264
254
|
VALUE current;
|
265
255
|
VALUE resultObj;
|
266
|
-
VALUE *params_enc;
|
256
|
+
VALUE *params_enc = NULL;
|
267
257
|
int is_streaming;
|
268
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
269
258
|
rb_encoding *conn_enc;
|
270
|
-
#endif
|
271
259
|
|
272
260
|
GET_STATEMENT(self);
|
273
261
|
GET_CLIENT(stmt_wrapper->client);
|
274
262
|
|
275
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
276
263
|
conn_enc = rb_to_encoding(wrapper->encoding);
|
277
|
-
#endif
|
278
|
-
|
279
|
-
/* Scratch space for string encoding exports, allocate on the stack. */
|
280
|
-
params_enc = alloca(sizeof(VALUE) * argc);
|
281
264
|
|
282
265
|
stmt = stmt_wrapper->stmt;
|
283
|
-
|
284
266
|
bind_count = mysql_stmt_param_count(stmt);
|
285
|
-
|
286
|
-
|
267
|
+
|
268
|
+
// Get count of ordinary arguments, and extract hash opts/keyword arguments
|
269
|
+
// Use a local scope to avoid leaking the temporary count variable
|
270
|
+
{
|
271
|
+
int c = rb_scan_args(argc, argv, "*:", NULL, &opts);
|
272
|
+
if (c != (long)bind_count) {
|
273
|
+
rb_raise(cMysql2Error, "Bind parameter count (%ld) doesn't match number of arguments (%d)", bind_count, c);
|
274
|
+
}
|
287
275
|
}
|
288
276
|
|
289
277
|
// setup any bind variables in the query
|
290
278
|
if (bind_count > 0) {
|
279
|
+
// Scratch space for string encoding exports, allocate on the stack
|
280
|
+
params_enc = alloca(sizeof(VALUE) * bind_count);
|
291
281
|
bind_buffers = xcalloc(bind_count, sizeof(MYSQL_BIND));
|
292
282
|
length_buffers = xcalloc(bind_count, sizeof(unsigned long));
|
293
283
|
|
294
|
-
for (i = 0; i <
|
284
|
+
for (i = 0; i < bind_count; i++) {
|
295
285
|
bind_buffers[i].buffer = NULL;
|
296
286
|
params_enc[i] = Qnil;
|
297
287
|
|
@@ -319,12 +309,8 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) {
|
|
319
309
|
*(LONG_LONG*)(bind_buffers[i].buffer) = num;
|
320
310
|
} else {
|
321
311
|
/* The bignum was larger than we can fit in LONG_LONG, send it as a string */
|
322
|
-
VALUE rb_val_as_string = rb_big2str(argv[i], 10);
|
323
312
|
bind_buffers[i].buffer_type = MYSQL_TYPE_NEWDECIMAL;
|
324
|
-
params_enc[i] =
|
325
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
326
|
-
params_enc[i] = rb_str_export_to_enc(params_enc[i], conn_enc);
|
327
|
-
#endif
|
313
|
+
params_enc[i] = rb_str_export_to_enc(rb_big2str(argv[i], 10), conn_enc);
|
328
314
|
set_buffer_for_string(&bind_buffers[i], &length_buffers[i], params_enc[i]);
|
329
315
|
}
|
330
316
|
}
|
@@ -338,9 +324,7 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) {
|
|
338
324
|
bind_buffers[i].buffer_type = MYSQL_TYPE_STRING;
|
339
325
|
|
340
326
|
params_enc[i] = argv[i];
|
341
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
342
327
|
params_enc[i] = rb_str_export_to_enc(params_enc[i], conn_enc);
|
343
|
-
#endif
|
344
328
|
set_buffer_for_string(&bind_buffers[i], &length_buffers[i], params_enc[i]);
|
345
329
|
break;
|
346
330
|
case T_TRUE:
|
@@ -405,9 +389,7 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) {
|
|
405
389
|
VALUE rb_val_as_string = rb_funcall(argv[i], intern_to_s, 0);
|
406
390
|
|
407
391
|
params_enc[i] = rb_val_as_string;
|
408
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
409
392
|
params_enc[i] = rb_str_export_to_enc(params_enc[i], conn_enc);
|
410
|
-
#endif
|
411
393
|
set_buffer_for_string(&bind_buffers[i], &length_buffers[i], params_enc[i]);
|
412
394
|
}
|
413
395
|
break;
|
@@ -421,7 +403,40 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) {
|
|
421
403
|
}
|
422
404
|
}
|
423
405
|
|
424
|
-
|
406
|
+
// Duplicate the options hash, merge! extra opts, put the copy into the Result object
|
407
|
+
current = rb_hash_dup(rb_iv_get(stmt_wrapper->client, "@query_options"));
|
408
|
+
(void)RB_GC_GUARD(current);
|
409
|
+
Check_Type(current, T_HASH);
|
410
|
+
|
411
|
+
// Merge in hash opts/keyword arguments
|
412
|
+
if (!NIL_P(opts)) {
|
413
|
+
rb_funcall(current, intern_merge_bang, 1, opts);
|
414
|
+
}
|
415
|
+
|
416
|
+
is_streaming = (Qtrue == rb_hash_aref(current, sym_stream));
|
417
|
+
|
418
|
+
// From stmt_execute to mysql_stmt_result_metadata to stmt_store_result, no
|
419
|
+
// Ruby API calls are allowed so that GC is not invoked. If the connection is
|
420
|
+
// in results-streaming-mode for Statement A, and in the middle Statement B
|
421
|
+
// gets garbage collected, a message will be sent to the server notifying it
|
422
|
+
// to release Statement B, resulting in the following error:
|
423
|
+
// Commands out of sync; you can't run this command now
|
424
|
+
//
|
425
|
+
// In streaming mode, statement execute must return a cursor because we
|
426
|
+
// cannot prevent other Statement objects from being garbage collected
|
427
|
+
// between fetches of each row of the result set. The following error
|
428
|
+
// occurs if cursor mode is not set:
|
429
|
+
// Row retrieval was canceled by mysql_stmt_close
|
430
|
+
|
431
|
+
if (is_streaming) {
|
432
|
+
unsigned long type = CURSOR_TYPE_READ_ONLY;
|
433
|
+
if (mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, &type)) {
|
434
|
+
FREE_BINDS;
|
435
|
+
rb_raise(cMysql2Error, "Unable to stream prepared statement, could not set CURSOR_TYPE_READ_ONLY");
|
436
|
+
}
|
437
|
+
}
|
438
|
+
|
439
|
+
if ((VALUE)rb_thread_call_without_gvl(nogvl_stmt_execute, stmt, RUBY_UBF_IO, 0) == Qfalse) {
|
425
440
|
FREE_BINDS;
|
426
441
|
rb_raise_mysql2_stmt_error(stmt_wrapper);
|
427
442
|
}
|
@@ -439,11 +454,6 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) {
|
|
439
454
|
return Qnil;
|
440
455
|
}
|
441
456
|
|
442
|
-
current = rb_hash_dup(rb_iv_get(stmt_wrapper->client, "@query_options"));
|
443
|
-
(void)RB_GC_GUARD(current);
|
444
|
-
Check_Type(current, T_HASH);
|
445
|
-
|
446
|
-
is_streaming = (Qtrue == rb_hash_aref(current, sym_stream));
|
447
457
|
if (!is_streaming) {
|
448
458
|
// recieve the whole result set from the server
|
449
459
|
if (mysql_stmt_store_result(stmt)) {
|
@@ -455,6 +465,8 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) {
|
|
455
465
|
|
456
466
|
resultObj = rb_mysql_result_to_obj(stmt_wrapper->client, wrapper->encoding, current, metadata, self);
|
457
467
|
|
468
|
+
rb_mysql_set_server_query_flags(wrapper->client, resultObj);
|
469
|
+
|
458
470
|
if (!is_streaming) {
|
459
471
|
// cache all result
|
460
472
|
rb_funcall(resultObj, intern_each, 0);
|
@@ -467,27 +479,23 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) {
|
|
467
479
|
*
|
468
480
|
* Returns a list of fields that will be returned by this statement.
|
469
481
|
*/
|
470
|
-
static VALUE
|
482
|
+
static VALUE rb_mysql_stmt_fields(VALUE self) {
|
471
483
|
MYSQL_FIELD *fields;
|
472
484
|
MYSQL_RES *metadata;
|
473
485
|
unsigned int field_count;
|
474
486
|
unsigned int i;
|
475
487
|
VALUE field_list;
|
476
488
|
MYSQL_STMT* stmt;
|
477
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
478
489
|
rb_encoding *default_internal_enc, *conn_enc;
|
479
|
-
#endif
|
480
490
|
GET_STATEMENT(self);
|
481
491
|
GET_CLIENT(stmt_wrapper->client);
|
482
492
|
stmt = stmt_wrapper->stmt;
|
483
493
|
|
484
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
485
494
|
default_internal_enc = rb_default_internal_encoding();
|
486
495
|
{
|
487
496
|
GET_CLIENT(stmt_wrapper->client);
|
488
497
|
conn_enc = rb_to_encoding(wrapper->encoding);
|
489
498
|
}
|
490
|
-
#endif
|
491
499
|
|
492
500
|
metadata = mysql_stmt_result_metadata(stmt);
|
493
501
|
if (metadata == NULL) {
|
@@ -508,12 +516,10 @@ static VALUE fields(VALUE self) {
|
|
508
516
|
VALUE rb_field;
|
509
517
|
|
510
518
|
rb_field = rb_str_new(fields[i].name, fields[i].name_length);
|
511
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
512
519
|
rb_enc_associate(rb_field, conn_enc);
|
513
520
|
if (default_internal_enc) {
|
514
521
|
rb_field = rb_str_export_to_enc(rb_field, default_internal_enc);
|
515
522
|
}
|
516
|
-
#endif
|
517
523
|
|
518
524
|
rb_ary_store(field_list, (long)i, rb_field);
|
519
525
|
}
|
@@ -564,12 +570,15 @@ static VALUE rb_mysql_stmt_close(VALUE self) {
|
|
564
570
|
}
|
565
571
|
|
566
572
|
void init_mysql2_statement() {
|
567
|
-
|
573
|
+
cDate = rb_const_get(rb_cObject, rb_intern("Date"));
|
574
|
+
cDateTime = rb_const_get(rb_cObject, rb_intern("DateTime"));
|
575
|
+
cBigDecimal = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
|
568
576
|
|
569
|
-
|
570
|
-
rb_define_method(cMysql2Statement, "
|
571
|
-
rb_define_method(cMysql2Statement, "
|
572
|
-
rb_define_method(cMysql2Statement, "
|
577
|
+
cMysql2Statement = rb_define_class_under(mMysql2, "Statement", rb_cObject);
|
578
|
+
rb_define_method(cMysql2Statement, "param_count", rb_mysql_stmt_param_count, 0);
|
579
|
+
rb_define_method(cMysql2Statement, "field_count", rb_mysql_stmt_field_count, 0);
|
580
|
+
rb_define_method(cMysql2Statement, "_execute", rb_mysql_stmt_execute, -1);
|
581
|
+
rb_define_method(cMysql2Statement, "fields", rb_mysql_stmt_fields, 0);
|
573
582
|
rb_define_method(cMysql2Statement, "last_id", rb_mysql_stmt_last_id, 0);
|
574
583
|
rb_define_method(cMysql2Statement, "affected_rows", rb_mysql_stmt_affected_rows, 0);
|
575
584
|
rb_define_method(cMysql2Statement, "close", rb_mysql_stmt_close, 0);
|
@@ -589,7 +598,5 @@ void init_mysql2_statement() {
|
|
589
598
|
intern_year = rb_intern("year");
|
590
599
|
|
591
600
|
intern_to_s = rb_intern("to_s");
|
592
|
-
|
593
|
-
id_cmp = rb_intern("<=>");
|
594
|
-
#endif
|
601
|
+
intern_merge_bang = rb_intern("merge!");
|
595
602
|
}
|
data/ext/mysql2/statement.h
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
/*
|
2
|
-
* backwards compatibility for
|
2
|
+
* backwards compatibility for Rubinius. See
|
3
|
+
* https://github.com/rubinius/rubinius/issues/3771.
|
3
4
|
*
|
4
5
|
* Ruby 1.9.3 provides this API which allows the use of ppoll() on Linux
|
5
6
|
* to minimize select() and malloc() overhead on high-numbered FDs.
|
data/lib/mysql2.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
|
-
# encoding: UTF-8
|
2
1
|
require 'date'
|
3
2
|
require 'bigdecimal'
|
4
|
-
require 'rational' unless RUBY_VERSION >= '1.9.2'
|
5
3
|
|
6
4
|
# Load libmysql.dll before requiring mysql2/mysql2.so
|
7
5
|
# This gives a chance to be flexible about the load path
|
@@ -13,16 +11,20 @@ if RUBY_PLATFORM =~ /mswin|mingw/
|
|
13
11
|
ENV['RUBY_MYSQL2_LIBMYSQL_DLL']
|
14
12
|
elsif File.exist?(File.expand_path('../vendor/libmysql.dll', File.dirname(__FILE__)))
|
15
13
|
# Use vendor/libmysql.dll if it exists, convert slashes for Win32 LoadLibrary
|
16
|
-
File.expand_path('../vendor/libmysql.dll', File.dirname(__FILE__))
|
14
|
+
File.expand_path('../vendor/libmysql.dll', File.dirname(__FILE__))
|
15
|
+
elsif defined?(RubyInstaller)
|
16
|
+
# RubyInstaller-2.4+ native build doesn't need DLL preloading
|
17
17
|
else
|
18
18
|
# This will use default / system library paths
|
19
19
|
'libmysql.dll'
|
20
20
|
end
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
if dll_path
|
23
|
+
require 'Win32API'
|
24
|
+
LoadLibrary = Win32API.new('Kernel32', 'LoadLibrary', ['P'], 'I')
|
25
|
+
if LoadLibrary.call(dll_path).zero?
|
26
|
+
abort "Failed to load libmysql.dll from #{dll_path}"
|
27
|
+
end
|
26
28
|
end
|
27
29
|
end
|
28
30
|
|
@@ -71,14 +73,11 @@ module Mysql2
|
|
71
73
|
# Timeout::ExitException was removed in Ruby 2.3.0, 2.2.3, and 2.1.8,
|
72
74
|
# but is present in earlier 2.1.x and 2.2.x, so we provide a shim.
|
73
75
|
#
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
else
|
80
|
-
::Timeout::Error
|
81
|
-
end
|
76
|
+
require 'timeout'
|
77
|
+
TIMEOUT_ERROR_CLASS = if defined?(::Timeout::ExitException)
|
78
|
+
::Timeout::ExitException
|
79
|
+
else
|
80
|
+
::Timeout::Error
|
82
81
|
end
|
83
82
|
end
|
84
83
|
end
|