mysql2 0.4.10 → 0.5.3
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 +5 -5
- data/README.md +66 -32
- data/ext/mysql2/client.c +125 -59
- data/ext/mysql2/client.h +1 -39
- data/ext/mysql2/extconf.rb +24 -21
- data/ext/mysql2/mysql2_ext.c +2 -1
- data/ext/mysql2/mysql2_ext.h +8 -4
- data/ext/mysql2/mysql_enc_name_to_ruby.h +60 -56
- data/ext/mysql2/mysql_enc_to_ruby.h +64 -3
- data/ext/mysql2/result.c +32 -85
- data/ext/mysql2/result.h +2 -3
- data/ext/mysql2/statement.c +81 -72
- data/ext/mysql2/statement.h +0 -2
- data/ext/mysql2/wait_for_single_fd.h +2 -1
- data/lib/mysql2.rb +17 -15
- data/lib/mysql2/client.rb +33 -27
- data/lib/mysql2/em.rb +2 -4
- data/lib/mysql2/error.rb +51 -22
- data/lib/mysql2/result.rb +2 -0
- data/lib/mysql2/statement.rb +3 -9
- data/lib/mysql2/version.rb +1 -1
- data/support/5072E1F5.asc +5 -5
- data/support/mysql_enc_to_ruby.rb +8 -3
- data/support/ruby_enc_to_mysql.rb +7 -5
- metadata +8 -58
- data/examples/eventmachine.rb +0 -21
- data/examples/threaded.rb +0 -18
- data/spec/configuration.yml.example +0 -11
- data/spec/em/em_spec.rb +0 -136
- data/spec/my.cnf.example +0 -9
- data/spec/mysql2/client_spec.rb +0 -1039
- data/spec/mysql2/error_spec.rb +0 -82
- data/spec/mysql2/result_spec.rb +0 -545
- data/spec/mysql2/statement_spec.rb +0 -776
- data/spec/rcov.opts +0 -3
- data/spec/spec_helper.rb +0 -108
- data/spec/ssl/ca-cert.pem +0 -17
- data/spec/ssl/ca-key.pem +0 -27
- data/spec/ssl/ca.cnf +0 -22
- data/spec/ssl/cert.cnf +0 -22
- data/spec/ssl/client-cert.pem +0 -17
- data/spec/ssl/client-key.pem +0 -27
- data/spec/ssl/client-req.pem +0 -15
- data/spec/ssl/gen_certs.sh +0 -48
- data/spec/ssl/pkcs8-client-key.pem +0 -28
- data/spec/ssl/pkcs8-server-key.pem +0 -28
- data/spec/ssl/server-cert.pem +0 -17
- data/spec/ssl/server-key.pem +0 -27
- data/spec/ssl/server-req.pem +0 -15
- data/spec/test_data +0 -1
data/ext/mysql2/result.c
CHANGED
@@ -1,52 +1,21 @@
|
|
1
1
|
#include <mysql2_ext.h>
|
2
2
|
|
3
3
|
#include "mysql_enc_to_ruby.h"
|
4
|
+
#define MYSQL2_CHARSETNR_SIZE (sizeof(mysql2_mysql_enc_to_rb)/sizeof(mysql2_mysql_enc_to_rb[0]))
|
4
5
|
|
5
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
6
6
|
static rb_encoding *binaryEncoding;
|
7
|
-
#endif
|
8
7
|
|
9
|
-
#if (SIZEOF_INT < SIZEOF_LONG) || defined(HAVE_RUBY_ENCODING_H)
|
10
8
|
/* on 64bit platforms we can handle dates way outside 2038-01-19T03:14:07
|
11
9
|
*
|
12
10
|
* (9999*31557600) + (12*2592000) + (31*86400) + (11*3600) + (59*60) + 59
|
13
11
|
*/
|
14
12
|
#define MYSQL2_MAX_TIME 315578267999ULL
|
15
|
-
#else
|
16
|
-
/**
|
17
|
-
* On 32bit platforms the maximum date the Time class can handle is 2038-01-19T03:14:07
|
18
|
-
* 2038 years + 1 month + 19 days + 3 hours + 14 minutes + 7 seconds = 64318634047 seconds
|
19
|
-
*
|
20
|
-
* (2038*31557600) + (1*2592000) + (19*86400) + (3*3600) + (14*60) + 7
|
21
|
-
*/
|
22
|
-
#define MYSQL2_MAX_TIME 64318634047ULL
|
23
|
-
#endif
|
24
13
|
|
25
|
-
#if defined(HAVE_RUBY_ENCODING_H)
|
26
14
|
/* 0000-1-1 00:00:00 UTC
|
27
15
|
*
|
28
16
|
* (0*31557600) + (1*2592000) + (1*86400) + (0*3600) + (0*60) + 0
|
29
17
|
*/
|
30
18
|
#define MYSQL2_MIN_TIME 2678400ULL
|
31
|
-
#elif SIZEOF_INT < SIZEOF_LONG /* 64bit Ruby 1.8 */
|
32
|
-
/* 0139-1-1 00:00:00 UTC
|
33
|
-
*
|
34
|
-
* (139*31557600) + (1*2592000) + (1*86400) + (0*3600) + (0*60) + 0
|
35
|
-
*/
|
36
|
-
#define MYSQL2_MIN_TIME 4389184800ULL
|
37
|
-
#elif defined(NEGATIVE_TIME_T)
|
38
|
-
/* 1901-12-13 20:45:52 UTC : The oldest time in 32-bit signed time_t.
|
39
|
-
*
|
40
|
-
* (1901*31557600) + (12*2592000) + (13*86400) + (20*3600) + (45*60) + 52
|
41
|
-
*/
|
42
|
-
#define MYSQL2_MIN_TIME 60023299552ULL
|
43
|
-
#else
|
44
|
-
/* 1970-01-01 00:00:01 UTC : The Unix epoch - the oldest time in portable time_t.
|
45
|
-
*
|
46
|
-
* (1970*31557600) + (1*2592000) + (1*86400) + (0*3600) + (0*60) + 1
|
47
|
-
*/
|
48
|
-
#define MYSQL2_MIN_TIME 62171150401ULL
|
49
|
-
#endif
|
50
19
|
|
51
20
|
#define GET_RESULT(self) \
|
52
21
|
mysql2_result_wrapper *wrapper; \
|
@@ -61,17 +30,18 @@ typedef struct {
|
|
61
30
|
int streaming;
|
62
31
|
ID db_timezone;
|
63
32
|
ID app_timezone;
|
64
|
-
|
33
|
+
int block_given; /* boolean */
|
65
34
|
} result_each_args;
|
66
35
|
|
67
|
-
VALUE cBigDecimal, cDateTime, cDate;
|
68
|
-
static VALUE cMysql2Result;
|
69
|
-
static VALUE opt_decimal_zero, opt_float_zero, opt_time_year, opt_time_month, opt_utc_offset;
|
70
36
|
extern VALUE mMysql2, cMysql2Client, cMysql2Error;
|
71
|
-
static
|
72
|
-
static VALUE
|
73
|
-
|
74
|
-
|
37
|
+
static VALUE cMysql2Result, cDateTime, cDate;
|
38
|
+
static VALUE opt_decimal_zero, opt_float_zero, opt_time_year, opt_time_month, opt_utc_offset;
|
39
|
+
static ID intern_new, intern_utc, intern_local, intern_localtime, intern_local_offset,
|
40
|
+
intern_civil, intern_new_offset, intern_merge, intern_BigDecimal,
|
41
|
+
intern_query_options;
|
42
|
+
static VALUE sym_symbolize_keys, sym_as, sym_array, sym_database_timezone,
|
43
|
+
sym_application_timezone, sym_local, sym_utc, sym_cast_booleans,
|
44
|
+
sym_cache_rows, sym_cast, sym_stream, sym_name;
|
75
45
|
|
76
46
|
/* Mark any VALUEs that are only referenced in C, so the GC won't get them. */
|
77
47
|
static void rb_mysql_result_mark(void * wrapper) {
|
@@ -179,29 +149,19 @@ static VALUE rb_mysql_result_fetch_field(VALUE self, unsigned int idx, int symbo
|
|
179
149
|
rb_field = rb_ary_entry(wrapper->fields, idx);
|
180
150
|
if (rb_field == Qnil) {
|
181
151
|
MYSQL_FIELD *field = NULL;
|
182
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
183
152
|
rb_encoding *default_internal_enc = rb_default_internal_encoding();
|
184
153
|
rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding);
|
185
|
-
#endif
|
186
154
|
|
187
155
|
field = mysql_fetch_field_direct(wrapper->result, idx);
|
188
156
|
if (symbolize_keys) {
|
189
|
-
#ifdef HAVE_RB_INTERN3
|
190
157
|
rb_field = rb_intern3(field->name, field->name_length, rb_utf8_encoding());
|
191
158
|
rb_field = ID2SYM(rb_field);
|
192
|
-
#else
|
193
|
-
VALUE colStr;
|
194
|
-
colStr = rb_str_new(field->name, field->name_length);
|
195
|
-
rb_field = ID2SYM(rb_to_id(colStr));
|
196
|
-
#endif
|
197
159
|
} else {
|
198
160
|
rb_field = rb_str_new(field->name, field->name_length);
|
199
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
200
161
|
rb_enc_associate(rb_field, conn_enc);
|
201
162
|
if (default_internal_enc) {
|
202
163
|
rb_field = rb_str_export_to_enc(rb_field, default_internal_enc);
|
203
164
|
}
|
204
|
-
#endif
|
205
165
|
}
|
206
166
|
rb_ary_store(wrapper->fields, idx, rb_field);
|
207
167
|
}
|
@@ -209,7 +169,6 @@ static VALUE rb_mysql_result_fetch_field(VALUE self, unsigned int idx, int symbo
|
|
209
169
|
return rb_field;
|
210
170
|
}
|
211
171
|
|
212
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
213
172
|
static VALUE mysql2_set_field_string_encoding(VALUE val, MYSQL_FIELD field, rb_encoding *default_internal_enc, rb_encoding *conn_enc) {
|
214
173
|
/* if binary flag is set, respect its wishes */
|
215
174
|
if (field.flags & BINARY_FLAG && field.charsetnr == 63) {
|
@@ -222,7 +181,8 @@ static VALUE mysql2_set_field_string_encoding(VALUE val, MYSQL_FIELD field, rb_e
|
|
222
181
|
const char *enc_name;
|
223
182
|
int enc_index;
|
224
183
|
|
225
|
-
enc_name = mysql2_mysql_enc_to_rb[field.charsetnr-1];
|
184
|
+
enc_name = (field.charsetnr-1 < MYSQL2_CHARSETNR_SIZE) ? mysql2_mysql_enc_to_rb[field.charsetnr-1] : NULL;
|
185
|
+
|
226
186
|
if (enc_name != NULL) {
|
227
187
|
/* use the field encoding we were able to match */
|
228
188
|
enc_index = rb_enc_find_index(enc_name);
|
@@ -238,7 +198,6 @@ static VALUE mysql2_set_field_string_encoding(VALUE val, MYSQL_FIELD field, rb_e
|
|
238
198
|
}
|
239
199
|
return val;
|
240
200
|
}
|
241
|
-
#endif
|
242
201
|
|
243
202
|
/* Interpret microseconds digits left-aligned in fixed-width field.
|
244
203
|
* e.g. 10.123 seconds means 10 seconds and 123000 microseconds,
|
@@ -262,8 +221,8 @@ static void rb_mysql_result_alloc_result_buffers(VALUE self, MYSQL_FIELD *fields
|
|
262
221
|
if (wrapper->result_buffers != NULL) return;
|
263
222
|
|
264
223
|
wrapper->result_buffers = xcalloc(wrapper->numberOfFields, sizeof(MYSQL_BIND));
|
265
|
-
wrapper->is_null = xcalloc(wrapper->numberOfFields, sizeof(
|
266
|
-
wrapper->error = xcalloc(wrapper->numberOfFields, sizeof(
|
224
|
+
wrapper->is_null = xcalloc(wrapper->numberOfFields, sizeof(my_bool));
|
225
|
+
wrapper->error = xcalloc(wrapper->numberOfFields, sizeof(my_bool));
|
267
226
|
wrapper->length = xcalloc(wrapper->numberOfFields, sizeof(unsigned long));
|
268
227
|
|
269
228
|
for (i = 0; i < wrapper->numberOfFields; i++) {
|
@@ -278,12 +237,12 @@ static void rb_mysql_result_alloc_result_buffers(VALUE self, MYSQL_FIELD *fields
|
|
278
237
|
wrapper->result_buffers[i].buffer_length = sizeof(signed char);
|
279
238
|
break;
|
280
239
|
case MYSQL_TYPE_SHORT: // short int
|
240
|
+
case MYSQL_TYPE_YEAR: // short int
|
281
241
|
wrapper->result_buffers[i].buffer = xcalloc(1, sizeof(short int));
|
282
242
|
wrapper->result_buffers[i].buffer_length = sizeof(short int);
|
283
243
|
break;
|
284
244
|
case MYSQL_TYPE_INT24: // int
|
285
245
|
case MYSQL_TYPE_LONG: // int
|
286
|
-
case MYSQL_TYPE_YEAR: // int
|
287
246
|
wrapper->result_buffers[i].buffer = xcalloc(1, sizeof(int));
|
288
247
|
wrapper->result_buffers[i].buffer_length = sizeof(int);
|
289
248
|
break;
|
@@ -335,16 +294,12 @@ static VALUE rb_mysql_result_fetch_row_stmt(VALUE self, MYSQL_FIELD * fields, co
|
|
335
294
|
VALUE rowVal;
|
336
295
|
unsigned int i = 0;
|
337
296
|
|
338
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
339
297
|
rb_encoding *default_internal_enc;
|
340
298
|
rb_encoding *conn_enc;
|
341
|
-
#endif
|
342
299
|
GET_RESULT(self);
|
343
300
|
|
344
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
345
301
|
default_internal_enc = rb_default_internal_encoding();
|
346
302
|
conn_enc = rb_to_encoding(wrapper->encoding);
|
347
|
-
#endif
|
348
303
|
|
349
304
|
if (wrapper->fields == Qnil) {
|
350
305
|
wrapper->numberOfFields = mysql_num_fields(wrapper->result);
|
@@ -413,6 +368,7 @@ static VALUE rb_mysql_result_fetch_row_stmt(VALUE self, MYSQL_FIELD * fields, co
|
|
413
368
|
}
|
414
369
|
break;
|
415
370
|
case MYSQL_TYPE_SHORT: // short int
|
371
|
+
case MYSQL_TYPE_YEAR: // short int
|
416
372
|
if (result_buffer->is_unsigned) {
|
417
373
|
val = UINT2NUM(*((unsigned short int*)result_buffer->buffer));
|
418
374
|
} else {
|
@@ -421,7 +377,6 @@ static VALUE rb_mysql_result_fetch_row_stmt(VALUE self, MYSQL_FIELD * fields, co
|
|
421
377
|
break;
|
422
378
|
case MYSQL_TYPE_INT24: // int
|
423
379
|
case MYSQL_TYPE_LONG: // int
|
424
|
-
case MYSQL_TYPE_YEAR: // int
|
425
380
|
if (result_buffer->is_unsigned) {
|
426
381
|
val = UINT2NUM(*((unsigned int*)result_buffer->buffer));
|
427
382
|
} else {
|
@@ -492,7 +447,7 @@ static VALUE rb_mysql_result_fetch_row_stmt(VALUE self, MYSQL_FIELD * fields, co
|
|
492
447
|
}
|
493
448
|
case MYSQL_TYPE_DECIMAL: // char[]
|
494
449
|
case MYSQL_TYPE_NEWDECIMAL: // char[]
|
495
|
-
val = rb_funcall(
|
450
|
+
val = rb_funcall(rb_mKernel, intern_BigDecimal, 1, rb_str_new(result_buffer->buffer, *(result_buffer->length)));
|
496
451
|
break;
|
497
452
|
case MYSQL_TYPE_STRING: // char[]
|
498
453
|
case MYSQL_TYPE_VAR_STRING: // char[]
|
@@ -506,9 +461,7 @@ static VALUE rb_mysql_result_fetch_row_stmt(VALUE self, MYSQL_FIELD * fields, co
|
|
506
461
|
case MYSQL_TYPE_GEOMETRY: // char[]
|
507
462
|
default:
|
508
463
|
val = rb_str_new(result_buffer->buffer, *(result_buffer->length));
|
509
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
510
464
|
val = mysql2_set_field_string_encoding(val, fields[i], default_internal_enc, conn_enc);
|
511
|
-
#endif
|
512
465
|
break;
|
513
466
|
}
|
514
467
|
}
|
@@ -530,16 +483,12 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, MYSQL_FIELD * fields, const r
|
|
530
483
|
unsigned int i = 0;
|
531
484
|
unsigned long * fieldLengths;
|
532
485
|
void * ptr;
|
533
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
534
486
|
rb_encoding *default_internal_enc;
|
535
487
|
rb_encoding *conn_enc;
|
536
|
-
#endif
|
537
488
|
GET_RESULT(self);
|
538
489
|
|
539
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
540
490
|
default_internal_enc = rb_default_internal_encoding();
|
541
491
|
conn_enc = rb_to_encoding(wrapper->encoding);
|
542
|
-
#endif
|
543
492
|
|
544
493
|
ptr = wrapper->result;
|
545
494
|
row = (MYSQL_ROW)rb_thread_call_without_gvl(nogvl_fetch_row, ptr, RUBY_UBF_IO, 0);
|
@@ -569,9 +518,7 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, MYSQL_FIELD * fields, const r
|
|
569
518
|
val = Qnil;
|
570
519
|
} else {
|
571
520
|
val = rb_str_new(row[i], fieldLengths[i]);
|
572
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
573
521
|
val = mysql2_set_field_string_encoding(val, fields[i], default_internal_enc, conn_enc);
|
574
|
-
#endif
|
575
522
|
}
|
576
523
|
} else {
|
577
524
|
switch(type) {
|
@@ -602,9 +549,9 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, MYSQL_FIELD * fields, const r
|
|
602
549
|
if (fields[i].decimals == 0) {
|
603
550
|
val = rb_cstr2inum(row[i], 10);
|
604
551
|
} else if (strtod(row[i], NULL) == 0.000000){
|
605
|
-
val = rb_funcall(
|
552
|
+
val = rb_funcall(rb_mKernel, intern_BigDecimal, 1, opt_decimal_zero);
|
606
553
|
}else{
|
607
|
-
val = rb_funcall(
|
554
|
+
val = rb_funcall(rb_mKernel, intern_BigDecimal, 1, rb_str_new(row[i], fieldLengths[i]));
|
608
555
|
}
|
609
556
|
break;
|
610
557
|
case MYSQL_TYPE_FLOAT: /* FLOAT field */
|
@@ -722,9 +669,7 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, MYSQL_FIELD * fields, const r
|
|
722
669
|
case MYSQL_TYPE_GEOMETRY: /* Spatial fielda */
|
723
670
|
default:
|
724
671
|
val = rb_str_new(row[i], fieldLengths[i]);
|
725
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
726
672
|
val = mysql2_set_field_string_encoding(val, fields[i], default_internal_enc, conn_enc);
|
727
|
-
#endif
|
728
673
|
break;
|
729
674
|
}
|
730
675
|
}
|
@@ -751,7 +696,7 @@ static VALUE rb_mysql_result_fetch_fields(VALUE self) {
|
|
751
696
|
|
752
697
|
GET_RESULT(self);
|
753
698
|
|
754
|
-
defaults =
|
699
|
+
defaults = rb_ivar_get(self, intern_query_options);
|
755
700
|
Check_Type(defaults, T_HASH);
|
756
701
|
if (rb_hash_aref(defaults, sym_symbolize_keys) == Qtrue) {
|
757
702
|
symbolizeKeys = 1;
|
@@ -796,7 +741,7 @@ static VALUE rb_mysql_result_each_(VALUE self,
|
|
796
741
|
row = fetch_row_func(self, fields, args);
|
797
742
|
if (row != Qnil) {
|
798
743
|
wrapper->numberOfRows++;
|
799
|
-
if (args->block_given
|
744
|
+
if (args->block_given) {
|
800
745
|
rb_yield(row);
|
801
746
|
}
|
802
747
|
}
|
@@ -846,7 +791,7 @@ static VALUE rb_mysql_result_each_(VALUE self,
|
|
846
791
|
return Qnil;
|
847
792
|
}
|
848
793
|
|
849
|
-
if (args->block_given
|
794
|
+
if (args->block_given) {
|
850
795
|
rb_yield(row);
|
851
796
|
}
|
852
797
|
}
|
@@ -864,7 +809,7 @@ static VALUE rb_mysql_result_each_(VALUE self,
|
|
864
809
|
|
865
810
|
static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
|
866
811
|
result_each_args args;
|
867
|
-
VALUE defaults, opts,
|
812
|
+
VALUE defaults, opts, (*fetch_row_func)(VALUE, MYSQL_FIELD *fields, const result_each_args *args);
|
868
813
|
ID db_timezone, app_timezone, dbTz, appTz;
|
869
814
|
int symbolizeKeys, asArray, castBool, cacheRows, cast;
|
870
815
|
|
@@ -874,9 +819,12 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
|
|
874
819
|
rb_raise(cMysql2Error, "Statement handle already closed");
|
875
820
|
}
|
876
821
|
|
877
|
-
defaults =
|
822
|
+
defaults = rb_ivar_get(self, intern_query_options);
|
878
823
|
Check_Type(defaults, T_HASH);
|
879
|
-
|
824
|
+
|
825
|
+
// A block can be passed to this method, but since we don't call the block directly from C,
|
826
|
+
// we don't need to capture it into a variable here with the "&" scan arg.
|
827
|
+
if (rb_scan_args(argc, argv, "01", &opts) == 1) {
|
880
828
|
opts = rb_funcall(defaults, intern_merge, 1, opts);
|
881
829
|
} else {
|
882
830
|
opts = defaults;
|
@@ -942,7 +890,7 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
|
|
942
890
|
args.cast = cast;
|
943
891
|
args.db_timezone = db_timezone;
|
944
892
|
args.app_timezone = app_timezone;
|
945
|
-
args.block_given =
|
893
|
+
args.block_given = rb_block_given_p();
|
946
894
|
|
947
895
|
if (wrapper->stmt_wrapper) {
|
948
896
|
fetch_row_func = rb_mysql_result_fetch_row_stmt;
|
@@ -1007,7 +955,7 @@ VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_
|
|
1007
955
|
}
|
1008
956
|
|
1009
957
|
rb_obj_call_init(obj, 0, NULL);
|
1010
|
-
|
958
|
+
rb_ivar_set(obj, intern_query_options, options);
|
1011
959
|
|
1012
960
|
/* Options that cannot be changed in results.each(...) { |row| }
|
1013
961
|
* should be processed here. */
|
@@ -1017,7 +965,6 @@ VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_
|
|
1017
965
|
}
|
1018
966
|
|
1019
967
|
void init_mysql2_result() {
|
1020
|
-
cBigDecimal = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
|
1021
968
|
cDate = rb_const_get(rb_cObject, rb_intern("Date"));
|
1022
969
|
cDateTime = rb_const_get(rb_cObject, rb_intern("DateTime"));
|
1023
970
|
|
@@ -1036,6 +983,8 @@ void init_mysql2_result() {
|
|
1036
983
|
intern_local_offset = rb_intern("local_offset");
|
1037
984
|
intern_civil = rb_intern("civil");
|
1038
985
|
intern_new_offset = rb_intern("new_offset");
|
986
|
+
intern_BigDecimal = rb_intern("BigDecimal");
|
987
|
+
intern_query_options = rb_intern("@query_options");
|
1039
988
|
|
1040
989
|
sym_symbolize_keys = ID2SYM(rb_intern("symbolize_keys"));
|
1041
990
|
sym_as = ID2SYM(rb_intern("as"));
|
@@ -1058,7 +1007,5 @@ void init_mysql2_result() {
|
|
1058
1007
|
opt_time_month = INT2NUM(1);
|
1059
1008
|
opt_utc_offset = INT2NUM(0);
|
1060
1009
|
|
1061
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
1062
1010
|
binaryEncoding = rb_enc_find("binary");
|
1063
|
-
#endif
|
1064
1011
|
}
|
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,10 @@
|
|
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;
|
6
|
-
static VALUE intern_sec_fraction, intern_usec, intern_sec, intern_min, intern_hour, intern_day, intern_month, intern_year
|
7
|
-
|
8
|
-
static ID id_cmp;
|
9
|
-
#endif
|
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
|
+
static VALUE intern_sec_fraction, intern_usec, intern_sec, intern_min, intern_hour, intern_day, intern_month, intern_year,
|
7
|
+
intern_query_options;
|
10
8
|
|
11
9
|
#define GET_STATEMENT(self) \
|
12
10
|
mysql_stmt_wrapper *stmt_wrapper; \
|
@@ -21,7 +19,7 @@ static void rb_mysql_stmt_mark(void * ptr) {
|
|
21
19
|
rb_gc_mark(stmt_wrapper->client);
|
22
20
|
}
|
23
21
|
|
24
|
-
static void *nogvl_stmt_close(void *
|
22
|
+
static void *nogvl_stmt_close(void *ptr) {
|
25
23
|
mysql_stmt_wrapper *stmt_wrapper = ptr;
|
26
24
|
if (stmt_wrapper->stmt) {
|
27
25
|
mysql_stmt_close(stmt_wrapper->stmt);
|
@@ -30,7 +28,7 @@ static void *nogvl_stmt_close(void * ptr) {
|
|
30
28
|
return NULL;
|
31
29
|
}
|
32
30
|
|
33
|
-
static void rb_mysql_stmt_free(void *
|
31
|
+
static void rb_mysql_stmt_free(void *ptr) {
|
34
32
|
mysql_stmt_wrapper *stmt_wrapper = ptr;
|
35
33
|
decr_mysql2_stmt(stmt_wrapper);
|
36
34
|
}
|
@@ -50,7 +48,6 @@ void rb_raise_mysql2_stmt_error(mysql_stmt_wrapper *stmt_wrapper) {
|
|
50
48
|
VALUE rb_error_msg = rb_str_new2(mysql_stmt_error(stmt_wrapper->stmt));
|
51
49
|
VALUE rb_sql_state = rb_tainted_str_new2(mysql_stmt_sqlstate(stmt_wrapper->stmt));
|
52
50
|
|
53
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
54
51
|
rb_encoding *conn_enc;
|
55
52
|
conn_enc = rb_to_encoding(wrapper->encoding);
|
56
53
|
|
@@ -62,7 +59,6 @@ void rb_raise_mysql2_stmt_error(mysql_stmt_wrapper *stmt_wrapper) {
|
|
62
59
|
rb_error_msg = rb_str_export_to_enc(rb_error_msg, default_internal_enc);
|
63
60
|
rb_sql_state = rb_str_export_to_enc(rb_sql_state, default_internal_enc);
|
64
61
|
}
|
65
|
-
#endif
|
66
62
|
|
67
63
|
e = rb_funcall(cMysql2Error, intern_new_with_args, 4,
|
68
64
|
rb_error_msg,
|
@@ -96,9 +92,7 @@ static void *nogvl_prepare_statement(void *ptr) {
|
|
96
92
|
VALUE rb_mysql_stmt_new(VALUE rb_client, VALUE sql) {
|
97
93
|
mysql_stmt_wrapper *stmt_wrapper;
|
98
94
|
VALUE rb_stmt;
|
99
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
100
95
|
rb_encoding *conn_enc;
|
101
|
-
#endif
|
102
96
|
|
103
97
|
Check_Type(sql, T_STRING);
|
104
98
|
|
@@ -114,9 +108,7 @@ VALUE rb_mysql_stmt_new(VALUE rb_client, VALUE sql) {
|
|
114
108
|
{
|
115
109
|
GET_CLIENT(rb_client);
|
116
110
|
stmt_wrapper->stmt = mysql_stmt_init(wrapper->client);
|
117
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
118
111
|
conn_enc = rb_to_encoding(wrapper->encoding);
|
119
|
-
#endif
|
120
112
|
}
|
121
113
|
if (stmt_wrapper->stmt == NULL) {
|
122
114
|
rb_raise(cMysql2Error, "Unable to initialize prepared statement: out of memory");
|
@@ -124,7 +116,7 @@ VALUE rb_mysql_stmt_new(VALUE rb_client, VALUE sql) {
|
|
124
116
|
|
125
117
|
// set STMT_ATTR_UPDATE_MAX_LENGTH attr
|
126
118
|
{
|
127
|
-
|
119
|
+
my_bool truth = 1;
|
128
120
|
if (mysql_stmt_attr_set(stmt_wrapper->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &truth)) {
|
129
121
|
rb_raise(cMysql2Error, "Unable to initialize prepared statement: set STMT_ATTR_UPDATE_MAX_LENGTH");
|
130
122
|
}
|
@@ -134,11 +126,8 @@ VALUE rb_mysql_stmt_new(VALUE rb_client, VALUE sql) {
|
|
134
126
|
{
|
135
127
|
struct nogvl_prepare_statement_args args;
|
136
128
|
args.stmt = stmt_wrapper->stmt;
|
137
|
-
args.sql = sql;
|
138
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
139
129
|
// ensure the string is in the encoding the connection is expecting
|
140
|
-
args.sql = rb_str_export_to_enc(
|
141
|
-
#endif
|
130
|
+
args.sql = rb_str_export_to_enc(sql, conn_enc);
|
142
131
|
args.sql_ptr = RSTRING_PTR(sql);
|
143
132
|
args.sql_len = RSTRING_LEN(sql);
|
144
133
|
|
@@ -154,7 +143,7 @@ VALUE rb_mysql_stmt_new(VALUE rb_client, VALUE sql) {
|
|
154
143
|
*
|
155
144
|
* Returns the number of parameters the prepared statement expects.
|
156
145
|
*/
|
157
|
-
static VALUE
|
146
|
+
static VALUE rb_mysql_stmt_param_count(VALUE self) {
|
158
147
|
GET_STATEMENT(self);
|
159
148
|
|
160
149
|
return ULL2NUM(mysql_stmt_param_count(stmt_wrapper->stmt));
|
@@ -164,13 +153,13 @@ static VALUE param_count(VALUE self) {
|
|
164
153
|
*
|
165
154
|
* Returns the number of fields the prepared statement returns.
|
166
155
|
*/
|
167
|
-
static VALUE
|
156
|
+
static VALUE rb_mysql_stmt_field_count(VALUE self) {
|
168
157
|
GET_STATEMENT(self);
|
169
158
|
|
170
159
|
return UINT2NUM(mysql_stmt_field_count(stmt_wrapper->stmt));
|
171
160
|
}
|
172
161
|
|
173
|
-
static void *
|
162
|
+
static void *nogvl_stmt_execute(void *ptr) {
|
174
163
|
MYSQL_STMT *stmt = ptr;
|
175
164
|
|
176
165
|
if (mysql_stmt_execute(stmt)) {
|
@@ -196,7 +185,7 @@ static void set_buffer_for_string(MYSQL_BIND* bind_buffer, unsigned long *length
|
|
196
185
|
* the buffer is a Ruby string pointer and not our memory to manage.
|
197
186
|
*/
|
198
187
|
#define FREE_BINDS \
|
199
|
-
for (i = 0; i <
|
188
|
+
for (i = 0; i < bind_count; i++) { \
|
200
189
|
if (bind_buffers[i].buffer && NIL_P(params_enc[i])) { \
|
201
190
|
xfree(bind_buffers[i].buffer); \
|
202
191
|
} \
|
@@ -211,6 +200,8 @@ static int my_big2ll(VALUE bignum, LONG_LONG *ptr)
|
|
211
200
|
{
|
212
201
|
unsigned LONG_LONG num;
|
213
202
|
size_t len;
|
203
|
+
// rb_absint_size was added in 2.1.0. See:
|
204
|
+
// https://github.com/ruby/ruby/commit/9fea875
|
214
205
|
#ifdef HAVE_RB_ABSINT_SIZE
|
215
206
|
int nlz_bits = 0;
|
216
207
|
len = rb_absint_size(bignum, &nlz_bits);
|
@@ -229,16 +220,15 @@ static int my_big2ll(VALUE bignum, LONG_LONG *ptr)
|
|
229
220
|
#ifdef HAVE_RB_ABSINT_SIZE
|
230
221
|
nlz_bits == 0 &&
|
231
222
|
#endif
|
223
|
+
// rb_absint_singlebit_p was added in 2.1.0. See:
|
224
|
+
// https://github.com/ruby/ruby/commit/e5ff9d5
|
232
225
|
#if defined(HAVE_RB_ABSINT_SIZE) && defined(HAVE_RB_ABSINT_SINGLEBIT_P)
|
233
226
|
/* Optimized to avoid object allocation for Ruby 2.1+
|
234
227
|
* only -0x8000000000000000 is safe if `len == 8 && nlz_bits == 0`
|
235
228
|
*/
|
236
229
|
!rb_absint_singlebit_p(bignum)
|
237
|
-
#elif defined(HAVE_RB_BIG_CMP)
|
238
|
-
rb_big_cmp(bignum, LL2NUM(LLONG_MIN)) == INT2FIX(-1)
|
239
230
|
#else
|
240
|
-
|
241
|
-
rb_funcall(bignum, id_cmp, 1, LL2NUM(LLONG_MIN)) == INT2FIX(-1)
|
231
|
+
rb_big_cmp(bignum, LL2NUM(LLONG_MIN)) == INT2FIX(-1)
|
242
232
|
#endif
|
243
233
|
) {
|
244
234
|
goto overflow;
|
@@ -254,44 +244,45 @@ overflow:
|
|
254
244
|
*
|
255
245
|
* Executes the current prepared statement, returns +result+.
|
256
246
|
*/
|
257
|
-
static VALUE
|
247
|
+
static VALUE rb_mysql_stmt_execute(int argc, VALUE *argv, VALUE self) {
|
258
248
|
MYSQL_BIND *bind_buffers = NULL;
|
259
249
|
unsigned long *length_buffers = NULL;
|
260
250
|
unsigned long bind_count;
|
261
|
-
long i;
|
251
|
+
unsigned long i;
|
262
252
|
MYSQL_STMT *stmt;
|
263
253
|
MYSQL_RES *metadata;
|
254
|
+
VALUE opts;
|
264
255
|
VALUE current;
|
265
256
|
VALUE resultObj;
|
266
|
-
VALUE *params_enc;
|
257
|
+
VALUE *params_enc = NULL;
|
267
258
|
int is_streaming;
|
268
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
269
259
|
rb_encoding *conn_enc;
|
270
|
-
#endif
|
271
260
|
|
272
261
|
GET_STATEMENT(self);
|
273
262
|
GET_CLIENT(stmt_wrapper->client);
|
274
263
|
|
275
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
276
264
|
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
265
|
|
282
266
|
stmt = stmt_wrapper->stmt;
|
283
|
-
|
284
267
|
bind_count = mysql_stmt_param_count(stmt);
|
285
|
-
|
286
|
-
|
268
|
+
|
269
|
+
// Get count of ordinary arguments, and extract hash opts/keyword arguments
|
270
|
+
// Use a local scope to avoid leaking the temporary count variable
|
271
|
+
{
|
272
|
+
int c = rb_scan_args(argc, argv, "*:", NULL, &opts);
|
273
|
+
if (c != (long)bind_count) {
|
274
|
+
rb_raise(cMysql2Error, "Bind parameter count (%ld) doesn't match number of arguments (%d)", bind_count, c);
|
275
|
+
}
|
287
276
|
}
|
288
277
|
|
289
278
|
// setup any bind variables in the query
|
290
279
|
if (bind_count > 0) {
|
280
|
+
// Scratch space for string encoding exports, allocate on the stack
|
281
|
+
params_enc = alloca(sizeof(VALUE) * bind_count);
|
291
282
|
bind_buffers = xcalloc(bind_count, sizeof(MYSQL_BIND));
|
292
283
|
length_buffers = xcalloc(bind_count, sizeof(unsigned long));
|
293
284
|
|
294
|
-
for (i = 0; i <
|
285
|
+
for (i = 0; i < bind_count; i++) {
|
295
286
|
bind_buffers[i].buffer = NULL;
|
296
287
|
params_enc[i] = Qnil;
|
297
288
|
|
@@ -319,12 +310,8 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) {
|
|
319
310
|
*(LONG_LONG*)(bind_buffers[i].buffer) = num;
|
320
311
|
} else {
|
321
312
|
/* 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
313
|
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
|
314
|
+
params_enc[i] = rb_str_export_to_enc(rb_big2str(argv[i], 10), conn_enc);
|
328
315
|
set_buffer_for_string(&bind_buffers[i], &length_buffers[i], params_enc[i]);
|
329
316
|
}
|
330
317
|
}
|
@@ -338,9 +325,7 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) {
|
|
338
325
|
bind_buffers[i].buffer_type = MYSQL_TYPE_STRING;
|
339
326
|
|
340
327
|
params_enc[i] = argv[i];
|
341
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
342
328
|
params_enc[i] = rb_str_export_to_enc(params_enc[i], conn_enc);
|
343
|
-
#endif
|
344
329
|
set_buffer_for_string(&bind_buffers[i], &length_buffers[i], params_enc[i]);
|
345
330
|
break;
|
346
331
|
case T_TRUE:
|
@@ -405,9 +390,7 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) {
|
|
405
390
|
VALUE rb_val_as_string = rb_funcall(argv[i], intern_to_s, 0);
|
406
391
|
|
407
392
|
params_enc[i] = rb_val_as_string;
|
408
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
409
393
|
params_enc[i] = rb_str_export_to_enc(params_enc[i], conn_enc);
|
410
|
-
#endif
|
411
394
|
set_buffer_for_string(&bind_buffers[i], &length_buffers[i], params_enc[i]);
|
412
395
|
}
|
413
396
|
break;
|
@@ -421,7 +404,40 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) {
|
|
421
404
|
}
|
422
405
|
}
|
423
406
|
|
424
|
-
|
407
|
+
// Duplicate the options hash, merge! extra opts, put the copy into the Result object
|
408
|
+
current = rb_hash_dup(rb_ivar_get(stmt_wrapper->client, intern_query_options));
|
409
|
+
(void)RB_GC_GUARD(current);
|
410
|
+
Check_Type(current, T_HASH);
|
411
|
+
|
412
|
+
// Merge in hash opts/keyword arguments
|
413
|
+
if (!NIL_P(opts)) {
|
414
|
+
rb_funcall(current, intern_merge_bang, 1, opts);
|
415
|
+
}
|
416
|
+
|
417
|
+
is_streaming = (Qtrue == rb_hash_aref(current, sym_stream));
|
418
|
+
|
419
|
+
// From stmt_execute to mysql_stmt_result_metadata to stmt_store_result, no
|
420
|
+
// Ruby API calls are allowed so that GC is not invoked. If the connection is
|
421
|
+
// in results-streaming-mode for Statement A, and in the middle Statement B
|
422
|
+
// gets garbage collected, a message will be sent to the server notifying it
|
423
|
+
// to release Statement B, resulting in the following error:
|
424
|
+
// Commands out of sync; you can't run this command now
|
425
|
+
//
|
426
|
+
// In streaming mode, statement execute must return a cursor because we
|
427
|
+
// cannot prevent other Statement objects from being garbage collected
|
428
|
+
// between fetches of each row of the result set. The following error
|
429
|
+
// occurs if cursor mode is not set:
|
430
|
+
// Row retrieval was canceled by mysql_stmt_close
|
431
|
+
|
432
|
+
if (is_streaming) {
|
433
|
+
unsigned long type = CURSOR_TYPE_READ_ONLY;
|
434
|
+
if (mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, &type)) {
|
435
|
+
FREE_BINDS;
|
436
|
+
rb_raise(cMysql2Error, "Unable to stream prepared statement, could not set CURSOR_TYPE_READ_ONLY");
|
437
|
+
}
|
438
|
+
}
|
439
|
+
|
440
|
+
if ((VALUE)rb_thread_call_without_gvl(nogvl_stmt_execute, stmt, RUBY_UBF_IO, 0) == Qfalse) {
|
425
441
|
FREE_BINDS;
|
426
442
|
rb_raise_mysql2_stmt_error(stmt_wrapper);
|
427
443
|
}
|
@@ -439,11 +455,6 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) {
|
|
439
455
|
return Qnil;
|
440
456
|
}
|
441
457
|
|
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
458
|
if (!is_streaming) {
|
448
459
|
// recieve the whole result set from the server
|
449
460
|
if (mysql_stmt_store_result(stmt)) {
|
@@ -455,6 +466,8 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) {
|
|
455
466
|
|
456
467
|
resultObj = rb_mysql_result_to_obj(stmt_wrapper->client, wrapper->encoding, current, metadata, self);
|
457
468
|
|
469
|
+
rb_mysql_set_server_query_flags(wrapper->client, resultObj);
|
470
|
+
|
458
471
|
if (!is_streaming) {
|
459
472
|
// cache all result
|
460
473
|
rb_funcall(resultObj, intern_each, 0);
|
@@ -467,27 +480,23 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) {
|
|
467
480
|
*
|
468
481
|
* Returns a list of fields that will be returned by this statement.
|
469
482
|
*/
|
470
|
-
static VALUE
|
483
|
+
static VALUE rb_mysql_stmt_fields(VALUE self) {
|
471
484
|
MYSQL_FIELD *fields;
|
472
485
|
MYSQL_RES *metadata;
|
473
486
|
unsigned int field_count;
|
474
487
|
unsigned int i;
|
475
488
|
VALUE field_list;
|
476
489
|
MYSQL_STMT* stmt;
|
477
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
478
490
|
rb_encoding *default_internal_enc, *conn_enc;
|
479
|
-
#endif
|
480
491
|
GET_STATEMENT(self);
|
481
492
|
GET_CLIENT(stmt_wrapper->client);
|
482
493
|
stmt = stmt_wrapper->stmt;
|
483
494
|
|
484
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
485
495
|
default_internal_enc = rb_default_internal_encoding();
|
486
496
|
{
|
487
497
|
GET_CLIENT(stmt_wrapper->client);
|
488
498
|
conn_enc = rb_to_encoding(wrapper->encoding);
|
489
499
|
}
|
490
|
-
#endif
|
491
500
|
|
492
501
|
metadata = mysql_stmt_result_metadata(stmt);
|
493
502
|
if (metadata == NULL) {
|
@@ -508,12 +517,10 @@ static VALUE fields(VALUE self) {
|
|
508
517
|
VALUE rb_field;
|
509
518
|
|
510
519
|
rb_field = rb_str_new(fields[i].name, fields[i].name_length);
|
511
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
512
520
|
rb_enc_associate(rb_field, conn_enc);
|
513
521
|
if (default_internal_enc) {
|
514
522
|
rb_field = rb_str_export_to_enc(rb_field, default_internal_enc);
|
515
523
|
}
|
516
|
-
#endif
|
517
524
|
|
518
525
|
rb_ary_store(field_list, (long)i, rb_field);
|
519
526
|
}
|
@@ -564,12 +571,15 @@ static VALUE rb_mysql_stmt_close(VALUE self) {
|
|
564
571
|
}
|
565
572
|
|
566
573
|
void init_mysql2_statement() {
|
567
|
-
|
574
|
+
cDate = rb_const_get(rb_cObject, rb_intern("Date"));
|
575
|
+
cDateTime = rb_const_get(rb_cObject, rb_intern("DateTime"));
|
576
|
+
cBigDecimal = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
|
568
577
|
|
569
|
-
|
570
|
-
rb_define_method(cMysql2Statement, "
|
571
|
-
rb_define_method(cMysql2Statement, "
|
572
|
-
rb_define_method(cMysql2Statement, "
|
578
|
+
cMysql2Statement = rb_define_class_under(mMysql2, "Statement", rb_cObject);
|
579
|
+
rb_define_method(cMysql2Statement, "param_count", rb_mysql_stmt_param_count, 0);
|
580
|
+
rb_define_method(cMysql2Statement, "field_count", rb_mysql_stmt_field_count, 0);
|
581
|
+
rb_define_method(cMysql2Statement, "_execute", rb_mysql_stmt_execute, -1);
|
582
|
+
rb_define_method(cMysql2Statement, "fields", rb_mysql_stmt_fields, 0);
|
573
583
|
rb_define_method(cMysql2Statement, "last_id", rb_mysql_stmt_last_id, 0);
|
574
584
|
rb_define_method(cMysql2Statement, "affected_rows", rb_mysql_stmt_affected_rows, 0);
|
575
585
|
rb_define_method(cMysql2Statement, "close", rb_mysql_stmt_close, 0);
|
@@ -589,7 +599,6 @@ void init_mysql2_statement() {
|
|
589
599
|
intern_year = rb_intern("year");
|
590
600
|
|
591
601
|
intern_to_s = rb_intern("to_s");
|
592
|
-
|
593
|
-
|
594
|
-
#endif
|
602
|
+
intern_merge_bang = rb_intern("merge!");
|
603
|
+
intern_query_options = rb_intern("@query_options");
|
595
604
|
}
|