diff options
-rw-r--r-- | include/decimal.h | 8 | ||||
-rw-r--r-- | sql/sql_show.cc | 4 | ||||
-rw-r--r-- | strings/decimal.c | 28 |
3 files changed, 28 insertions, 12 deletions
diff --git a/include/decimal.h b/include/decimal.h index 5b5b8c0b460..fddae1f54a6 100644 --- a/include/decimal.h +++ b/include/decimal.h @@ -51,13 +51,7 @@ int decimal_mul(decimal *from1, decimal *from2, decimal *to); int decimal_div(decimal *from1, decimal *from2, decimal *to, int scale_incr); int decimal_mod(decimal *from1, decimal *from2, decimal *to); int decimal_round(decimal *from, decimal *to, int new_scale, decimal_round_mode mode); - -/* - the following works only on special "zero" decimal, not on any - decimal that happen to evaluate to zero -*/ - -#define decimal_is_zero(dec) ((dec)->intg1==1 && (dec)->frac1==0 && (dec)->buf[0]==0) +int decimal_is_zero(decimal *from); /* set a decimal to zero */ diff --git a/sql/sql_show.cc b/sql/sql_show.cc index fd12c206e64..f30eeb2d206 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2951,10 +2951,12 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) } break; default: - if (!(item= new Item_string("", fields_info->field_length, cs))) + /* this should be changed when Item_empty_string is fixed(in 4.1) */ + if (!(item= new Item_empty_string("", 0, cs))) { DBUG_RETURN(0); } + item->max_length= fields_info->field_length * cs->mbmaxlen; item->set_name(fields_info->field_name, strlen(fields_info->field_name), cs); break; diff --git a/strings/decimal.c b/strings/decimal.c index 224d75f6844..2dcc2c88ceb 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -901,19 +901,26 @@ int decimal_round(decimal *from, decimal *to, int scale, decimal_round_mode mode if (scale >= from->frac) goto done; /* nothing to do */ - DBUG_ASSERT(frac0+intg0 > 0); buf0+=intg0+frac0-1; buf1+=intg0+frac0-1; if (scale == frac0*DIG_PER_DEC1) { + DBUG_ASSERT(frac0+intg0 >= 0); x=buf0[1]/DIG_MASK; if (x > round_digit || - (round_digit == 5 && x == 5 && (mode == HALF_UP || *buf0 & 1))) - (*buf1)++; + (round_digit == 5 && x == 5 && (mode == HALF_UP || + (frac0+intg0 > 0 && *buf0 & 1)))) + { + if (frac0+intg0>0) + (*buf1)++; + else + *(++buf1)=DIG_BASE; + } } else { int pos=frac0*DIG_PER_DEC1-scale-1; + DBUG_ASSERT(frac0+intg0 > 0); x=*buf1 / powers10[pos]; y=x % 10; if (y > round_digit || @@ -942,7 +949,7 @@ int decimal_round(decimal *from, decimal *to, int scale, decimal_round_mode mode scale=frac0*DIG_PER_DEC1; error=E_DEC_TRUNCATED; /* XXX */ } - for (buf1=to->buf+frac0+intg0; buf1 > to->buf; buf1--) + for (buf1=to->buf+intg0+max(frac0,0); buf1 > to->buf; buf1--) { buf1[0]=buf1[-1]; } @@ -1233,6 +1240,16 @@ int decimal_cmp(decimal *from1, decimal *from2) return from1->sign > from2->sign ? -1 : 1; } +int decimal_is_zero(decimal *from) +{ + dec1 *buf1=from->buf, + *end=buf1+ROUND_UP(from->intg)+ROUND_UP(from->frac); + while (buf1 < end) + if (*buf1++) + return 0; + return 1; +} + /* multiply two decimals @@ -2103,6 +2120,9 @@ main() test_ro("15.4",-1,HALF_UP,"20"); test_ro("-15.4",-1,HALF_UP,"-20"); test_ro("5.4",-1,HALF_UP,"10"); + test_ro(".999", 0, HALF_UP, "1"); + memset(buf2, 33, sizeof(buf2)); + test_ro("999999999", -9, HALF_UP, "1000000000"); test_ro("15.1",0,HALF_EVEN,"15"); test_ro("15.5",0,HALF_EVEN,"16"); test_ro("14.5",0,HALF_EVEN,"14"); |