Save on coercion overhead for zero value decimal and float column values

This commit is contained in:
Lourens Naudé 2010-08-08 18:33:55 +01:00 committed by Brian Lopez
parent c808e78028
commit d9153b82fc
3 changed files with 28 additions and 6 deletions

View File

@ -22,8 +22,10 @@ create_table_sql = %[
int_test INT,
big_int_test BIGINT,
float_test FLOAT(10,3),
float_zero_test FLOAT(10,3),
double_test DOUBLE(10,3),
decimal_test DECIMAL(10,3),
decimal_zero_test DECIMAL(10,3),
date_test DATE,
date_time_test DATETIME,
timestamp_test TIMESTAMP,
@ -55,7 +57,7 @@ def insert_record(args)
insert_sql = "
INSERT INTO mysql2_test (
null_test, bit_test, tiny_int_test, small_int_test, medium_int_test, int_test, big_int_test,
float_test, double_test, decimal_test, date_test, date_time_test, timestamp_test, time_test,
float_test, float_zero_test, double_test, decimal_test, decimal_zero_test, date_test, date_time_test, timestamp_test, time_test,
year_test, char_test, varchar_test, binary_test, varbinary_test, tiny_blob_test,
tiny_text_test, blob_test, text_test, medium_blob_test, medium_text_test,
long_blob_test, long_text_test, enum_test, set_test
@ -63,7 +65,7 @@ def insert_record(args)
VALUES (
NULL, #{args[:bit_test]}, #{args[:tiny_int_test]}, #{args[:small_int_test]}, #{args[:medium_int_test]}, #{args[:int_test]}, #{args[:big_int_test]},
#{args[:float_test]}, #{args[:double_test]}, #{args[:decimal_test]}, '#{args[:date_test]}', '#{args[:date_time_test]}', '#{args[:timestamp_test]}', '#{args[:time_test]}',
#{args[:float_test]}, #{args[:float_zero_test]}, #{args[:double_test]}, #{args[:decimal_test]}, #{args[:decimal_zero_test]}, '#{args[:date_test]}', '#{args[:date_time_test]}', '#{args[:timestamp_test]}', '#{args[:time_test]}',
#{args[:year_test]}, '#{args[:char_test]}', '#{args[:varchar_test]}', '#{args[:binary_test]}', '#{args[:varbinary_test]}', '#{args[:tiny_blob_test]}',
'#{args[:tiny_text_test]}', '#{args[:blob_test]}', '#{args[:text_test]}', '#{args[:medium_blob_test]}', '#{args[:medium_text_test]}',
'#{args[:long_blob_test]}', '#{args[:long_text_test]}', '#{args[:enum_test]}', '#{args[:set_test]}'
@ -82,8 +84,10 @@ num.times do |n|
:int_test => rand(2147483647),
:big_int_test => rand(9223372036854775807),
:float_test => rand(32767)/1.87,
:float_zero_test => 0.0,
:double_test => rand(8388607)/1.87,
:decimal_test => rand(8388607)/1.87,
:decimal_zero_test => 0,
:date_test => '2010-4-4',
:date_time_test => '2010-4-4 11:44:00',
:timestamp_test => '2010-4-4 11:44:00',

View File

@ -6,6 +6,7 @@ rb_encoding *binaryEncoding;
VALUE cMysql2Result;
VALUE cBigDecimal, cDate, cDateTime;
VALUE opt_decimal_zero, opt_float_zero;
extern VALUE mMysql2, cMysql2Client, cMysql2Error;
static VALUE intern_encoding_from_charset;
static ID intern_new, intern_utc, intern_local, intern_encoding_from_charset_code,
@ -95,6 +96,7 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
MYSQL_FIELD * fields = NULL;
unsigned int i = 0;
unsigned long * fieldLengths;
double column_to_double;
void * ptr;
#ifdef HAVE_RUBY_ENCODING_H
rb_encoding *default_internal_enc = rb_default_internal_encoding();
@ -146,11 +148,20 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
break;
case MYSQL_TYPE_DECIMAL: // DECIMAL or NUMERIC field
case MYSQL_TYPE_NEWDECIMAL: // Precision math DECIMAL or NUMERIC field (MySQL 5.0.3 and up)
val = rb_funcall(cBigDecimal, intern_new, 1, rb_str_new(row[i], fieldLengths[i]));
if (strtod(row[i], NULL) == 0.000000){
val = rb_funcall(cBigDecimal, intern_new, 1, opt_decimal_zero);
}else{
val = rb_funcall(cBigDecimal, intern_new, 1, rb_str_new(row[i], fieldLengths[i]));
}
break;
case MYSQL_TYPE_FLOAT: // FLOAT field
case MYSQL_TYPE_DOUBLE: // DOUBLE or REAL field
val = rb_float_new(strtod(row[i], NULL));
column_to_double = strtod(row[i], NULL);
if (column_to_double == 0.000000){
val = opt_float_zero;
}else{
val = rb_float_new(column_to_double);
}
break;
case MYSQL_TYPE_TIME: { // TIME field
int hour, min, sec, tokens;
@ -420,6 +431,11 @@ void init_mysql2_result() {
sym_database_timezone = ID2SYM(rb_intern("database_timezone"));
sym_application_timezone = ID2SYM(rb_intern("application_timezone"));
rb_global_variable(&opt_decimal_zero); //never GC
opt_decimal_zero = rb_str_new2("0.0");
rb_global_variable(&opt_float_zero);
opt_float_zero = rb_float_new((double)0);
#ifdef HAVE_RUBY_ENCODING_H
binaryEncoding = rb_enc_find("binary");
#endif

View File

@ -20,8 +20,10 @@ Spec::Runner.configure do |config|
int_test INT,
big_int_test BIGINT,
float_test FLOAT(10,3),
float_zero_test FLOAT(10,3),
double_test DOUBLE(10,3),
decimal_test DECIMAL(10,3),
decimal_zero_test DECIMAL(10,3),
date_test DATE,
date_time_test DATETIME,
timestamp_test TIMESTAMP,
@ -47,7 +49,7 @@ Spec::Runner.configure do |config|
client.query %[
INSERT INTO mysql2_test (
null_test, bit_test, tiny_int_test, bool_cast_test, small_int_test, medium_int_test, int_test, big_int_test,
float_test, double_test, decimal_test, date_test, date_time_test, timestamp_test, time_test,
float_test, float_zero_test, double_test, decimal_test, decimal_zero_test, date_test, date_time_test, timestamp_test, time_test,
year_test, char_test, varchar_test, binary_test, varbinary_test, tiny_blob_test,
tiny_text_test, blob_test, text_test, medium_blob_test, medium_text_test,
long_blob_test, long_text_test, enum_test, set_test
@ -55,7 +57,7 @@ Spec::Runner.configure do |config|
VALUES (
NULL, b'101', 1, 1, 10, 10, 10, 10,
10.3, 10.3, 10.3, '2010-4-4', '2010-4-4 11:44:00', '2010-4-4 11:44:00', '11:44:00',
10.3, 0, 10.3, 10.3, 0, '2010-4-4', '2010-4-4 11:44:00', '2010-4-4 11:44:00', '11:44:00',
2009, "test", "test", "test", "test", "test",
"test", "test", "test", "test", "test",
"test", "test", 'val1', 'val1,val2'