Skip to content

Commit cb42b73

Browse files
committed
Refactor the microseconds DATE code to also handle microseconds in a TIME field
1 parent 57f8428 commit cb42b73

File tree

1 file changed

+21
-15
lines changed

1 file changed

+21
-15
lines changed

ext/mysql2/result.c

Lines changed: 21 additions & 15 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);
@@ -326,18 +343,7 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
326343
}
327344
}
328345
} else {
329-
/* microseconds can be up to 6 digits. Fewer digits must be interpreted from
330-
* the left because the microseconds are to the right of the decimal point.
331-
*/
332-
if (tokens == 7) {
333-
int i;
334-
for (i = 0; i < 6; ++i) {
335-
if (msec_char[i] == '\0') {
336-
msec_char[i] = '0';
337-
}
338-
}
339-
msec = (unsigned int)strtoul(msec_char, NULL, 10);
340-
}
346+
msec = msec_char_to_uint(msec_char, sizeof(msec_char));
341347
val = rb_funcall(rb_cTime, db_timezone, 7, UINT2NUM(year), UINT2NUM(month), UINT2NUM(day), UINT2NUM(hour), UINT2NUM(min), UINT2NUM(sec), UINT2NUM(msec));
342348
if (!NIL_P(app_timezone)) {
343349
if (app_timezone == intern_local) {

0 commit comments

Comments
 (0)