mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 04:53:01 +01:00
Adding handling of numbers with exponent to decimal type.
This commit is contained in:
parent
1d074b3d16
commit
e773a26e6e
3 changed files with 363 additions and 130 deletions
|
@ -156,6 +156,8 @@ insert into t1 values ("-.1"),("+.1"),(".1");
|
||||||
insert into t1 values ("00000000000001"),("+0000000000001"),("-0000000000001");
|
insert into t1 values ("00000000000001"),("+0000000000001"),("-0000000000001");
|
||||||
insert into t1 values ("+111111111.11"),("111111111.11"),("-11111111.11");
|
insert into t1 values ("+111111111.11"),("111111111.11"),("-11111111.11");
|
||||||
insert into t1 values ("-111111111.11"),("+1111111111.11"),("1111111111.11");
|
insert into t1 values ("-111111111.11"),("+1111111111.11"),("1111111111.11");
|
||||||
|
insert into t1 values ("1e+1000"),("1e-1000"),("-1e+1000");
|
||||||
|
insert into t1 values ("123.4e"),("123.4e+2"),("123.4e-2"),("123e1"),("123e+0");
|
||||||
select * from t1;
|
select * from t1;
|
||||||
a
|
a
|
||||||
0.00
|
0.00
|
||||||
|
@ -176,6 +178,14 @@ a
|
||||||
-99999999.99
|
-99999999.99
|
||||||
999999999.99
|
999999999.99
|
||||||
999999999.99
|
999999999.99
|
||||||
|
999999999.99
|
||||||
|
0.00
|
||||||
|
-99999999.99
|
||||||
|
123.40
|
||||||
|
12340.00
|
||||||
|
1.23
|
||||||
|
1230.00
|
||||||
|
123.00
|
||||||
drop table t1;
|
drop table t1;
|
||||||
create table t1 (a decimal(10,2) unsigned);
|
create table t1 (a decimal(10,2) unsigned);
|
||||||
insert into t1 values ("0.0"),("-0.0"),("+0.0"),("01.0"),("+01.0"),("-01.0");
|
insert into t1 values ("0.0"),("-0.0"),("+0.0"),("01.0"),("+01.0"),("-01.0");
|
||||||
|
@ -183,6 +193,8 @@ insert into t1 values ("-.1"),("+.1"),(".1");
|
||||||
insert into t1 values ("00000000000001"),("+0000000000001"),("-0000000000001");
|
insert into t1 values ("00000000000001"),("+0000000000001"),("-0000000000001");
|
||||||
insert into t1 values ("+111111111.11"),("111111111.11"),("-11111111.11");
|
insert into t1 values ("+111111111.11"),("111111111.11"),("-11111111.11");
|
||||||
insert into t1 values ("-111111111.11"),("+1111111111.11"),("1111111111.11");
|
insert into t1 values ("-111111111.11"),("+1111111111.11"),("1111111111.11");
|
||||||
|
insert into t1 values ("1e+1000"),("1e-1000"),("-1e+1000");
|
||||||
|
insert into t1 values ("123.4e"),("123.4e+2"),("123.4e-2"),("123e1"),("123e+0");
|
||||||
select * from t1;
|
select * from t1;
|
||||||
a
|
a
|
||||||
0.00
|
0.00
|
||||||
|
@ -203,6 +215,14 @@ a
|
||||||
0.00
|
0.00
|
||||||
99999999.99
|
99999999.99
|
||||||
99999999.99
|
99999999.99
|
||||||
|
99999999.99
|
||||||
|
0.00
|
||||||
|
0.00
|
||||||
|
123.40
|
||||||
|
12340.00
|
||||||
|
1.23
|
||||||
|
1230.00
|
||||||
|
123.00
|
||||||
drop table t1;
|
drop table t1;
|
||||||
create table t1 (a decimal(10,2) zerofill);
|
create table t1 (a decimal(10,2) zerofill);
|
||||||
insert into t1 values ("0.0"),("-0.0"),("+0.0"),("01.0"),("+01.0"),("-01.0");
|
insert into t1 values ("0.0"),("-0.0"),("+0.0"),("01.0"),("+01.0"),("-01.0");
|
||||||
|
@ -210,6 +230,8 @@ insert into t1 values ("-.1"),("+.1"),(".1");
|
||||||
insert into t1 values ("00000000000001"),("+0000000000001"),("-0000000000001");
|
insert into t1 values ("00000000000001"),("+0000000000001"),("-0000000000001");
|
||||||
insert into t1 values ("+111111111.11"),("111111111.11"),("-11111111.11");
|
insert into t1 values ("+111111111.11"),("111111111.11"),("-11111111.11");
|
||||||
insert into t1 values ("-111111111.11"),("+1111111111.11"),("1111111111.11");
|
insert into t1 values ("-111111111.11"),("+1111111111.11"),("1111111111.11");
|
||||||
|
insert into t1 values ("1e+1000"),("1e-1000"),("-1e+1000");
|
||||||
|
insert into t1 values ("123.4e"),("123.4e+2"),("123.4e-2"),("123e1"),("123e+0");
|
||||||
select * from t1;
|
select * from t1;
|
||||||
a
|
a
|
||||||
00000000.00
|
00000000.00
|
||||||
|
@ -230,6 +252,14 @@ a
|
||||||
00000000.00
|
00000000.00
|
||||||
99999999.99
|
99999999.99
|
||||||
99999999.99
|
99999999.99
|
||||||
|
99999999.99
|
||||||
|
00000000.00
|
||||||
|
00000000.00
|
||||||
|
00000123.40
|
||||||
|
00012340.00
|
||||||
|
00000001.23
|
||||||
|
00001230.00
|
||||||
|
00000123.00
|
||||||
drop table t1;
|
drop table t1;
|
||||||
create table t1 (a decimal(10,2));
|
create table t1 (a decimal(10,2));
|
||||||
insert into t1 values (0.0),("-0.0"),(+0.0),(01.0),(+01.0),(-01.0);
|
insert into t1 values (0.0),("-0.0"),(+0.0),(01.0),(+01.0),(-01.0);
|
||||||
|
@ -237,6 +267,8 @@ insert into t1 values (-.1),(+.1),(.1);
|
||||||
insert into t1 values (00000000000001),(+0000000000001),(-0000000000001);
|
insert into t1 values (00000000000001),(+0000000000001),(-0000000000001);
|
||||||
insert into t1 values (+111111111.11),(111111111.11),(-11111111.11);
|
insert into t1 values (+111111111.11),(111111111.11),(-11111111.11);
|
||||||
insert into t1 values (-111111111.11),(+1111111111.11),(1111111111.11);
|
insert into t1 values (-111111111.11),(+1111111111.11),(1111111111.11);
|
||||||
|
insert into t1 values (1e+1000),(1e-1000),(-1e+1000);
|
||||||
|
insert into t1 values (123.4e0),(123.4e+2),(123.4e-2),(123e1),(123e+0);
|
||||||
select * from t1;
|
select * from t1;
|
||||||
a
|
a
|
||||||
0.00
|
0.00
|
||||||
|
@ -257,6 +289,14 @@ a
|
||||||
-99999999.99
|
-99999999.99
|
||||||
999999999.99
|
999999999.99
|
||||||
999999999.99
|
999999999.99
|
||||||
|
999999999.99
|
||||||
|
0.00
|
||||||
|
-99999999.99
|
||||||
|
123.40
|
||||||
|
12340.00
|
||||||
|
1.23
|
||||||
|
1230.00
|
||||||
|
123.00
|
||||||
drop table t1;
|
drop table t1;
|
||||||
create table t1 (a decimal);
|
create table t1 (a decimal);
|
||||||
insert into t1 values (-99999999999999),(-1),('+1'),('01'),('+00000000000001'),('+12345678901'),(99999999999999);
|
insert into t1 values (-99999999999999),(-1),('+1'),('01'),('+00000000000001'),('+12345678901'),(99999999999999);
|
||||||
|
|
|
@ -160,6 +160,8 @@ insert into t1 values ("-.1"),("+.1"),(".1");
|
||||||
insert into t1 values ("00000000000001"),("+0000000000001"),("-0000000000001");
|
insert into t1 values ("00000000000001"),("+0000000000001"),("-0000000000001");
|
||||||
insert into t1 values ("+111111111.11"),("111111111.11"),("-11111111.11");
|
insert into t1 values ("+111111111.11"),("111111111.11"),("-11111111.11");
|
||||||
insert into t1 values ("-111111111.11"),("+1111111111.11"),("1111111111.11");
|
insert into t1 values ("-111111111.11"),("+1111111111.11"),("1111111111.11");
|
||||||
|
insert into t1 values ("1e+1000"),("1e-1000"),("-1e+1000");
|
||||||
|
insert into t1 values ("123.4e"),("123.4e+2"),("123.4e-2"),("123e1"),("123e+0");
|
||||||
select * from t1;
|
select * from t1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
@ -169,6 +171,8 @@ insert into t1 values ("-.1"),("+.1"),(".1");
|
||||||
insert into t1 values ("00000000000001"),("+0000000000001"),("-0000000000001");
|
insert into t1 values ("00000000000001"),("+0000000000001"),("-0000000000001");
|
||||||
insert into t1 values ("+111111111.11"),("111111111.11"),("-11111111.11");
|
insert into t1 values ("+111111111.11"),("111111111.11"),("-11111111.11");
|
||||||
insert into t1 values ("-111111111.11"),("+1111111111.11"),("1111111111.11");
|
insert into t1 values ("-111111111.11"),("+1111111111.11"),("1111111111.11");
|
||||||
|
insert into t1 values ("1e+1000"),("1e-1000"),("-1e+1000");
|
||||||
|
insert into t1 values ("123.4e"),("123.4e+2"),("123.4e-2"),("123e1"),("123e+0");
|
||||||
select * from t1;
|
select * from t1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
@ -178,6 +182,8 @@ insert into t1 values ("-.1"),("+.1"),(".1");
|
||||||
insert into t1 values ("00000000000001"),("+0000000000001"),("-0000000000001");
|
insert into t1 values ("00000000000001"),("+0000000000001"),("-0000000000001");
|
||||||
insert into t1 values ("+111111111.11"),("111111111.11"),("-11111111.11");
|
insert into t1 values ("+111111111.11"),("111111111.11"),("-11111111.11");
|
||||||
insert into t1 values ("-111111111.11"),("+1111111111.11"),("1111111111.11");
|
insert into t1 values ("-111111111.11"),("+1111111111.11"),("1111111111.11");
|
||||||
|
insert into t1 values ("1e+1000"),("1e-1000"),("-1e+1000");
|
||||||
|
insert into t1 values ("123.4e"),("123.4e+2"),("123.4e-2"),("123e1"),("123e+0");
|
||||||
select * from t1;
|
select * from t1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
@ -189,6 +195,8 @@ insert into t1 values (-.1),(+.1),(.1);
|
||||||
insert into t1 values (00000000000001),(+0000000000001),(-0000000000001);
|
insert into t1 values (00000000000001),(+0000000000001),(-0000000000001);
|
||||||
insert into t1 values (+111111111.11),(111111111.11),(-11111111.11);
|
insert into t1 values (+111111111.11),(111111111.11),(-11111111.11);
|
||||||
insert into t1 values (-111111111.11),(+1111111111.11),(1111111111.11);
|
insert into t1 values (-111111111.11),(+1111111111.11),(1111111111.11);
|
||||||
|
insert into t1 values (1e+1000),(1e-1000),(-1e+1000);
|
||||||
|
insert into t1 values (123.4e0),(123.4e+2),(123.4e-2),(123e1),(123e+0);
|
||||||
select * from t1;
|
select * from t1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
|
445
sql/field.cc
445
sql/field.cc
|
@ -42,7 +42,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
** Instansiate templates and static variables
|
Instansiate templates and static variables
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
|
@ -50,69 +50,13 @@ template class List<create_field>;
|
||||||
template class List_iterator<create_field>;
|
template class List_iterator<create_field>;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct st_decstr {
|
|
||||||
uint nr_length,nr_dec,sign,extra;
|
|
||||||
char sign_char;
|
|
||||||
};
|
|
||||||
|
|
||||||
uchar Field_null::null[1]={1};
|
uchar Field_null::null[1]={1};
|
||||||
const char field_separator=',';
|
const char field_separator=',';
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
** Static help functions
|
Static help functions
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
/*
|
|
||||||
Calculate length of number and its parts
|
|
||||||
Increment cuted_fields if wrong number
|
|
||||||
*/
|
|
||||||
|
|
||||||
static bool
|
|
||||||
number_dec(struct st_decstr *sdec, const char *str, const char *end)
|
|
||||||
{
|
|
||||||
sdec->sign=sdec->extra=0;
|
|
||||||
if (str == end)
|
|
||||||
{
|
|
||||||
current_thd->cuted_fields++;
|
|
||||||
sdec->nr_length=sdec->nr_dec=sdec->sign=0;
|
|
||||||
sdec->extra=1; // We must put one 0 before .
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*str == '-' || *str == '+') /* sign */
|
|
||||||
{
|
|
||||||
sdec->sign_char= *str;
|
|
||||||
sdec->sign=1;
|
|
||||||
str++;
|
|
||||||
}
|
|
||||||
const char *start=str;
|
|
||||||
while (str != end && isdigit(*str))
|
|
||||||
str++;
|
|
||||||
if (!(sdec->nr_length=(uint) (str-start)))
|
|
||||||
sdec->extra=1; // We must put one 0 before .
|
|
||||||
start=str;
|
|
||||||
if (str != end && *str == '.')
|
|
||||||
{
|
|
||||||
str++;
|
|
||||||
start=str;
|
|
||||||
while (str != end && isdigit(*str))
|
|
||||||
str++;
|
|
||||||
}
|
|
||||||
sdec->nr_dec=(uint) (str-start);
|
|
||||||
if (current_thd->count_cuted_fields)
|
|
||||||
{
|
|
||||||
while (str != end && isspace(*str))
|
|
||||||
str++; /* purecov: inspected */
|
|
||||||
if (str != end)
|
|
||||||
{
|
|
||||||
current_thd->cuted_fields++;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Field_num::prepend_zeros(String *value)
|
void Field_num::prepend_zeros(String *value)
|
||||||
{
|
{
|
||||||
int diff;
|
int diff;
|
||||||
|
@ -127,8 +71,8 @@ void Field_num::prepend_zeros(String *value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Test if given number is a int (or a fixed format float with .000)
|
Test if given number is a int (or a fixed format float with .000)
|
||||||
** This is only used to give warnings in ALTER TABLE or LOAD DATA...
|
This is only used to give warnings in ALTER TABLE or LOAD DATA...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool test_if_int(const char *str,int length)
|
bool test_if_int(const char *str,int length)
|
||||||
|
@ -417,99 +361,332 @@ void Field_decimal::overflow(bool negative)
|
||||||
|
|
||||||
void Field_decimal::store(const char *from,uint len)
|
void Field_decimal::store(const char *from,uint len)
|
||||||
{
|
{
|
||||||
reg3 int i;
|
const char *end= from+len;
|
||||||
uint tmp_dec;
|
/* The pointer where the field value starts (i.e., "where to write") */
|
||||||
char fyllchar;
|
char *to=ptr;
|
||||||
const char *end=from+len;
|
uint tmp_dec, tmp_uint;
|
||||||
struct st_decstr decstr;
|
/*
|
||||||
bool error;
|
The sign of the number : will be 0 (means positive but sign not
|
||||||
|
specified), '+' or '-'
|
||||||
|
*/
|
||||||
|
char sign_char=0;
|
||||||
|
/* The pointers where prezeros start and stop */
|
||||||
|
const char *pre_zeros_from, *pre_zeros_end;
|
||||||
|
/* The pointers where digits at the left of '.' start and stop */
|
||||||
|
const char *int_digits_from, *int_digits_end;
|
||||||
|
/* The pointers where digits at the right of '.' start and stop */
|
||||||
|
const char *frac_digits_from, *frac_digits_end;
|
||||||
|
/* The sign of the exponent : will be 0 (means no exponent), '+' or '-' */
|
||||||
|
char expo_sign_char=0;
|
||||||
|
uint exponent=0; // value of the exponent
|
||||||
|
/*
|
||||||
|
Pointers used when digits move from the left of the '.' to the
|
||||||
|
right of the '.' (explained below)
|
||||||
|
*/
|
||||||
|
const char *int_digits_tail_from;
|
||||||
|
/* Number of 0 that need to be added at the left of the '.' (1E3: 3 zeros) */
|
||||||
|
uint int_digits_added_zeros;
|
||||||
|
/*
|
||||||
|
Pointer used when digits move from the right of the '.' to the left
|
||||||
|
of the '.'
|
||||||
|
*/
|
||||||
|
const char *frac_digits_head_end;
|
||||||
|
/* Number of 0 that need to be added at the right of the '.' (for 1E-3) */
|
||||||
|
uint frac_digits_added_zeros;
|
||||||
|
char *pos,*tmp_left_pos,*tmp_right_pos;
|
||||||
|
/* Pointers that are used as limits (begin and end of the field buffer) */
|
||||||
|
char *left_wall,*right_wall;
|
||||||
|
char tmp_char;
|
||||||
|
/*
|
||||||
|
To remember if current_thd->cuted_fields has already been incremented,
|
||||||
|
to do that only once
|
||||||
|
*/
|
||||||
|
bool is_cuted_fields_incr=0;
|
||||||
|
|
||||||
if ((tmp_dec= dec))
|
LINT_INIT(int_digits_tail_from);
|
||||||
tmp_dec++; // Calculate pos of '.'
|
LINT_INIT(int_digits_added_zeros);
|
||||||
while (from != end && isspace(*from))
|
LINT_INIT(frac_digits_head_end);
|
||||||
from++;
|
LINT_INIT(frac_digits_added_zeros);
|
||||||
if (zerofill)
|
|
||||||
|
/*
|
||||||
|
There are three steps in this function :
|
||||||
|
- parse the input string
|
||||||
|
- modify the position of digits around the decimal dot '.'
|
||||||
|
according to the exponent value (if specified)
|
||||||
|
- write the formatted number
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((tmp_dec=dec))
|
||||||
|
tmp_dec++;
|
||||||
|
|
||||||
|
for (; from!=end && isspace(*from); from++) ; // Read spaces
|
||||||
|
if (from == end)
|
||||||
{
|
{
|
||||||
fyllchar = '0';
|
current_thd->cuted_fields++;
|
||||||
if (from != end)
|
is_cuted_fields_incr=1;
|
||||||
while (*from == '0' && from != end-1) // Skip prezero
|
|
||||||
from++;
|
|
||||||
}
|
}
|
||||||
else
|
else if (*from == '+' || *from == '-') // Found some sign ?
|
||||||
fyllchar=' ';
|
|
||||||
error=number_dec(&decstr,from,end);
|
|
||||||
if (decstr.sign)
|
|
||||||
{
|
{
|
||||||
from++;
|
sign_char= *from++;
|
||||||
if (unsigned_flag) // No sign with zerofill
|
/*
|
||||||
{
|
Unsigned can't have any flag. So we'll just drop "+"
|
||||||
if (decstr.sign_char == '+') // just remove "+"
|
and will overflow on "-"
|
||||||
decstr.sign= 0;
|
*/
|
||||||
else
|
if (unsigned_flag)
|
||||||
|
{
|
||||||
|
if (sign_char=='-')
|
||||||
{
|
{
|
||||||
if (!error)
|
current_thd->cuted_fields++;
|
||||||
current_thd->cuted_fields++;
|
Field_decimal::overflow(1);
|
||||||
Field_decimal::overflow(1);
|
return;
|
||||||
return;
|
}
|
||||||
|
else
|
||||||
|
sign_char=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
pre_zeros_from= from;
|
||||||
|
for (; from!=end && *from == '0'; from++) ; // Read prezeros
|
||||||
|
pre_zeros_end=int_digits_from=from;
|
||||||
|
/* Read non zero digits at the left of '.'*/
|
||||||
|
for (; from!=end && isdigit(*from);from++) ;
|
||||||
|
int_digits_end=from;
|
||||||
|
if (from!=end && *from == '.') // Some '.' ?
|
||||||
|
from++;
|
||||||
|
frac_digits_from= from;
|
||||||
|
/* Read digits at the right of '.' */
|
||||||
|
for (;from!=end && isdigit(*from); from++) ;
|
||||||
|
frac_digits_end=from;
|
||||||
|
// Some exponentiation symbol ?
|
||||||
|
if (from != end && (*from == 'e' || *from == 'E'))
|
||||||
|
{
|
||||||
|
from++;
|
||||||
|
if (from != end && (*from == '+' || *from == '-')) // Some exponent sign ?
|
||||||
|
expo_sign_char= *from++;
|
||||||
|
else
|
||||||
|
expo_sign_char= '+';
|
||||||
|
/*
|
||||||
|
Read digits of the exponent and compute its value
|
||||||
|
'exponent' overflow (e.g. if 1E10000000000000000) is not a problem
|
||||||
|
(the value of the field will be overflow anyway, or 0 anyway,
|
||||||
|
it does not change anything if the exponent is 2^32 or more
|
||||||
|
*/
|
||||||
|
for (;from!=end && isdigit(*from); from++)
|
||||||
|
exponent=10*exponent+(*from-'0');
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
We only have to generate warnings if count_cuted_fields is set.
|
||||||
|
This is to avoid extra checks of the number when they are not needed.
|
||||||
|
Even if this flag is not set, it's ok to increment warnings, if
|
||||||
|
it makes the code easer to read.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (current_thd->count_cuted_fields)
|
||||||
|
{
|
||||||
|
for (;from!=end && isspace(*from); from++) ; // Read end spaces
|
||||||
|
if (from != end) // If still something left, warn
|
||||||
|
{
|
||||||
|
current_thd->cuted_fields++;
|
||||||
|
is_cuted_fields_incr=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Now "move" digits around the decimal dot according to the exponent value,
|
||||||
|
and add necessary zeros.
|
||||||
|
Examples :
|
||||||
|
- 1E+3 : needs 3 more zeros at the left of '.' (int_digits_added_zeros=3)
|
||||||
|
- 1E-3 : '1' moves at the right of '.', and 2 more zeros are needed
|
||||||
|
between '.' and '1'
|
||||||
|
- 1234.5E-3 : '234' moves at the right of '.'
|
||||||
|
These moves are implemented with pointers which point at the begin
|
||||||
|
and end of each moved segment. Examples :
|
||||||
|
- 1234.5E-3 : before the code below is executed, the int_digits part is
|
||||||
|
from '1' to '4' and the frac_digits part from '5' to '5'. After the code
|
||||||
|
below, the int_digits part is from '1' to '1', the frac_digits_head
|
||||||
|
part is from '2' to '4', and the frac_digits part from '5' to '5'.
|
||||||
|
- 1234.5E3 : before the code below is executed, the int_digits part is
|
||||||
|
from '1' to '4' and the frac_digits part from '5' to '5'. After the code
|
||||||
|
below, the int_digits part is from '1' to '4', the int_digits_tail
|
||||||
|
part is from '5' to '5', the frac_digits part is empty, and
|
||||||
|
int_digits_added_zeros=2 (to make 1234500).
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!expo_sign_char)
|
||||||
|
tmp_uint=tmp_dec+(uint)(int_digits_end-int_digits_from);
|
||||||
|
else if (expo_sign_char == '-')
|
||||||
|
{
|
||||||
|
tmp_uint=min(exponent,(uint)(int_digits_end-int_digits_from));
|
||||||
|
frac_digits_added_zeros=exponent-tmp_uint;
|
||||||
|
int_digits_end -= tmp_uint;
|
||||||
|
frac_digits_head_end=int_digits_end+tmp_uint;
|
||||||
|
tmp_uint=tmp_dec+(uint)(int_digits_end-int_digits_from);
|
||||||
|
}
|
||||||
|
else // (expo_sign_char=='+')
|
||||||
|
{
|
||||||
|
tmp_uint=min(exponent,(uint)(frac_digits_end-frac_digits_from));
|
||||||
|
int_digits_added_zeros=exponent-tmp_uint;
|
||||||
|
int_digits_tail_from=frac_digits_from;
|
||||||
|
frac_digits_from=frac_digits_from+tmp_uint;
|
||||||
|
/*
|
||||||
|
We "eat" the heading zeros of the
|
||||||
|
int_digits.int_digits_tail.int_digits_added_zeros concatenation
|
||||||
|
(for example 0.003e3 must become 3 and not 0003)
|
||||||
|
*/
|
||||||
|
if (int_digits_from == int_digits_end)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
There was nothing in the int_digits part, so continue
|
||||||
|
eating int_digits_tail zeros
|
||||||
|
*/
|
||||||
|
for (; int_digits_tail_from != frac_digits_from &&
|
||||||
|
*int_digits_tail_from == '0'; int_digits_tail_from++) ;
|
||||||
|
if (int_digits_tail_from == frac_digits_from)
|
||||||
|
{
|
||||||
|
// there were only zeros in int_digits_tail too
|
||||||
|
int_digits_added_zeros=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
tmp_uint=(tmp_dec+(uint)(int_digits_end-int_digits_from)
|
||||||
|
+(uint)(frac_digits_from-int_digits_tail_from)+
|
||||||
|
int_digits_added_zeros);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Remove pre-zeros if too big number
|
Now write the formated number
|
||||||
|
|
||||||
|
First the digits of the int_% parts.
|
||||||
|
Do we have enough room to write these digits ?
|
||||||
|
If the sign is defined and '-', we need one position for it
|
||||||
*/
|
*/
|
||||||
for (i= (int) (decstr.nr_length+decstr.extra -(field_length-tmp_dec)+
|
|
||||||
decstr.sign) ;
|
if (field_length < tmp_uint + (int) (sign_char == '-'))
|
||||||
i > 0 ;
|
|
||||||
i--)
|
|
||||||
{
|
{
|
||||||
if (*from == '0')
|
|
||||||
{
|
|
||||||
from++;
|
|
||||||
decstr.nr_length--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (decstr.sign && decstr.sign_char == '+' && i == 1)
|
|
||||||
{ // Remove pre '+'
|
|
||||||
decstr.sign=0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
current_thd->cuted_fields++;
|
current_thd->cuted_fields++;
|
||||||
// too big number, change to max or min number
|
// too big number, change to max or min number
|
||||||
Field_decimal::overflow(decstr.sign && decstr.sign_char == '-');
|
Field_decimal::overflow(sign_char == '-');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
char *to=ptr;
|
|
||||||
for (i=(int) (field_length-tmp_dec-decstr.nr_length-decstr.extra - decstr.sign) ;
|
/*
|
||||||
i-- > 0 ;)
|
Tmp_left_pos is the position where the leftmost digit of
|
||||||
*to++ = fyllchar;
|
the int_% parts will be written
|
||||||
if (decstr.sign)
|
*/
|
||||||
*to++= decstr.sign_char;
|
tmp_left_pos=pos=to+(uint)(field_length-tmp_uint);
|
||||||
if (decstr.extra)
|
|
||||||
*to++ = '0';
|
// Write all digits of the int_% parts
|
||||||
for (i=(int) decstr.nr_length ; i-- > 0 ; )
|
while (int_digits_from != int_digits_end)
|
||||||
*to++ = *from++;
|
*pos++ = *int_digits_from++ ;
|
||||||
if (tmp_dec--)
|
|
||||||
{
|
if (expo_sign_char == '+')
|
||||||
*to++ ='.';
|
{
|
||||||
if (decstr.nr_dec) from++; // Skip '.'
|
while (int_digits_tail_from != frac_digits_from)
|
||||||
for (i=(int) min(decstr.nr_dec,tmp_dec) ; i-- > 0 ; ) *to++ = *from++;
|
*pos++= *int_digits_tail_from++;
|
||||||
for (i=(int) (tmp_dec-min(decstr.nr_dec,tmp_dec)) ; i-- > 0 ; ) *to++ = '0';
|
while (int_digits_added_zeros-- >0)
|
||||||
|
*pos++= '0';
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
Note the position where the rightmost digit of the int_% parts has been
|
||||||
|
written (this is to later check if the int_% parts contained nothing,
|
||||||
|
meaning an extra 0 is needed).
|
||||||
|
*/
|
||||||
|
tmp_right_pos=pos;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Check for incorrect string if in batch mode (ALTER TABLE/LOAD DATA...)
|
Step back to the position of the leftmost digit of the int_% parts,
|
||||||
|
to write sign and fill with zeros or blanks or prezeros.
|
||||||
*/
|
*/
|
||||||
if (!error && current_thd->count_cuted_fields && from != end)
|
pos=tmp_left_pos-1;
|
||||||
{ // Check if number was cuted
|
if (zerofill)
|
||||||
for (; from != end ; from++)
|
{
|
||||||
|
left_wall=to-1;
|
||||||
|
while (pos != left_wall) // Fill with zeros
|
||||||
|
*pos--='0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
left_wall=to+(sign_char!=0)-1;
|
||||||
|
if (!expo_sign_char) // If exponent was specified, ignore prezeros
|
||||||
{
|
{
|
||||||
if (*from != '0')
|
for (;pos != left_wall && pre_zeros_from !=pre_zeros_end;
|
||||||
|
pre_zeros_from++)
|
||||||
|
*pos--= '0';
|
||||||
|
}
|
||||||
|
if (pos == tmp_right_pos-1)
|
||||||
|
*pos--= '0'; // no 0 has ever been written, so write one
|
||||||
|
left_wall= to-1;
|
||||||
|
if (sign_char && pos != left_wall)
|
||||||
|
{
|
||||||
|
/* Write sign if possible (it is if sign is '-') */
|
||||||
|
*pos--= sign_char;
|
||||||
|
}
|
||||||
|
while (pos != left_wall)
|
||||||
|
*pos--=' '; //fill with blanks
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmp_dec) // This field has decimals
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Write digits of the frac_% parts ;
|
||||||
|
Depending on current_thd->count_cutted_fields, we may also want
|
||||||
|
to know if some non-zero tail of these parts will
|
||||||
|
be truncated (for example, 0.002->0.00 will generate a warning,
|
||||||
|
while 0.000->0.00 will not)
|
||||||
|
(and 0E1000000000 will not, while 1E-1000000000 will)
|
||||||
|
*/
|
||||||
|
|
||||||
|
pos=to+(uint)(field_length-tmp_dec); // Calculate post to '.'
|
||||||
|
*pos++='.';
|
||||||
|
right_wall=to+field_length;
|
||||||
|
|
||||||
|
if (expo_sign_char == '-')
|
||||||
|
{
|
||||||
|
while (frac_digits_added_zeros-- > 0)
|
||||||
{
|
{
|
||||||
if (!isspace(*from)) // Space is ok
|
if (pos == right_wall)
|
||||||
current_thd->cuted_fields++;
|
{
|
||||||
break;
|
if (current_thd->count_cuted_fields && !is_cuted_fields_incr)
|
||||||
|
break; // Go on below to see if we lose non zero digits
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*pos++='0';
|
||||||
|
}
|
||||||
|
while (int_digits_end != frac_digits_head_end)
|
||||||
|
{
|
||||||
|
tmp_char= *int_digits_end++;
|
||||||
|
if (pos == right_wall)
|
||||||
|
{
|
||||||
|
if (tmp_char != '0') // Losing a non zero digit ?
|
||||||
|
{
|
||||||
|
if (current_thd->count_cuted_fields && !is_cuted_fields_incr)
|
||||||
|
current_thd->cuted_fields++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*pos++= tmp_char;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (;frac_digits_from!=frac_digits_end;)
|
||||||
|
{
|
||||||
|
tmp_char= *frac_digits_from++;
|
||||||
|
if (pos == right_wall)
|
||||||
|
{
|
||||||
|
if (tmp_char != '0') // Losing a non zero digit ?
|
||||||
|
{
|
||||||
|
if (!is_cuted_fields_incr)
|
||||||
|
current_thd->cuted_fields++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*pos++= tmp_char;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (pos != right_wall)
|
||||||
|
*pos++='0'; // Fill with zeros at right of '.'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -522,6 +699,14 @@ void Field_decimal::store(double nr)
|
||||||
current_thd->cuted_fields++;
|
current_thd->cuted_fields++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isinf(nr)) // Handle infinity as special case
|
||||||
|
{
|
||||||
|
overflow(nr < 0.0);
|
||||||
|
current_thd->cuted_fields++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
reg4 uint i,length;
|
reg4 uint i,length;
|
||||||
char fyllchar,*to;
|
char fyllchar,*to;
|
||||||
char buff[320];
|
char buff[320];
|
||||||
|
|
Loading…
Reference in a new issue