@@ -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 );
@@ -294,9 +311,10 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
294
311
case MYSQL_TYPE_DATETIME : { /* DATETIME field */
295
312
int tokens ;
296
313
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' };
297
315
uint64_t seconds ;
298
316
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 );
300
318
if (tokens < 6 ) { /* msec might be empty */
301
319
val = Qnil ;
302
320
break ;
@@ -324,7 +342,8 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
324
342
val = rb_funcall (val , intern_new_offset , 1 , opt_utc_offset );
325
343
}
326
344
}
327
- } else { /* use Time, supports microseconds */
345
+ } else {
346
+ msec = msec_char_to_uint (msec_char , sizeof (msec_char ));
328
347
val = rb_funcall (rb_cTime , db_timezone , 7 , UINT2NUM (year ), UINT2NUM (month ), UINT2NUM (day ), UINT2NUM (hour ), UINT2NUM (min ), UINT2NUM (sec ), UINT2NUM (msec ));
329
348
if (!NIL_P (app_timezone )) {
330
349
if (app_timezone == intern_local ) {
0 commit comments