mysql2 icon indicating copy to clipboard operation
mysql2 copied to clipboard

Prepared statement float value converted to 64bits ?

Open ericproulx opened this issue 2 years ago • 1 comments

Hi,

When trying to switch to prepared_statements, our float columns had different values in ruby (2.6 series).

For instance, 1.1 is now 1.100000023841858

I know that 1.100000023841858 is a limited floating point representation using 32bits.

I'm far from being an expert in C but when looking at the code, I've figured that a T_FLOAT is converted to as MYSQL_TYPE_DOUBLE in a case of a prepared statement

case T_FLOAT:
  bind_buffers[i].buffer_type = MYSQL_TYPE_DOUBLE;
  bind_buffers[i].buffer = xmalloc(sizeof(double));
  *(double*)(bind_buffers[i].buffer) = NUM2DBL(argv[i]);
  break;

But it's not handle the same way within a simple MySQL result

case MYSQL_TYPE_FLOAT:        // float
  val = rb_float_new((double)(*((float*)result_buffer->buffer)));
  break;
case MYSQL_TYPE_DOUBLE:       // double
  val = rb_float_new((double)(*((double*)result_buffer->buffer)));
  break;

At least, the buffer seems to be handled differently.

Also, I did a small change locally by switching my float column to double column and 1.1 stays 1.1.

Thanks for your time :)

ericproulx avatar Aug 03 '22 12:08 ericproulx

Yes, this is an interesting case. MySQL's FLOAT column type is single-precision and DOUBLE is double-precision. Ruby doesn't have a single-precision floating point, so both are mapped to Ruby's Float which is double-precision.

sodabrew avatar Aug 04 '22 05:08 sodabrew