@@ -176,6 +176,20 @@ static VALUE mysql2_set_field_string_encoding(VALUE val, MYSQL_FIELD field, rb_e
176
176
}
177
177
#endif
178
178
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
+ }
179
193
180
194
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 ) {
181
195
VALUE rowVal ;
@@ -274,13 +288,16 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
274
288
}
275
289
case MYSQL_TYPE_TIME : { /* TIME field */
276
290
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 );
279
295
if (tokens < 3 ) {
280
296
val = Qnil ;
281
297
break ;
282
298
}
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 ));
284
301
if (!NIL_P (app_timezone )) {
285
302
if (app_timezone == intern_local ) {
286
303
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
326
343
}
327
344
}
328
345
} 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 ));
341
347
val = rb_funcall (rb_cTime , db_timezone , 7 , UINT2NUM (year ), UINT2NUM (month ), UINT2NUM (day ), UINT2NUM (hour ), UINT2NUM (min ), UINT2NUM (sec ), UINT2NUM (msec ));
342
348
if (!NIL_P (app_timezone )) {
343
349
if (app_timezone == intern_local ) {
0 commit comments