mysql2 0.4.10 → 0.5.4
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 +98 -38
- data/ext/mysql2/client.c +223 -76
- data/ext/mysql2/client.h +1 -39
- data/ext/mysql2/extconf.rb +46 -26
- data/ext/mysql2/mysql2_ext.c +8 -2
- 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 +242 -86
- data/ext/mysql2/result.h +3 -3
- data/ext/mysql2/statement.c +90 -73
- data/ext/mysql2/statement.h +0 -2
- data/ext/mysql2/wait_for_single_fd.h +2 -1
- data/lib/mysql2/client.rb +51 -28
- data/lib/mysql2/em.rb +2 -4
- data/lib/mysql2/error.rb +52 -22
- data/lib/mysql2/result.rb +2 -0
- data/lib/mysql2/statement.rb +3 -11
- data/lib/mysql2/version.rb +1 -1
- data/lib/mysql2.rb +18 -15
- data/support/3A79BD29.asc +49 -0
- 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 +14 -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,51 +1,34 @@
|
|
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
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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
|
19
|
+
|
20
|
+
#define MYSQL2_MAX_BYTES_PER_CHAR 3
|
21
|
+
|
22
|
+
/* From Mysql documentations:
|
23
|
+
* To distinguish between binary and nonbinary data for string data types,
|
24
|
+
* check whether the charsetnr value is 63. If so, the character set is binary,
|
25
|
+
* which indicates binary rather than nonbinary data. This enables you to distinguish BINARY
|
26
|
+
* from CHAR, VARBINARY from VARCHAR, and the BLOB types from the TEXT types.
|
47
27
|
*/
|
48
|
-
#define
|
28
|
+
#define MYSQL2_BINARY_CHARSET 63
|
29
|
+
|
30
|
+
#ifndef MYSQL_TYPE_JSON
|
31
|
+
#define MYSQL_TYPE_JSON 245
|
49
32
|
#endif
|
50
33
|
|
51
34
|
#define GET_RESULT(self) \
|
@@ -61,17 +44,18 @@ typedef struct {
|
|
61
44
|
int streaming;
|
62
45
|
ID db_timezone;
|
63
46
|
ID app_timezone;
|
64
|
-
|
47
|
+
int block_given; /* boolean */
|
65
48
|
} result_each_args;
|
66
49
|
|
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
50
|
extern VALUE mMysql2, cMysql2Client, cMysql2Error;
|
71
|
-
static
|
72
|
-
static VALUE
|
73
|
-
|
74
|
-
|
51
|
+
static VALUE cMysql2Result, cDateTime, cDate;
|
52
|
+
static VALUE opt_decimal_zero, opt_float_zero, opt_time_year, opt_time_month, opt_utc_offset;
|
53
|
+
static ID intern_new, intern_utc, intern_local, intern_localtime, intern_local_offset,
|
54
|
+
intern_civil, intern_new_offset, intern_merge, intern_BigDecimal,
|
55
|
+
intern_query_options;
|
56
|
+
static VALUE sym_symbolize_keys, sym_as, sym_array, sym_database_timezone,
|
57
|
+
sym_application_timezone, sym_local, sym_utc, sym_cast_booleans,
|
58
|
+
sym_cache_rows, sym_cast, sym_stream, sym_name;
|
75
59
|
|
76
60
|
/* Mark any VALUEs that are only referenced in C, so the GC won't get them. */
|
77
61
|
static void rb_mysql_result_mark(void * wrapper) {
|
@@ -179,28 +163,25 @@ static VALUE rb_mysql_result_fetch_field(VALUE self, unsigned int idx, int symbo
|
|
179
163
|
rb_field = rb_ary_entry(wrapper->fields, idx);
|
180
164
|
if (rb_field == Qnil) {
|
181
165
|
MYSQL_FIELD *field = NULL;
|
182
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
183
166
|
rb_encoding *default_internal_enc = rb_default_internal_encoding();
|
184
167
|
rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding);
|
185
|
-
#endif
|
186
168
|
|
187
169
|
field = mysql_fetch_field_direct(wrapper->result, idx);
|
188
170
|
if (symbolize_keys) {
|
189
|
-
#ifdef HAVE_RB_INTERN3
|
190
171
|
rb_field = rb_intern3(field->name, field->name_length, rb_utf8_encoding());
|
191
172
|
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
173
|
} else {
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
174
|
+
#ifdef HAVE_RB_ENC_INTERNED_STR
|
175
|
+
rb_field = rb_enc_interned_str(field->name, field->name_length, conn_enc);
|
176
|
+
if (default_internal_enc && default_internal_enc != conn_enc) {
|
177
|
+
rb_field = rb_str_to_interned_str(rb_str_export_to_enc(rb_field, default_internal_enc));
|
178
|
+
}
|
179
|
+
#else
|
180
|
+
rb_field = rb_enc_str_new(field->name, field->name_length, conn_enc);
|
181
|
+
if (default_internal_enc && default_internal_enc != conn_enc) {
|
202
182
|
rb_field = rb_str_export_to_enc(rb_field, default_internal_enc);
|
203
183
|
}
|
184
|
+
rb_obj_freeze(rb_field);
|
204
185
|
#endif
|
205
186
|
}
|
206
187
|
rb_ary_store(wrapper->fields, idx, rb_field);
|
@@ -209,10 +190,171 @@ static VALUE rb_mysql_result_fetch_field(VALUE self, unsigned int idx, int symbo
|
|
209
190
|
return rb_field;
|
210
191
|
}
|
211
192
|
|
212
|
-
|
193
|
+
static VALUE rb_mysql_result_fetch_field_type(VALUE self, unsigned int idx) {
|
194
|
+
VALUE rb_field_type;
|
195
|
+
GET_RESULT(self);
|
196
|
+
|
197
|
+
if (wrapper->fieldTypes == Qnil) {
|
198
|
+
wrapper->numberOfFields = mysql_num_fields(wrapper->result);
|
199
|
+
wrapper->fieldTypes = rb_ary_new2(wrapper->numberOfFields);
|
200
|
+
}
|
201
|
+
|
202
|
+
rb_field_type = rb_ary_entry(wrapper->fieldTypes, idx);
|
203
|
+
if (rb_field_type == Qnil) {
|
204
|
+
MYSQL_FIELD *field = NULL;
|
205
|
+
rb_encoding *default_internal_enc = rb_default_internal_encoding();
|
206
|
+
rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding);
|
207
|
+
int precision;
|
208
|
+
|
209
|
+
field = mysql_fetch_field_direct(wrapper->result, idx);
|
210
|
+
|
211
|
+
switch(field->type) {
|
212
|
+
case MYSQL_TYPE_NULL: // NULL
|
213
|
+
rb_field_type = rb_str_new_cstr("null");
|
214
|
+
break;
|
215
|
+
case MYSQL_TYPE_TINY: // signed char
|
216
|
+
rb_field_type = rb_sprintf("tinyint(%ld)", field->length);
|
217
|
+
break;
|
218
|
+
case MYSQL_TYPE_SHORT: // short int
|
219
|
+
rb_field_type = rb_sprintf("smallint(%ld)", field->length);
|
220
|
+
break;
|
221
|
+
case MYSQL_TYPE_YEAR: // short int
|
222
|
+
rb_field_type = rb_sprintf("year(%ld)", field->length);
|
223
|
+
break;
|
224
|
+
case MYSQL_TYPE_INT24: // int
|
225
|
+
rb_field_type = rb_sprintf("mediumint(%ld)", field->length);
|
226
|
+
break;
|
227
|
+
case MYSQL_TYPE_LONG: // int
|
228
|
+
rb_field_type = rb_sprintf("int(%ld)", field->length);
|
229
|
+
break;
|
230
|
+
case MYSQL_TYPE_LONGLONG: // long long int
|
231
|
+
rb_field_type = rb_sprintf("bigint(%ld)", field->length);
|
232
|
+
break;
|
233
|
+
case MYSQL_TYPE_FLOAT: // float
|
234
|
+
rb_field_type = rb_sprintf("float(%ld,%d)", field->length, field->decimals);
|
235
|
+
break;
|
236
|
+
case MYSQL_TYPE_DOUBLE: // double
|
237
|
+
rb_field_type = rb_sprintf("double(%ld,%d)", field->length, field->decimals);
|
238
|
+
break;
|
239
|
+
case MYSQL_TYPE_TIME: // MYSQL_TIME
|
240
|
+
rb_field_type = rb_str_new_cstr("time");
|
241
|
+
break;
|
242
|
+
case MYSQL_TYPE_DATE: // MYSQL_TIME
|
243
|
+
case MYSQL_TYPE_NEWDATE: // MYSQL_TIME
|
244
|
+
rb_field_type = rb_str_new_cstr("date");
|
245
|
+
break;
|
246
|
+
case MYSQL_TYPE_DATETIME: // MYSQL_TIME
|
247
|
+
rb_field_type = rb_str_new_cstr("datetime");
|
248
|
+
break;
|
249
|
+
case MYSQL_TYPE_TIMESTAMP: // MYSQL_TIME
|
250
|
+
rb_field_type = rb_str_new_cstr("timestamp");
|
251
|
+
break;
|
252
|
+
case MYSQL_TYPE_DECIMAL: // char[]
|
253
|
+
case MYSQL_TYPE_NEWDECIMAL: // char[]
|
254
|
+
/*
|
255
|
+
Handle precision similar to this line from mysql's code:
|
256
|
+
https://github.com/mysql/mysql-server/blob/ea7d2e2d16ac03afdd9cb72a972a95981107bf51/sql/field.cc#L2246
|
257
|
+
*/
|
258
|
+
precision = field->length - (field->decimals > 0 ? 2 : 1);
|
259
|
+
rb_field_type = rb_sprintf("decimal(%d,%d)", precision, field->decimals);
|
260
|
+
break;
|
261
|
+
case MYSQL_TYPE_STRING: // char[]
|
262
|
+
if (field->flags & ENUM_FLAG) {
|
263
|
+
rb_field_type = rb_str_new_cstr("enum");
|
264
|
+
} else if (field->flags & SET_FLAG) {
|
265
|
+
rb_field_type = rb_str_new_cstr("set");
|
266
|
+
} else {
|
267
|
+
if (field->charsetnr == MYSQL2_BINARY_CHARSET) {
|
268
|
+
rb_field_type = rb_sprintf("binary(%ld)", field->length);
|
269
|
+
} else {
|
270
|
+
rb_field_type = rb_sprintf("char(%ld)", field->length / MYSQL2_MAX_BYTES_PER_CHAR);
|
271
|
+
}
|
272
|
+
}
|
273
|
+
break;
|
274
|
+
case MYSQL_TYPE_VAR_STRING: // char[]
|
275
|
+
if (field->charsetnr == MYSQL2_BINARY_CHARSET) {
|
276
|
+
rb_field_type = rb_sprintf("varbinary(%ld)", field->length);
|
277
|
+
} else {
|
278
|
+
rb_field_type = rb_sprintf("varchar(%ld)", field->length / MYSQL2_MAX_BYTES_PER_CHAR);
|
279
|
+
}
|
280
|
+
break;
|
281
|
+
case MYSQL_TYPE_VARCHAR: // char[]
|
282
|
+
rb_field_type = rb_sprintf("varchar(%ld)", field->length / MYSQL2_MAX_BYTES_PER_CHAR);
|
283
|
+
break;
|
284
|
+
case MYSQL_TYPE_TINY_BLOB: // char[]
|
285
|
+
rb_field_type = rb_str_new_cstr("tinyblob");
|
286
|
+
break;
|
287
|
+
case MYSQL_TYPE_BLOB: // char[]
|
288
|
+
if (field->charsetnr == MYSQL2_BINARY_CHARSET) {
|
289
|
+
switch(field->length) {
|
290
|
+
case 255:
|
291
|
+
rb_field_type = rb_str_new_cstr("tinyblob");
|
292
|
+
break;
|
293
|
+
case 65535:
|
294
|
+
rb_field_type = rb_str_new_cstr("blob");
|
295
|
+
break;
|
296
|
+
case 16777215:
|
297
|
+
rb_field_type = rb_str_new_cstr("mediumblob");
|
298
|
+
break;
|
299
|
+
case 4294967295:
|
300
|
+
rb_field_type = rb_str_new_cstr("longblob");
|
301
|
+
default:
|
302
|
+
break;
|
303
|
+
}
|
304
|
+
} else {
|
305
|
+
if (field->length == (255 * MYSQL2_MAX_BYTES_PER_CHAR)) {
|
306
|
+
rb_field_type = rb_str_new_cstr("tinytext");
|
307
|
+
} else if (field->length == (65535 * MYSQL2_MAX_BYTES_PER_CHAR)) {
|
308
|
+
rb_field_type = rb_str_new_cstr("text");
|
309
|
+
} else if (field->length == (16777215 * MYSQL2_MAX_BYTES_PER_CHAR)) {
|
310
|
+
rb_field_type = rb_str_new_cstr("mediumtext");
|
311
|
+
} else if (field->length == 4294967295) {
|
312
|
+
rb_field_type = rb_str_new_cstr("longtext");
|
313
|
+
} else {
|
314
|
+
rb_field_type = rb_sprintf("text(%ld)", field->length);
|
315
|
+
}
|
316
|
+
}
|
317
|
+
break;
|
318
|
+
case MYSQL_TYPE_MEDIUM_BLOB: // char[]
|
319
|
+
rb_field_type = rb_str_new_cstr("mediumblob");
|
320
|
+
break;
|
321
|
+
case MYSQL_TYPE_LONG_BLOB: // char[]
|
322
|
+
rb_field_type = rb_str_new_cstr("longblob");
|
323
|
+
break;
|
324
|
+
case MYSQL_TYPE_BIT: // char[]
|
325
|
+
rb_field_type = rb_sprintf("bit(%ld)", field->length);
|
326
|
+
break;
|
327
|
+
case MYSQL_TYPE_SET: // char[]
|
328
|
+
rb_field_type = rb_str_new_cstr("set");
|
329
|
+
break;
|
330
|
+
case MYSQL_TYPE_ENUM: // char[]
|
331
|
+
rb_field_type = rb_str_new_cstr("enum");
|
332
|
+
break;
|
333
|
+
case MYSQL_TYPE_GEOMETRY: // char[]
|
334
|
+
rb_field_type = rb_str_new_cstr("geometry");
|
335
|
+
break;
|
336
|
+
case MYSQL_TYPE_JSON: // json
|
337
|
+
rb_field_type = rb_str_new_cstr("json");
|
338
|
+
break;
|
339
|
+
default:
|
340
|
+
rb_field_type = rb_str_new_cstr("unknown");
|
341
|
+
break;
|
342
|
+
}
|
343
|
+
|
344
|
+
rb_enc_associate(rb_field_type, conn_enc);
|
345
|
+
if (default_internal_enc) {
|
346
|
+
rb_field_type = rb_str_export_to_enc(rb_field_type, default_internal_enc);
|
347
|
+
}
|
348
|
+
|
349
|
+
rb_ary_store(wrapper->fieldTypes, idx, rb_field_type);
|
350
|
+
}
|
351
|
+
|
352
|
+
return rb_field_type;
|
353
|
+
}
|
354
|
+
|
213
355
|
static VALUE mysql2_set_field_string_encoding(VALUE val, MYSQL_FIELD field, rb_encoding *default_internal_enc, rb_encoding *conn_enc) {
|
214
356
|
/* if binary flag is set, respect its wishes */
|
215
|
-
if (field.flags & BINARY_FLAG && field.charsetnr ==
|
357
|
+
if (field.flags & BINARY_FLAG && field.charsetnr == MYSQL2_BINARY_CHARSET) {
|
216
358
|
rb_enc_associate(val, binaryEncoding);
|
217
359
|
} else if (!field.charsetnr) {
|
218
360
|
/* MySQL 4.x may not provide an encoding, binary will get the bytes through */
|
@@ -222,7 +364,8 @@ static VALUE mysql2_set_field_string_encoding(VALUE val, MYSQL_FIELD field, rb_e
|
|
222
364
|
const char *enc_name;
|
223
365
|
int enc_index;
|
224
366
|
|
225
|
-
enc_name = mysql2_mysql_enc_to_rb[field.charsetnr-1];
|
367
|
+
enc_name = (field.charsetnr-1 < MYSQL2_CHARSETNR_SIZE) ? mysql2_mysql_enc_to_rb[field.charsetnr-1] : NULL;
|
368
|
+
|
226
369
|
if (enc_name != NULL) {
|
227
370
|
/* use the field encoding we were able to match */
|
228
371
|
enc_index = rb_enc_find_index(enc_name);
|
@@ -238,7 +381,6 @@ static VALUE mysql2_set_field_string_encoding(VALUE val, MYSQL_FIELD field, rb_e
|
|
238
381
|
}
|
239
382
|
return val;
|
240
383
|
}
|
241
|
-
#endif
|
242
384
|
|
243
385
|
/* Interpret microseconds digits left-aligned in fixed-width field.
|
244
386
|
* e.g. 10.123 seconds means 10 seconds and 123000 microseconds,
|
@@ -262,8 +404,8 @@ static void rb_mysql_result_alloc_result_buffers(VALUE self, MYSQL_FIELD *fields
|
|
262
404
|
if (wrapper->result_buffers != NULL) return;
|
263
405
|
|
264
406
|
wrapper->result_buffers = xcalloc(wrapper->numberOfFields, sizeof(MYSQL_BIND));
|
265
|
-
wrapper->is_null = xcalloc(wrapper->numberOfFields, sizeof(
|
266
|
-
wrapper->error = xcalloc(wrapper->numberOfFields, sizeof(
|
407
|
+
wrapper->is_null = xcalloc(wrapper->numberOfFields, sizeof(my_bool));
|
408
|
+
wrapper->error = xcalloc(wrapper->numberOfFields, sizeof(my_bool));
|
267
409
|
wrapper->length = xcalloc(wrapper->numberOfFields, sizeof(unsigned long));
|
268
410
|
|
269
411
|
for (i = 0; i < wrapper->numberOfFields; i++) {
|
@@ -278,12 +420,12 @@ static void rb_mysql_result_alloc_result_buffers(VALUE self, MYSQL_FIELD *fields
|
|
278
420
|
wrapper->result_buffers[i].buffer_length = sizeof(signed char);
|
279
421
|
break;
|
280
422
|
case MYSQL_TYPE_SHORT: // short int
|
423
|
+
case MYSQL_TYPE_YEAR: // short int
|
281
424
|
wrapper->result_buffers[i].buffer = xcalloc(1, sizeof(short int));
|
282
425
|
wrapper->result_buffers[i].buffer_length = sizeof(short int);
|
283
426
|
break;
|
284
427
|
case MYSQL_TYPE_INT24: // int
|
285
428
|
case MYSQL_TYPE_LONG: // int
|
286
|
-
case MYSQL_TYPE_YEAR: // int
|
287
429
|
wrapper->result_buffers[i].buffer = xcalloc(1, sizeof(int));
|
288
430
|
wrapper->result_buffers[i].buffer_length = sizeof(int);
|
289
431
|
break;
|
@@ -335,16 +477,12 @@ static VALUE rb_mysql_result_fetch_row_stmt(VALUE self, MYSQL_FIELD * fields, co
|
|
335
477
|
VALUE rowVal;
|
336
478
|
unsigned int i = 0;
|
337
479
|
|
338
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
339
480
|
rb_encoding *default_internal_enc;
|
340
481
|
rb_encoding *conn_enc;
|
341
|
-
#endif
|
342
482
|
GET_RESULT(self);
|
343
483
|
|
344
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
345
484
|
default_internal_enc = rb_default_internal_encoding();
|
346
485
|
conn_enc = rb_to_encoding(wrapper->encoding);
|
347
|
-
#endif
|
348
486
|
|
349
487
|
if (wrapper->fields == Qnil) {
|
350
488
|
wrapper->numberOfFields = mysql_num_fields(wrapper->result);
|
@@ -413,6 +551,7 @@ static VALUE rb_mysql_result_fetch_row_stmt(VALUE self, MYSQL_FIELD * fields, co
|
|
413
551
|
}
|
414
552
|
break;
|
415
553
|
case MYSQL_TYPE_SHORT: // short int
|
554
|
+
case MYSQL_TYPE_YEAR: // short int
|
416
555
|
if (result_buffer->is_unsigned) {
|
417
556
|
val = UINT2NUM(*((unsigned short int*)result_buffer->buffer));
|
418
557
|
} else {
|
@@ -421,7 +560,6 @@ static VALUE rb_mysql_result_fetch_row_stmt(VALUE self, MYSQL_FIELD * fields, co
|
|
421
560
|
break;
|
422
561
|
case MYSQL_TYPE_INT24: // int
|
423
562
|
case MYSQL_TYPE_LONG: // int
|
424
|
-
case MYSQL_TYPE_YEAR: // int
|
425
563
|
if (result_buffer->is_unsigned) {
|
426
564
|
val = UINT2NUM(*((unsigned int*)result_buffer->buffer));
|
427
565
|
} else {
|
@@ -492,7 +630,7 @@ static VALUE rb_mysql_result_fetch_row_stmt(VALUE self, MYSQL_FIELD * fields, co
|
|
492
630
|
}
|
493
631
|
case MYSQL_TYPE_DECIMAL: // char[]
|
494
632
|
case MYSQL_TYPE_NEWDECIMAL: // char[]
|
495
|
-
val = rb_funcall(
|
633
|
+
val = rb_funcall(rb_mKernel, intern_BigDecimal, 1, rb_str_new(result_buffer->buffer, *(result_buffer->length)));
|
496
634
|
break;
|
497
635
|
case MYSQL_TYPE_STRING: // char[]
|
498
636
|
case MYSQL_TYPE_VAR_STRING: // char[]
|
@@ -506,9 +644,7 @@ static VALUE rb_mysql_result_fetch_row_stmt(VALUE self, MYSQL_FIELD * fields, co
|
|
506
644
|
case MYSQL_TYPE_GEOMETRY: // char[]
|
507
645
|
default:
|
508
646
|
val = rb_str_new(result_buffer->buffer, *(result_buffer->length));
|
509
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
510
647
|
val = mysql2_set_field_string_encoding(val, fields[i], default_internal_enc, conn_enc);
|
511
|
-
#endif
|
512
648
|
break;
|
513
649
|
}
|
514
650
|
}
|
@@ -530,16 +666,12 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, MYSQL_FIELD * fields, const r
|
|
530
666
|
unsigned int i = 0;
|
531
667
|
unsigned long * fieldLengths;
|
532
668
|
void * ptr;
|
533
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
534
669
|
rb_encoding *default_internal_enc;
|
535
670
|
rb_encoding *conn_enc;
|
536
|
-
#endif
|
537
671
|
GET_RESULT(self);
|
538
672
|
|
539
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
540
673
|
default_internal_enc = rb_default_internal_encoding();
|
541
674
|
conn_enc = rb_to_encoding(wrapper->encoding);
|
542
|
-
#endif
|
543
675
|
|
544
676
|
ptr = wrapper->result;
|
545
677
|
row = (MYSQL_ROW)rb_thread_call_without_gvl(nogvl_fetch_row, ptr, RUBY_UBF_IO, 0);
|
@@ -569,9 +701,7 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, MYSQL_FIELD * fields, const r
|
|
569
701
|
val = Qnil;
|
570
702
|
} else {
|
571
703
|
val = rb_str_new(row[i], fieldLengths[i]);
|
572
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
573
704
|
val = mysql2_set_field_string_encoding(val, fields[i], default_internal_enc, conn_enc);
|
574
|
-
#endif
|
575
705
|
}
|
576
706
|
} else {
|
577
707
|
switch(type) {
|
@@ -602,9 +732,9 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, MYSQL_FIELD * fields, const r
|
|
602
732
|
if (fields[i].decimals == 0) {
|
603
733
|
val = rb_cstr2inum(row[i], 10);
|
604
734
|
} else if (strtod(row[i], NULL) == 0.000000){
|
605
|
-
val = rb_funcall(
|
735
|
+
val = rb_funcall(rb_mKernel, intern_BigDecimal, 1, opt_decimal_zero);
|
606
736
|
}else{
|
607
|
-
val = rb_funcall(
|
737
|
+
val = rb_funcall(rb_mKernel, intern_BigDecimal, 1, rb_str_new(row[i], fieldLengths[i]));
|
608
738
|
}
|
609
739
|
break;
|
610
740
|
case MYSQL_TYPE_FLOAT: /* FLOAT field */
|
@@ -722,9 +852,7 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, MYSQL_FIELD * fields, const r
|
|
722
852
|
case MYSQL_TYPE_GEOMETRY: /* Spatial fielda */
|
723
853
|
default:
|
724
854
|
val = rb_str_new(row[i], fieldLengths[i]);
|
725
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
726
855
|
val = mysql2_set_field_string_encoding(val, fields[i], default_internal_enc, conn_enc);
|
727
|
-
#endif
|
728
856
|
break;
|
729
857
|
}
|
730
858
|
}
|
@@ -751,7 +879,7 @@ static VALUE rb_mysql_result_fetch_fields(VALUE self) {
|
|
751
879
|
|
752
880
|
GET_RESULT(self);
|
753
881
|
|
754
|
-
defaults =
|
882
|
+
defaults = rb_ivar_get(self, intern_query_options);
|
755
883
|
Check_Type(defaults, T_HASH);
|
756
884
|
if (rb_hash_aref(defaults, sym_symbolize_keys) == Qtrue) {
|
757
885
|
symbolizeKeys = 1;
|
@@ -771,6 +899,25 @@ static VALUE rb_mysql_result_fetch_fields(VALUE self) {
|
|
771
899
|
return wrapper->fields;
|
772
900
|
}
|
773
901
|
|
902
|
+
static VALUE rb_mysql_result_fetch_field_types(VALUE self) {
|
903
|
+
unsigned int i = 0;
|
904
|
+
|
905
|
+
GET_RESULT(self);
|
906
|
+
|
907
|
+
if (wrapper->fieldTypes == Qnil) {
|
908
|
+
wrapper->numberOfFields = mysql_num_fields(wrapper->result);
|
909
|
+
wrapper->fieldTypes = rb_ary_new2(wrapper->numberOfFields);
|
910
|
+
}
|
911
|
+
|
912
|
+
if ((my_ulonglong)RARRAY_LEN(wrapper->fieldTypes) != wrapper->numberOfFields) {
|
913
|
+
for (i=0; i<wrapper->numberOfFields; i++) {
|
914
|
+
rb_mysql_result_fetch_field_type(self, i);
|
915
|
+
}
|
916
|
+
}
|
917
|
+
|
918
|
+
return wrapper->fieldTypes;
|
919
|
+
}
|
920
|
+
|
774
921
|
static VALUE rb_mysql_result_each_(VALUE self,
|
775
922
|
VALUE(*fetch_row_func)(VALUE, MYSQL_FIELD *fields, const result_each_args *args),
|
776
923
|
const result_each_args *args)
|
@@ -796,7 +943,7 @@ static VALUE rb_mysql_result_each_(VALUE self,
|
|
796
943
|
row = fetch_row_func(self, fields, args);
|
797
944
|
if (row != Qnil) {
|
798
945
|
wrapper->numberOfRows++;
|
799
|
-
if (args->block_given
|
946
|
+
if (args->block_given) {
|
800
947
|
rb_yield(row);
|
801
948
|
}
|
802
949
|
}
|
@@ -846,7 +993,7 @@ static VALUE rb_mysql_result_each_(VALUE self,
|
|
846
993
|
return Qnil;
|
847
994
|
}
|
848
995
|
|
849
|
-
if (args->block_given
|
996
|
+
if (args->block_given) {
|
850
997
|
rb_yield(row);
|
851
998
|
}
|
852
999
|
}
|
@@ -864,7 +1011,7 @@ static VALUE rb_mysql_result_each_(VALUE self,
|
|
864
1011
|
|
865
1012
|
static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
|
866
1013
|
result_each_args args;
|
867
|
-
VALUE defaults, opts,
|
1014
|
+
VALUE defaults, opts, (*fetch_row_func)(VALUE, MYSQL_FIELD *fields, const result_each_args *args);
|
868
1015
|
ID db_timezone, app_timezone, dbTz, appTz;
|
869
1016
|
int symbolizeKeys, asArray, castBool, cacheRows, cast;
|
870
1017
|
|
@@ -874,9 +1021,12 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
|
|
874
1021
|
rb_raise(cMysql2Error, "Statement handle already closed");
|
875
1022
|
}
|
876
1023
|
|
877
|
-
defaults =
|
1024
|
+
defaults = rb_ivar_get(self, intern_query_options);
|
878
1025
|
Check_Type(defaults, T_HASH);
|
879
|
-
|
1026
|
+
|
1027
|
+
// A block can be passed to this method, but since we don't call the block directly from C,
|
1028
|
+
// we don't need to capture it into a variable here with the "&" scan arg.
|
1029
|
+
if (rb_scan_args(argc, argv, "01", &opts) == 1) {
|
880
1030
|
opts = rb_funcall(defaults, intern_merge, 1, opts);
|
881
1031
|
} else {
|
882
1032
|
opts = defaults;
|
@@ -942,7 +1092,7 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
|
|
942
1092
|
args.cast = cast;
|
943
1093
|
args.db_timezone = db_timezone;
|
944
1094
|
args.app_timezone = app_timezone;
|
945
|
-
args.block_given =
|
1095
|
+
args.block_given = rb_block_given_p();
|
946
1096
|
|
947
1097
|
if (wrapper->stmt_wrapper) {
|
948
1098
|
fetch_row_func = rb_mysql_result_fetch_row_stmt;
|
@@ -986,6 +1136,7 @@ VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_
|
|
986
1136
|
wrapper->resultFreed = 0;
|
987
1137
|
wrapper->result = r;
|
988
1138
|
wrapper->fields = Qnil;
|
1139
|
+
wrapper->fieldTypes = Qnil;
|
989
1140
|
wrapper->rows = Qnil;
|
990
1141
|
wrapper->encoding = encoding;
|
991
1142
|
wrapper->streamingComplete = 0;
|
@@ -1007,7 +1158,7 @@ VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_
|
|
1007
1158
|
}
|
1008
1159
|
|
1009
1160
|
rb_obj_call_init(obj, 0, NULL);
|
1010
|
-
|
1161
|
+
rb_ivar_set(obj, intern_query_options, options);
|
1011
1162
|
|
1012
1163
|
/* Options that cannot be changed in results.each(...) { |row| }
|
1013
1164
|
* should be processed here. */
|
@@ -1017,13 +1168,18 @@ VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_
|
|
1017
1168
|
}
|
1018
1169
|
|
1019
1170
|
void init_mysql2_result() {
|
1020
|
-
cBigDecimal = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
|
1021
1171
|
cDate = rb_const_get(rb_cObject, rb_intern("Date"));
|
1172
|
+
rb_global_variable(&cDate);
|
1022
1173
|
cDateTime = rb_const_get(rb_cObject, rb_intern("DateTime"));
|
1174
|
+
rb_global_variable(&cDateTime);
|
1023
1175
|
|
1024
1176
|
cMysql2Result = rb_define_class_under(mMysql2, "Result", rb_cObject);
|
1177
|
+
rb_undef_alloc_func(cMysql2Result);
|
1178
|
+
rb_global_variable(&cMysql2Result);
|
1179
|
+
|
1025
1180
|
rb_define_method(cMysql2Result, "each", rb_mysql_result_each, -1);
|
1026
1181
|
rb_define_method(cMysql2Result, "fields", rb_mysql_result_fetch_fields, 0);
|
1182
|
+
rb_define_method(cMysql2Result, "field_types", rb_mysql_result_fetch_field_types, 0);
|
1027
1183
|
rb_define_method(cMysql2Result, "free", rb_mysql_result_free_, 0);
|
1028
1184
|
rb_define_method(cMysql2Result, "count", rb_mysql_result_count, 0);
|
1029
1185
|
rb_define_alias(cMysql2Result, "size", "count");
|
@@ -1036,6 +1192,8 @@ void init_mysql2_result() {
|
|
1036
1192
|
intern_local_offset = rb_intern("local_offset");
|
1037
1193
|
intern_civil = rb_intern("civil");
|
1038
1194
|
intern_new_offset = rb_intern("new_offset");
|
1195
|
+
intern_BigDecimal = rb_intern("BigDecimal");
|
1196
|
+
intern_query_options = rb_intern("@query_options");
|
1039
1197
|
|
1040
1198
|
sym_symbolize_keys = ID2SYM(rb_intern("symbolize_keys"));
|
1041
1199
|
sym_as = ID2SYM(rb_intern("as"));
|
@@ -1058,7 +1216,5 @@ void init_mysql2_result() {
|
|
1058
1216
|
opt_time_month = INT2NUM(1);
|
1059
1217
|
opt_utc_offset = INT2NUM(0);
|
1060
1218
|
|
1061
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
1062
1219
|
binaryEncoding = rb_enc_find("binary");
|
1063
|
-
#endif
|
1064
1220
|
}
|
data/ext/mysql2/result.h
CHANGED
@@ -1,12 +1,12 @@
|
|
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);
|
7
6
|
|
8
7
|
typedef struct {
|
9
8
|
VALUE fields;
|
9
|
+
VALUE fieldTypes;
|
10
10
|
VALUE rows;
|
11
11
|
VALUE client;
|
12
12
|
VALUE encoding;
|
@@ -22,8 +22,8 @@ typedef struct {
|
|
22
22
|
mysql_client_wrapper *client_wrapper;
|
23
23
|
/* statement result bind buffers */
|
24
24
|
MYSQL_BIND *result_buffers;
|
25
|
-
|
26
|
-
|
25
|
+
my_bool *is_null;
|
26
|
+
my_bool *error;
|
27
27
|
unsigned long *length;
|
28
28
|
} mysql2_result_wrapper;
|
29
29
|
|