|
3 | 3 | VALUE cMysql2Statement;
|
4 | 4 | extern VALUE mMysql2, cMysql2Error, cBigDecimal, cDateTime, cDate;
|
5 | 5 | static VALUE sym_stream, intern_new_with_args, intern_each;
|
6 |
| -static VALUE intern_usec, intern_sec, intern_min, intern_hour, intern_day, intern_month, intern_year; |
| 6 | +static VALUE intern_usec, intern_sec, intern_min, intern_hour, intern_day, intern_month, intern_year, intern_to_s; |
7 | 7 |
|
8 | 8 | #define GET_STATEMENT(self) \
|
9 | 9 | mysql_stmt_wrapper *stmt_wrapper; \
|
@@ -190,6 +190,19 @@ static void *nogvl_stmt_store_result(void *ptr) {
|
190 | 190 | }
|
191 | 191 | }
|
192 | 192 |
|
| 193 | +static void set_buffer_for_string(MYSQL_BIND* bind_buffer, unsigned long *length_buffer, VALUE string) { |
| 194 | + int length; |
| 195 | + |
| 196 | + bind_buffer->buffer_type = MYSQL_TYPE_STRING; |
| 197 | + bind_buffer->buffer = RSTRING_PTR(string); |
| 198 | + |
| 199 | + length = RSTRING_LEN(string); |
| 200 | + bind_buffer->buffer_length = length; |
| 201 | + *length_buffer = length; |
| 202 | + |
| 203 | + bind_buffer->length = length_buffer; |
| 204 | +} |
| 205 | + |
193 | 206 | /* Free each bind_buffer[i].buffer except when params_enc is non-nil, this means
|
194 | 207 | * the buffer is a Ruby string pointer and not our memory to manage.
|
195 | 208 | */
|
@@ -280,11 +293,7 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) {
|
280 | 293 | #ifdef HAVE_RUBY_ENCODING_H
|
281 | 294 | params_enc[i] = rb_str_export_to_enc(params_enc[i], conn_enc);
|
282 | 295 | #endif
|
283 |
| - bind_buffers[i].buffer_type = MYSQL_TYPE_STRING; |
284 |
| - bind_buffers[i].buffer = RSTRING_PTR(params_enc[i]); |
285 |
| - bind_buffers[i].buffer_length = RSTRING_LEN(params_enc[i]); |
286 |
| - length_buffers[i] = bind_buffers[i].buffer_length; |
287 |
| - bind_buffers[i].length = &length_buffers[i]; |
| 296 | + set_buffer_for_string(&bind_buffers[i], &length_buffers[i], params_enc[i]); |
288 | 297 | }
|
289 | 298 | break;
|
290 | 299 | default:
|
@@ -324,6 +333,19 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) {
|
324 | 333 | *(MYSQL_TIME*)(bind_buffers[i].buffer) = t;
|
325 | 334 | } else if (CLASS_OF(argv[i]) == cBigDecimal) {
|
326 | 335 | bind_buffers[i].buffer_type = MYSQL_TYPE_NEWDECIMAL;
|
| 336 | + |
| 337 | + // DECIMAL are represented with the "string representation of the |
| 338 | + // original server-side value", see |
| 339 | + // https://dev.mysql.com/doc/refman/5.7/en/c-api-prepared-statement-type-conversions.html |
| 340 | + // This should be independent of the locale used both on the server |
| 341 | + // and the client side. |
| 342 | + VALUE rb_val_as_string = rb_funcall(argv[i], intern_to_s, 0); |
| 343 | + |
| 344 | + params_enc[i] = rb_val_as_string; |
| 345 | +#ifdef HAVE_RUBY_ENCODING_H |
| 346 | + params_enc[i] = rb_str_export_to_enc(params_enc[i], conn_enc); |
| 347 | +#endif |
| 348 | + set_buffer_for_string(&bind_buffers[i], &length_buffers[i], params_enc[i]); |
327 | 349 | }
|
328 | 350 | break;
|
329 | 351 | }
|
@@ -491,4 +513,6 @@ void init_mysql2_statement() {
|
491 | 513 | intern_day = rb_intern("day");
|
492 | 514 | intern_month = rb_intern("month");
|
493 | 515 | intern_year = rb_intern("year");
|
| 516 | + |
| 517 | + intern_to_s = rb_intern("to_s"); |
494 | 518 | }
|
0 commit comments