Skip to content

Commit ddd708b

Browse files
committed
Merge pull request #521 from zhaoyk/master
2 parents 671db18 + cb42b73 commit ddd708b

File tree

1 file changed

+24
-5
lines changed

1 file changed

+24
-5
lines changed

ext/mysql2/result.c

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,20 @@ static VALUE mysql2_set_field_string_encoding(VALUE val, MYSQL_FIELD field, rb_e
176176
}
177177
#endif
178178

179+
/* Interpret microseconds digits left-aligned in fixed-width field.
180+
* e.g. 10.123 seconds means 10 seconds and 123000 microseconds,
181+
* because the microseconds are to the right of the decimal point.
182+
*/
183+
static unsigned int msec_char_to_uint(char *msec_char, size_t len)
184+
{
185+
int i;
186+
for (i = 0; i < (len - 1); i++) {
187+
if (msec_char[i] == '\0') {
188+
msec_char[i] = '0';
189+
}
190+
}
191+
return (unsigned int)strtoul(msec_char, NULL, 10);
192+
}
179193

180194
static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezone, int symbolizeKeys, int asArray, int castBool, int cast, MYSQL_FIELD * fields) {
181195
VALUE rowVal;
@@ -274,13 +288,16 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
274288
}
275289
case MYSQL_TYPE_TIME: { /* TIME field */
276290
int tokens;
277-
unsigned int hour=0, min=0, sec=0;
278-
tokens = sscanf(row[i], "%2u:%2u:%2u", &hour, &min, &sec);
291+
unsigned int hour=0, min=0, sec=0, msec=0;
292+
char msec_char[7] = {'0','0','0','0','0','0','\0'};
293+
294+
tokens = sscanf(row[i], "%2u:%2u:%2u.%6s", &hour, &min, &sec, msec_char);
279295
if (tokens < 3) {
280296
val = Qnil;
281297
break;
282298
}
283-
val = rb_funcall(rb_cTime, db_timezone, 6, opt_time_year, opt_time_month, opt_time_month, UINT2NUM(hour), UINT2NUM(min), UINT2NUM(sec));
299+
msec = msec_char_to_uint(msec_char, sizeof(msec_char));
300+
val = rb_funcall(rb_cTime, db_timezone, 6, opt_time_year, opt_time_month, opt_time_month, UINT2NUM(hour), UINT2NUM(min), UINT2NUM(sec), UINT2NUM(msec));
284301
if (!NIL_P(app_timezone)) {
285302
if (app_timezone == intern_local) {
286303
val = rb_funcall(val, intern_localtime, 0);
@@ -294,9 +311,10 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
294311
case MYSQL_TYPE_DATETIME: { /* DATETIME field */
295312
int tokens;
296313
unsigned int year=0, month=0, day=0, hour=0, min=0, sec=0, msec=0;
314+
char msec_char[7] = {'0','0','0','0','0','0','\0'};
297315
uint64_t seconds;
298316

299-
tokens = sscanf(row[i], "%4u-%2u-%2u %2u:%2u:%2u.%6u", &year, &month, &day, &hour, &min, &sec, &msec);
317+
tokens = sscanf(row[i], "%4u-%2u-%2u %2u:%2u:%2u.%6s", &year, &month, &day, &hour, &min, &sec, msec_char);
300318
if (tokens < 6) { /* msec might be empty */
301319
val = Qnil;
302320
break;
@@ -324,7 +342,8 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
324342
val = rb_funcall(val, intern_new_offset, 1, opt_utc_offset);
325343
}
326344
}
327-
} else { /* use Time, supports microseconds */
345+
} else {
346+
msec = msec_char_to_uint(msec_char, sizeof(msec_char));
328347
val = rb_funcall(rb_cTime, db_timezone, 7, UINT2NUM(year), UINT2NUM(month), UINT2NUM(day), UINT2NUM(hour), UINT2NUM(min), UINT2NUM(sec), UINT2NUM(msec));
329348
if (!NIL_P(app_timezone)) {
330349
if (app_timezone == intern_local) {

0 commit comments

Comments
 (0)