Commit 218e00ac authored by monty@mysql.com's avatar monty@mysql.com

Fixed BUILD script to use --with-berkeley-db instead of --with-bdb

Lots of small fixes to multi-precision-math path
Give Note for '123.4e'
Added helper functions type 'val_string_from_real()
Don't give warnings for end space for string2decimal()
Changed storage of values for SP so that we can detect length of argument without strlen()
Changed interface for str2dec() so that we must supple the pointer to the last character in the buffer
parent 7bc48798
......@@ -48,8 +48,8 @@ global_warnings="-Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wch
c_warnings="$global_warnings -Wunused"
cxx_warnings="$global_warnings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor"
base_max_configs="--with-innodb --with-bdb --with-ndbcluster --with-archive-storage-engine --with-raid --with-openssl --with-raid --with-vio"
max_leave_isam_configs="--with-innodb --with-bdb --with-ndbcluster --with-archive-storage-engine --with-federated-storage-engine --with-raid --with-openssl --with-raid --with-vio --with-embedded-server"
base_max_configs="--with-innodb --with-berkeley-db --with-ndbcluster --with-archive-storage-engine --with-raid --with-openssl --with-raid --with-vio"
max_leave_isam_configs="--with-innodb --with-berkeley-db --with-ndbcluster --with-archive-storage-engine --with-federated-storage-engine --with-raid --with-openssl --with-raid --with-vio --with-embedded-server"
max_no_es_configs="$max_leave_isam_configs --without-isam"
max_configs="$max_no_es_configs --with-embedded-server"
......
......@@ -17,7 +17,9 @@
#ifndef _decimal_h
#define _decimal_h
typedef enum {TRUNCATE=0, HALF_EVEN, HALF_UP, CEILING, FLOOR} decimal_round_mode;
typedef enum
{TRUNCATE=0, HALF_EVEN, HALF_UP, CEILING, FLOOR}
decimal_round_mode;
typedef int32 decimal_digit;
typedef struct st_decimal {
......@@ -26,11 +28,10 @@ typedef struct st_decimal {
decimal_digit *buf;
} decimal;
int internal_str2dec(const char *from, decimal *to, char **end, my_bool fixed);
int decimal2string(decimal *from, char *to, int *to_len,
int fixed_precision, int fixed_decimals,
char filler);
int string2decimal(char *from, decimal *to, char **end);
int string2decimal_fixed(char *from, decimal *to, char **end);
int decimal2ulonglong(decimal *from, ulonglong *to);
int ulonglong2decimal(ulonglong from, decimal *to);
int decimal2longlong(decimal *from, longlong *to);
......@@ -51,10 +52,14 @@ int decimal_cmp(decimal *from1, decimal *from2);
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);
int decimal_round(decimal *from, decimal *to, int new_scale,
decimal_round_mode mode);
int decimal_is_zero(decimal *from);
void max_decimal(int precision, int frac, decimal *to);
#define string2decimal(A,B,C) internal_str2dec((A), (B), (C), 0)
#define string2decimal_fixed(A,B,C) internal_str2dec((A), (B), (C), 1)
/* set a decimal to zero */
#define decimal_make_zero(dec) do { \
......
......@@ -90,6 +90,26 @@ id avg(rating)
1 3.0000
2 NULL
3 2.0000
select sql_small_result t2.id, avg(rating) from t2 group by t2.id;
id avg(rating)
1 3.0000
2 NULL
3 2.0000
select sql_big_result t2.id, avg(rating) from t2 group by t2.id;
id avg(rating)
1 3.0000
2 NULL
3 2.0000
select sql_small_result t2.id, avg(rating+0.0e0) from t2 group by t2.id;
id avg(rating+0.0e0)
1 3
2 NULL
3 2
select sql_big_result t2.id, avg(rating+0.0e0) from t2 group by t2.id;
id avg(rating+0.0e0)
1 3
2 NULL
3 2
drop table t1,t2;
create table t1 (a smallint(6) primary key, c char(10), b text);
INSERT INTO t1 VALUES (1,'1','1');
......
......@@ -30,6 +30,12 @@ Y-N-N-Y-N Y,N,N,Y,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,
select elt(2,1),field(NULL,"a","b","c");
elt(2,1) field(NULL,"a","b","c")
NULL 0
select field("b","a",NULL),field(1,0,NULL)+0,field(1.0,0.0,NULL)+0.0,field(1.0e1,0.0e1,NULL)+0.0e1;
field("b","a",NULL) field(1,0,NULL)+0 field(1.0,0.0,NULL)+0.0 field(1.0e1,0.0e1,NULL)+0.0e1
0 0 0.0 0
select field(NULL,"a",NULL),field(NULL,0,NULL)+0,field(NULL,0.0,NULL)+0.0,field(NULL,0.0e1,NULL)+0.0e1;
field(NULL,"a",NULL) field(NULL,0,NULL)+0 field(NULL,0.0,NULL)+0.0 field(NULL,0.0e1,NULL)+0.0e1
0 0 0.0 0
select find_in_set("","a,b,c"),find_in_set("","a,b,c,"),find_in_set("",",a,b,c");
find_in_set("","a,b,c") find_in_set("","a,b,c,") find_in_set("",",a,b,c")
0 4 1
......
......@@ -2674,7 +2674,6 @@ Warning 1265 Data truncated for column 'c4' at row 1
Warning 1265 Data truncated for column 'c5' at row 1
Warning 1265 Data truncated for column 'c6' at row 1
Warning 1264 Out of range value adjusted for column 'c7' at row 1
Note 1265 Data truncated for column 'c12' at row 1
Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 1
......@@ -2725,7 +2724,6 @@ Warning 1265 Data truncated for column 'c4' at row 1
Warning 1265 Data truncated for column 'c5' at row 1
Warning 1265 Data truncated for column 'c6' at row 1
Warning 1264 Out of range value adjusted for column 'c7' at row 1
Note 1265 Data truncated for column 'c12' at row 1
Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -1
......
......@@ -169,8 +169,19 @@ Warnings:
Warning 1264 Out of range value adjusted for column 'a' at row 1
Note 1265 Data truncated for column 'a' at row 2
Warning 1264 Out of range value adjusted for column 'a' at row 3
insert into t1 values ("1e+4294967296"),("1e-4294967296");
Warnings:
Warning 1264 Out of range value adjusted for column 'a' at row 1
Note 1265 Data truncated for column 'a' at row 2
insert into t1 values ("1e+18446744073709551615"),("1e+18446744073709551616"),("1e-9223372036854775807"),("1e-9223372036854775809");
Warnings:
Warning 1264 Out of range value adjusted for column 'a' at row 1
Warning 1366 Incorrect decimal value: '1e+18446744073709551616' for column 'a' at row 2
Note 1265 Data truncated for column 'a' at row 3
Warning 1366 Incorrect decimal value: '1e-9223372036854775809' for column 'a' at row 4
insert into t1 values ("123.4e"),("123.4e+2"),("123.4e-2"),("123e1"),("123e+0");
Warnings:
Note 1265 Data truncated for column 'a' at row 1
Note 1265 Data truncated for column 'a' at row 3
select * from t1;
a
......@@ -195,6 +206,12 @@ a
99999999.99
0.00
-99999999.99
99999999.99
0.00
99999999.99
0.00
0.00
0.00
123.40
12340.00
1.23
......@@ -229,6 +246,7 @@ Note 1265 Data truncated for column 'a' at row 2
Warning 1264 Out of range value adjusted for column 'a' at row 3
insert into t1 values ("123.4e"),("123.4e+2"),("123.4e-2"),("123e1"),("123e+0");
Warnings:
Note 1265 Data truncated for column 'a' at row 1
Note 1265 Data truncated for column 'a' at row 3
select * from t1;
a
......@@ -287,6 +305,7 @@ Note 1265 Data truncated for column 'a' at row 2
Warning 1264 Out of range value adjusted for column 'a' at row 3
insert into t1 values ("123.4e"),("123.4e+2"),("123.4e-2"),("123e1"),("123e+0");
Warnings:
Note 1265 Data truncated for column 'a' at row 1
Note 1265 Data truncated for column 'a' at row 3
select * from t1;
a
......@@ -338,6 +357,7 @@ Warning 1264 Out of range value adjusted for column 'a' at row 3
insert into t1 values (123.4e0),(123.4e+2),(123.4e-2),(123e1),(123e+0);
Warnings:
Note 1265 Data truncated for column 'a' at row 3
insert into t1 values (MID("987",1,2)),("987 "),("987.6e+2 ");
select * from t1;
a
0.00
......@@ -366,6 +386,9 @@ a
1.23
1230.00
123.00
98.00
987.00
98760.00
drop table t1;
create table t1 (a decimal);
insert into t1 values (-99999999999999),(-1),('+1'),('01'),('+00000000000001'),('+12345678901'),(99999999999999);
......
......@@ -696,7 +696,7 @@ end while; select v1, v2, v3 * 0.000000000001, v4 * 0.000000000001; end;//
call p1()//
#
v1 v2 v3 * 0.000000000001 v4 * 0.000000000001
1.000000100000 1.999999900000 1.000000100000000000 1.999999900000000000
1.000000100000 1.999999900000 1.000000100000 1.999999900000
drop procedure p1;
drop table if exists t1;
Warnings:
......
......@@ -58,6 +58,11 @@ create table t2 (id int not null,rating int null);
insert into t1 values(1),(2),(3);
insert into t2 values(1, 3),(2, NULL),(2, NULL),(3, 2),(3, NULL);
select t1.id, avg(rating) from t1 left join t2 on ( t1.id = t2.id ) group by t1.id;
# Test different types with avg()
select sql_small_result t2.id, avg(rating) from t2 group by t2.id;
select sql_big_result t2.id, avg(rating) from t2 group by t2.id;
select sql_small_result t2.id, avg(rating+0.0e0) from t2 group by t2.id;
select sql_big_result t2.id, avg(rating+0.0e0) from t2 group by t2.id;
drop table t1,t2;
#
......
......@@ -18,6 +18,8 @@ select export_set(9,"Y","N","-",5),export_set(9,"Y","N"),export_set(9,"Y","N",""
# Wrong usage of functions
#
select elt(2,1),field(NULL,"a","b","c");
select field("b","a",NULL),field(1,0,NULL)+0,field(1.0,0.0,NULL)+0.0,field(1.0e1,0.0e1,NULL)+0.0e1;
select field(NULL,"a",NULL),field(NULL,0,NULL)+0,field(NULL,0.0,NULL)+0.0,field(NULL,0.0e1,NULL)+0.0e1;
select find_in_set("","a,b,c"),find_in_set("","a,b,c,"),find_in_set("",",a,b,c");
select find_in_set("abc","abc"),find_in_set("ab","abc"),find_in_set("abcd","abc");
select interval(null, 1, 10, 100);
......
......@@ -165,6 +165,8 @@ insert into t1 values ("00000000000001"),("+0000000000001"),("-0000000000001");
insert into t1 values ("+111111111.11"),("111111111.11"),("-11111111.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 ("1e+4294967296"),("1e-4294967296");
insert into t1 values ("1e+18446744073709551615"),("1e+18446744073709551616"),("1e-9223372036854775807"),("1e-9223372036854775809");
insert into t1 values ("123.4e"),("123.4e+2"),("123.4e-2"),("123e1"),("123e+0");
select * from t1;
drop table t1;
......@@ -201,6 +203,7 @@ insert into t1 values (+111111111.11),(111111111.11),(-11111111.11);
insert into t1 values (-111111111.11),(+1111111111.11),(1111111111.11);
insert into t1 values (1e+100),(1e-100),(-1e+100);
insert into t1 values (123.4e0),(123.4e+2),(123.4e-2),(123e1),(123e+0);
insert into t1 values (MID("987",1,2)),("987 "),("987.6e+2 ");
select * from t1;
drop table t1;
......
......@@ -73,6 +73,99 @@ bool Item::val_bool()
}
String *Item::val_string_from_real(String *str)
{
double nr= val_real();
if (null_value)
return 0; /* purecov: inspected */
str->set(nr,decimals, &my_charset_bin);
return str;
}
String *Item::val_string_from_int(String *str)
{
longlong nr= val_int();
if (null_value)
return 0;
if (unsigned_flag)
str->set((ulonglong) nr, &my_charset_bin);
else
str->set(nr, &my_charset_bin);
return str;
}
String *Item::val_string_from_decimal(String *str)
{
my_decimal dec_buf, *dec= val_decimal(&dec_buf);
if (null_value)
return 0;
my_decimal_round(E_DEC_FATAL_ERROR, dec, decimals, FALSE, &dec_buf);
my_decimal2string(E_DEC_FATAL_ERROR, &dec_buf, 0, 0, 0, str);
return str;
}
my_decimal *Item::val_decimal_from_real(my_decimal *decimal_value)
{
double nr= val_real();
if (null_value)
return 0;
double2my_decimal(E_DEC_FATAL_ERROR, nr, decimal_value);
return (decimal_value);
}
my_decimal *Item::val_decimal_from_int(my_decimal *decimal_value)
{
longlong nr= val_int();
if (null_value)
return 0;
int2my_decimal(E_DEC_FATAL_ERROR, nr, unsigned_flag, decimal_value);
return decimal_value;
}
my_decimal *Item::val_decimal_from_string(my_decimal *decimal_value)
{
String *res;
char *end_ptr;
int error;
if (!(res= val_str(&str_value)))
return 0; // NULL or EOM
end_ptr= (char*) res->ptr()+ res->length();
str2my_decimal(E_DEC_FATAL_ERROR, res->ptr(), res->length(), res->charset(),
decimal_value);
return decimal_value;
}
double Item::val_real_from_decimal()
{
/* Note that fix_fields may not be called for Item_avg_field items */
double result;
my_decimal value_buff, *dec_val= val_decimal(&value_buff);
if (null_value)
return 0.0;
my_decimal2double(E_DEC_FATAL_ERROR, dec_val, &result);
return result;
}
longlong Item::val_int_from_decimal()
{
/* Note that fix_fields may not be called for Item_avg_field items */
longlong result;
my_decimal value, *dec_val= val_decimal(&value);
if (null_value)
return 0;
my_decimal2int(E_DEC_FATAL_ERROR, dec_val, unsigned_flag, &result);
return result;
}
Item::Item():
name(0), orig_name(0), name_length(0), fixed(0),
collation(&my_charset_bin, DERIVATION_COERCIBLE)
......@@ -1376,11 +1469,14 @@ void Item_param::set_double(double d)
binary protocol, we use str2my_decimal to convert it to
internal decimal value.
*/
void Item_param::set_decimal(const char *str, ulong length)
{
char *end;
DBUG_ENTER("Item_param::set_decimal");
str2my_decimal(E_DEC_FATAL_ERROR, str, &decimal_value);
end= (char*) str+length;
str2my_decimal(E_DEC_FATAL_ERROR, str, &decimal_value, &end);
state= DECIMAL_VALUE;
decimals= decimal_value.frac;
max_length= decimal_value.intg + decimals + 2;
......@@ -3012,6 +3108,29 @@ Item_num *Item_uint::neg()
}
static uint nr_of_decimals(const char *str, const char *end)
{
const char *decimal_point;
/* Find position for '.' */
for (;;)
{
if (str == end)
return 0;
if (*str == 'e' || *str == 'E')
return NOT_FIXED_DEC;
if (*str++ == '.')
break;
}
decimal_point= str;
for (; my_isdigit(system_charset_info, *str) ; str++)
;
if (*str == 'e' || *str == 'E')
return NOT_FIXED_DEC;
return (uint) (str - decimal_point);
}
/*
This function is only called during parsing. We will signal an error if
value is not a true double value (overflow)
......@@ -3033,7 +3152,7 @@ Item_float::Item_float(const char *str_arg, uint length)
my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "double", (char*) str_arg);
}
presentation= name=(char*) str_arg;
decimals=(uint8) nr_of_decimals(str_arg);
decimals=(uint8) nr_of_decimals(str_arg, str_arg+length);
max_length=length;
fixed= 1;
}
......
......@@ -276,6 +276,16 @@ public:
TRUE value is true (not equal to 0)
*/
bool val_bool();
/* Helper functions, see item_sum.cc */
String *val_string_from_real(String *str);
String *val_string_from_int(String *str);
String *val_string_from_decimal(String *str);
my_decimal *val_decimal_from_real(my_decimal *decimal_value);
my_decimal *val_decimal_from_int(my_decimal *decimal_value);
my_decimal *val_decimal_from_string(my_decimal *decimal_value);
longlong val_int_from_decimal();
double val_real_from_decimal();
virtual Field *get_tmp_table_field() { return 0; }
virtual Field *tmp_table_field(TABLE *t_arg) { return 0; }
virtual const char *full_name() const { return name ? name : "???"; }
......
This diff is collapsed.
......@@ -357,18 +357,15 @@ public:
};
class Item_func_int_div :public Item_func
class Item_func_int_div :public Item_int_func
{
public:
Item_func_int_div(Item *a,Item *b) :Item_func(a,b)
Item_func_int_div(Item *a,Item *b) :Item_int_func(a,b)
{}
double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
longlong val_int();
String *val_str(String*str);
const char *func_name() const { return "DIV"; }
void fix_length_and_dec();
void print(String *str) { print_op(str); }
enum Item_result result_type () const { return INT_RESULT; }
};
......@@ -384,23 +381,15 @@ public:
};
class Item_func_signproc :public Item_func_num1
{
public:
Item_func_signproc(Item *a) :Item_func_num1(a) {}
Item_func_signproc(Item *a, Item *b) :Item_func_num1(a, b) {}
void fix_length_and_dec();
};
class Item_func_neg :public Item_func_signproc
class Item_func_neg :public Item_func_num1
{
public:
Item_func_neg(Item *a) :Item_func_signproc(a) {}
Item_func_neg(Item *a) :Item_func_num1(a) {}
double real_op();
longlong int_op();
my_decimal *decimal_op(my_decimal *);
const char *func_name() const { return "-"; }
void fix_length_and_dec();
void fix_num_length_and_dec();
};
......
......@@ -47,19 +47,6 @@ static void my_coll_agg_error(DTCollation &c1, DTCollation &c2,
fname);
}
uint nr_of_decimals(const char *str)
{
if (strchr(str,'e') || strchr(str,'E'))
return NOT_FIXED_DEC;
if ((str=strchr(str,'.')))
{
const char *start= ++str;
for (; my_isdigit(system_charset_info,*str) ; str++) ;
return (uint) (str-start);
}
return 0;
}
double Item_str_func::val_real()
{
......
This diff is collapsed.
......@@ -78,7 +78,6 @@ public:
virtual void update_field()=0;
virtual bool keep_field_type(void) const { return 0; }
virtual void fix_length_and_dec() { maybe_null=1; null_value=1; }
my_decimal *val_decimal(my_decimal *);
virtual const char *func_name() const { return "?"; }
virtual Item *result_item(Field *field)
{ return new Item_field(field);}
......@@ -93,7 +92,6 @@ public:
virtual bool setup(THD *thd) {return 0;}
virtual void make_unique() {}
Item *get_tmp_table_item(THD *thd);
virtual int scale() { return decimals; }
virtual Field *create_tmp_field(bool group, TABLE *table,
uint convert_blob_length);
......@@ -129,6 +127,7 @@ public:
Item_sum_int(THD *thd, Item_sum_int *item) :Item_sum_num(thd, item) {}
double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
String *val_str(String*str);
my_decimal *val_decimal(my_decimal *);
enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec()
{ decimals=0; max_length=21; maybe_null=null_value=0; }
......@@ -176,6 +175,7 @@ class Item_sum_sum_distinct :public Item_sum_sum
Unique *tree;
byte *dec_bin_buff;
my_decimal tmp_dec;
uint key_length;
private:
Item_sum_sum_distinct(THD *thd, Item_sum_sum_distinct *item);
public:
......@@ -451,7 +451,9 @@ public:
Item_std_field(Item_sum_std *item);
enum Type type() const { return FIELD_STD_ITEM; }
double val_real();
my_decimal *val_decimal(my_decimal *);
enum Item_result result_type () const { return REAL_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE;}
};
/*
......@@ -472,6 +474,7 @@ class Item_sum_std :public Item_sum_variance
const char *func_name() const { return "std"; }
Item *copy_or_same(THD* thd);
enum Item_result result_type () const { return REAL_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE;}
};
// This class is a string or number function depending on num_func
......@@ -650,6 +653,7 @@ class Item_sum_udf_float :public Item_udf_sum
}
double val_real();
String *val_str(String*str);
my_decimal *val_decimal(my_decimal *);
void fix_length_and_dec() { fix_num_length_and_dec(); }
Item *copy_or_same(THD* thd);
};
......@@ -667,6 +671,7 @@ public:
double val_real()
{ DBUG_ASSERT(fixed == 1); return (double) Item_sum_udf_int::val_int(); }
String *val_str(String*str);
my_decimal *val_decimal(my_decimal *);
enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec() { decimals=0; max_length=21; }
Item *copy_or_same(THD* thd);
......@@ -697,11 +702,13 @@ public:
return res ? my_strntoll(res->charset(),res->ptr(),res->length(),10,
(char**) 0, &err_not_used) : (longlong) 0;
}
my_decimal *val_decimal(my_decimal *dec);
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec();
Item *copy_or_same(THD* thd);
};
class Item_sum_udf_decimal :public Item_udf_sum
{
public:
......@@ -864,6 +871,10 @@ class Item_func_group_concat : public Item_sum
end_ptr= (char*) res->ptr()+ res->length();
return my_strtoll10(res->ptr(), &end_ptr, &error);
}
my_decimal *val_decimal(my_decimal *decimal_value)
{
return val_decimal_from_string(decimal_value);
}
String* val_str(String* str);
Item *copy_or_same(THD* thd);
void no_rows_in_result() {}
......
......@@ -3281,7 +3281,7 @@ void User_var_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* las
bin2decimal(val+2, &dec, precision, scale);
decimal2string(&dec, str_buf, &str_len, 0, 0, 0);
str_buf[str_len]= 0;
fprintf(file, "%s",str_buf);
fprintf(file, ":=%s;\n",str_buf);
break;
}
case STRING_RESULT:
......
......@@ -13,6 +13,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysql_priv.h"
#ifndef MYSQL_CLIENT
......@@ -154,10 +155,11 @@ int my_decimal2binary(uint mask, const my_decimal *d, byte *bin, int prec,
E_DEC_BAD_NUM
E_DEC_OOM
*/
int str2my_decimal(uint mask, const char *from, uint length,
CHARSET_INFO *charset, my_decimal *decimal_value)
{
char *end;
char *end, *from_end;
int err;
char buff[STRING_BUFFER_USUAL_SIZE];
String tmp(buff, sizeof(buff), &my_charset_bin);
......@@ -169,10 +171,20 @@ int str2my_decimal(uint mask, const char *from, uint length,
length= tmp.length();
charset= &my_charset_bin;
}
my_decimal_set_zero(decimal_value);
from_end= end= (char*) from+length;
err= string2decimal((char *)from, (decimal *)decimal_value, &end);
if ((uint) (end-from) != length && !err)
err= E_DEC_TRUNCATED;
if (end != from_end && !err)
{
/* Give warining if there is something other than end space */
for ( ; end < from_end; end++)
{
if (!my_isspace(&my_charset_latin1, *end))
{
err= E_DEC_TRUNCATED;
break;
}
}
}
check_result(mask, err);
return err;
}
......@@ -200,12 +212,25 @@ print_decimal_buff(const my_decimal *dec, const byte* ptr, int length)
{
print_decimal(dec);
fprintf(DBUG_FILE, "Record: ");
for(int i= 0; i < length; i++)
for (int i= 0; i < length; i++)
{
fprintf(DBUG_FILE, "%02X ", (uint)((uchar *)ptr)[i]);
}
fprintf(DBUG_FILE, "\n");
}
void dbug_print_decimal(const char *tag, const char *format, my_decimal *val)
{
char buff[DECIMAL_MAX_STR_LENGTH];
String str(buff, sizeof(buff), &my_charset_bin);
if (!val)
str.set("NULL", 4, &my_charset_bin);
else
my_decimal2string(0, val, 0, 0, 0, &str);
DBUG_PRINT(tag, (format, val));
}
#endif
......
......@@ -68,10 +68,13 @@ inline uint my_decimal_size(uint precision, uint scale)
}
/* my_decimal class limits 'decimal' type to what we need in MySQL */
/* It internally all necessary space iside the instance so no extra */
/* memory is needed. One should call fix_buffer_pointer() function */
/* when he moves my_decimal objects in memory */
/*
my_decimal class limits 'decimal' type to what we need in MySQL
It contains internally all necessary space needed by the instance so
no extra memory is needed. One should call fix_buffer_pointer() function
when he moves my_decimal objects in memory
*/
class my_decimal :public decimal
{
decimal_digit buffer[DECIMAL_BUFF_LENGTH];
......@@ -83,6 +86,7 @@ public:
len= DECIMAL_BUFF_LENGTH;
buf= buffer;
#if !defined(HAVE_purify) && !defined(DBUG_OFF)
/* Set buffer to 'random' value to find wrong buffer usage */
for (uint i= 0; i < DECIMAL_BUFF_LENGTH; i++)
buffer[i]= i;
#endif
......@@ -101,6 +105,9 @@ public:
#ifndef DBUG_OFF
void print_decimal(const my_decimal *dec);
void print_decimal_buff(const my_decimal *dec, const byte* ptr, int length);
void dbug_print_decimal(const char *tag, const char *format, my_decimal *val);
#else
#define dbug_print_decimal(A,B,C)
#endif
#ifndef MYSQL_CLIENT
......@@ -158,7 +165,7 @@ inline
int binary2my_decimal(uint mask, const byte *bin, my_decimal *d, int prec,
int scale)
{
return check_result(mask, bin2decimal((char *)bin, (decimal *)d, prec,
return check_result(mask, bin2decimal((char *)bin, (decimal*) d, prec,
scale));
}
......@@ -166,7 +173,7 @@ int binary2my_decimal(uint mask, const byte *bin, my_decimal *d, int prec,
inline
int my_decimal_set_zero(my_decimal *d)
{
decimal_make_zero(((decimal *)d));
decimal_make_zero(((decimal*) d));
return 0;
}
......@@ -174,7 +181,7 @@ int my_decimal_set_zero(my_decimal *d)
inline
bool my_decimal_is_zero(const my_decimal *decimal_value)
{
return decimal_is_zero((decimal *)decimal_value);
return decimal_is_zero((decimal*) decimal_value);
}
......@@ -182,7 +189,7 @@ inline
int my_decimal_round(uint mask, const my_decimal *from, int scale,
bool truncate, my_decimal *to)
{
return check_result(mask, decimal_round((decimal *)from, to, scale,
return check_result(mask, decimal_round((decimal*) from, to, scale,
(truncate ? TRUNCATE : HALF_UP)));
}
......@@ -190,14 +197,14 @@ int my_decimal_round(uint mask, const my_decimal *from, int scale,
inline
int my_decimal_floor(uint mask, const my_decimal *from, my_decimal *to)
{
return check_result(mask, decimal_round((decimal *)from, to, 0, FLOOR));
return check_result(mask, decimal_round((decimal*) from, to, 0, FLOOR));
}
inline
int my_decimal_ceiling(uint mask, const my_decimal *from, my_decimal *to)
{
return check_result(mask, decimal_round((decimal *)from, to, 0, CEILING));
return check_result(mask, decimal_round((decimal*) from, to, 0, CEILING));
}
......@@ -222,17 +229,15 @@ int my_decimal2int(uint mask, const my_decimal *d, my_bool unsigned_flag,
inline
int my_decimal2double(uint mask, const my_decimal *d, double *result)
{
return check_result(mask, decimal2double((decimal *)d, result));
/* No need to call check_result as this will always succeed */
return decimal2double((decimal*) d, result);
}
inline
int str2my_decimal(uint mask, const char *str, my_decimal *d,
char **end= 0)
int str2my_decimal(uint mask, const char *str, my_decimal *d, char **end)
{
/* set it to 0 to avoid junk in value in case of error of conversion */
my_decimal_set_zero(d);
return check_result(mask, string2decimal((char *)str, (decimal *)d, end));
return check_result(mask, string2decimal(str, (decimal*) d, end));
}
......@@ -252,7 +257,7 @@ int string2my_decimal(uint mask, const String *str, my_decimal *d)
inline
int double2my_decimal(uint mask, double val, my_decimal *d)
{
return check_result(mask, double2decimal(val, (decimal *)d));
return check_result(mask, double2decimal(val, (decimal*) d));
}
......@@ -266,10 +271,9 @@ int int2my_decimal(uint mask, longlong i, my_bool unsigned_flag, my_decimal *d)
inline
int my_decimal_neg(st_decimal *arg)
void my_decimal_neg(st_decimal *arg)
{
decimal_neg(arg);
return 0;
}
......@@ -277,7 +281,7 @@ inline
int my_decimal_add(uint mask, my_decimal *res, const my_decimal *a,
const my_decimal *b)
{
return check_result(mask, decimal_add((decimal *)a, (decimal *)b, res));
return check_result(mask, decimal_add((decimal*) a, (decimal*) b, res));
}
......@@ -285,7 +289,7 @@ inline
int my_decimal_sub(uint mask, my_decimal *res, const my_decimal *a,
const my_decimal *b)
{
return check_result(mask, decimal_sub((decimal *)a, (decimal *)b, res));
return check_result(mask, decimal_sub((decimal*) a, (decimal*) b, res));
}
......@@ -293,7 +297,7 @@ inline
int my_decimal_mul(uint mask, my_decimal *res, const my_decimal *a,
const my_decimal *b)
{
return check_result(mask, decimal_mul((decimal *)a, (decimal *)b, res));
return check_result(mask, decimal_mul((decimal*) a, (decimal*) b, res));
}
......@@ -301,7 +305,7 @@ inline
int my_decimal_div(uint mask, my_decimal *res, const my_decimal *a,
const my_decimal *b, int div_scale_inc)
{
return check_result(mask, decimal_div((decimal *)a, (decimal *)b, res,
return check_result(mask, decimal_div((decimal*) a, (decimal*) b, res,
div_scale_inc));
}
......@@ -310,7 +314,7 @@ inline
int my_decimal_mod(uint mask, my_decimal *res, const my_decimal *a,
const my_decimal *b)
{
return check_result(mask, decimal_mod((decimal *)a, (decimal *)b, res));
return check_result(mask, decimal_mod((decimal*) a, (decimal*) b, res));
}
......@@ -318,14 +322,14 @@ int my_decimal_mod(uint mask, my_decimal *res, const my_decimal *a,
inline
int my_decimal_cmp(const my_decimal *a, const my_decimal *b)
{
return decimal_cmp((decimal *)a, (decimal *)b);
return decimal_cmp((decimal*) a, (decimal*) b);
}
inline
void max_my_decimal(my_decimal *to, int precision, int frac)
{
DBUG_ASSERT(precision <= DECIMAL_MAX_LENGTH);
max_decimal(precision, frac, (decimal *)to);
max_decimal(precision, frac, (decimal*) to);
}
#endif /*my_decimal_h*/
......
......@@ -400,8 +400,6 @@ typedef struct st_sql_list {
} SQL_LIST;
uint nr_of_decimals(const char *str); /* Neaded by sql_string.h */
extern pthread_key(THD*, THR_THD);
inline THD *_current_thd(void)
{
......
......@@ -822,15 +822,9 @@ bool Protocol_simple::store_decimal(const my_decimal *d)
field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
field_pos++;
#endif
int buf_size= my_decimal_string_length(d);
char *buff= (char *)my_alloca(buf_size);
String str(buff, buf_size, &my_charset_bin);
if (my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str))
{
my_afree(buff);
return TRUE;
}
my_afree(buff);
char buff[DECIMAL_MAX_STR_LENGTH];
String str(buff, sizeof(buff), &my_charset_bin);
(void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
return net_store_data(str.ptr(), str.length());
}
......@@ -1056,15 +1050,9 @@ bool Protocol_prep::store_decimal(const my_decimal *d)
field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
field_pos++;
#endif
int buf_size= my_decimal_string_length(d);
char *buff= (char *)my_alloca(buf_size);
String str(buff, buf_size, &my_charset_bin);
if (my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str))
{
my_afree(buff);
return TRUE;
}
my_afree(buff);
char buff[DECIMAL_MAX_STR_LENGTH];
String str(buff, sizeof(buff), &my_charset_bin);
(void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
return store(str.ptr(), str.length(), str.charset());
}
......
......@@ -104,15 +104,15 @@ bool Protocol_cursor::write()
byte *to;
new_record= (MYSQL_ROWS *)alloc_root(alloc,
sizeof(MYSQL_ROWS) + (field_count + 1)*sizeof(char *) + packet->length());
sizeof(MYSQL_ROWS) + (field_count + 2)*sizeof(char *) + packet->length());
if (!new_record)
goto err;
data_tmp= (byte **)(new_record + 1);
new_record->data= (char **)data_tmp;
to= (byte *)data_tmp + (field_count + 1)*sizeof(char *);
to= (byte *)data_tmp + (field_count + 2)*sizeof(char *);
for (; cur_field < fields_end; ++cur_field, ++data_tmp)
for (; cur_field < fields_end; cur_field++, data_tmp++)
{
if ((len= net_field_length((uchar **)&cp)) == 0 ||
len == NULL_LENGTH)
......@@ -135,7 +135,8 @@ bool Protocol_cursor::write()
cur_field->max_length=len;
}
}
*data_tmp= 0;
data_tmp[0]= to; // Pointer to last used byte
data_tmp[1]= 0;
*prev_record= new_record;
prev_record= &new_record->next;
......
......@@ -158,69 +158,12 @@ sp_eval_func_item(THD *thd, Item *it, enum enum_field_types type)
}
case DECIMAL_RESULT:
{
switch (it->result_type())
{
case DECIMAL_RESULT:
{
my_decimal value, *val= it->val_decimal(&value);
if (it->null_value)
it= new Item_null();
else
it= new Item_decimal(val);
break;
}
case INT_RESULT:
{
longlong val= it->val_int();
if (it->null_value)
it= new Item_null();
else
it= new Item_decimal(val, (int)it->max_length,
(bool)it->unsigned_flag);
break;
}
case REAL_RESULT:
{
double val= it->val_real();
if (it->null_value)
it= new Item_null();
else
it= new Item_decimal(val, (int)it->max_length,
(int)it->decimals);
break;
}
case STRING_RESULT:
{
char buffer[MAX_FIELD_WIDTH];
String tmp(buffer, sizeof(buffer), it->collation.collation);
String *val= it->val_str(&tmp);
if (it->null_value)
it= new Item_null();
else
it= new Item_decimal(val->ptr(), val->length(), val->charset());
break;
}
case ROW_RESULT:
default:
DBUG_ASSERT(0);
}
#ifndef DBUG_OFF
my_decimal value, *val= it->val_decimal(&value);
if (it->null_value)
{
DBUG_PRINT("info", ("DECIMAL_RESULT: null"));
}
it= new Item_null();
else
{
my_decimal value, *val= it->val_decimal(&value);
int len;
char *buff=
(char *)my_alloca(len= my_decimal_string_length(val) + 3);
String str(buff, len, &my_charset_bin);
my_decimal2string(0, val, 0, 0, 0, &str);
DBUG_PRINT("info", ("DECIMAL_RESULT: %s", str.ptr()));
my_afree(buff);
}
#endif
it= new Item_decimal(val);
dbug_print_decimal("info", "DECIMAL_RESULT: %s", val);
break;
}
case STRING_RESULT:
......@@ -236,8 +179,9 @@ sp_eval_func_item(THD *thd, Item *it, enum enum_field_types type)
}
else
{
DBUG_PRINT("info",("default result: %*s",s->length(),s->c_ptr_quick()));
it= new Item_string(thd->strmake(s->c_ptr_quick(), s->length()),
DBUG_PRINT("info",("default result: %*s",
s->length(), s->c_ptr_quick()));
it= new Item_string(thd->strmake(s->ptr(), s->length()),
s->length(), it->collation.collation);
}
break;
......@@ -811,7 +755,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
suv= new Item_func_set_user_var(guv->get_name(), item);
/*
we do not check suv->fixed, bacause it can't be fixed after
we do not check suv->fixed, because it can't be fixed after
creation
*/
suv->fix_fields(thd, NULL, &item);
......
......@@ -243,27 +243,36 @@ sp_cursor::fetch(THD *thd, List<struct sp_pvar> *vars)
if (!s)
it= new Item_null();
else
switch (sp_map_result_type(pv->type))
{
{
/*
Length of data can be calculated as:
pointer_to_next_not_null_object - s -1
where the last -1 is to remove the end \0
*/
uint len;
MYSQL_ROW next= row+fldcount+1;
while (!*next) // Skip nulls
next++;
len= (*next -s)-1;
switch (sp_map_result_type(pv->type)) {
case INT_RESULT:
it= new Item_int(s);
break;
case REAL_RESULT:
it= new Item_float(s, strlen(s));
it= new Item_float(s, len);
break;
case DECIMAL_RESULT:
it= new Item_decimal(s, strlen(s), thd->db_charset);
it= new Item_decimal(s, len, thd->db_charset);
break;
case STRING_RESULT:
{
uint len= strlen(s);
it= new Item_string(thd->strmake(s, len), len, thd->db_charset);
break;
}
/* TODO: Document why we do an extra copy of the string 's' here */
it= new Item_string(thd->strmake(s, len), len, thd->db_charset);
break;
case ROW_RESULT:
default:
DBUG_ASSERT(0);
}
}
thd->spcont->set_item(pv->offset, it);
}
if (fldcount < m_prot->get_field_count())
......
......@@ -133,22 +133,30 @@ proc_analyse_init(THD *thd, ORDER *param, select_result *result,
Item *item;
while ((item = it++))
{
if (item->result_type() == INT_RESULT)
{
field_info *new_field;
switch (item->result_type()) {
case INT_RESULT:
// Check if fieldtype is ulonglong
if (item->type() == Item::FIELD_ITEM &&
((Item_field*) item)->field->type() == FIELD_TYPE_LONGLONG &&
((Field_longlong*) ((Item_field*) item)->field)->unsigned_flag)
*f_info++ = new field_ulonglong(item, pc);
new_field= new field_ulonglong(item, pc);
else
*f_info++ = new field_longlong(item, pc);
new_field= new field_longlong(item, pc);
break;
case REAL_RESULT:
new_field= new field_real(item, pc);
break;
case DECIMAL_RESULT:
new_field= new field_decimal(item, pc);
break;
case STRING_RESULT:
new_field= new field_str(item, pc);
break;
default:
goto err;
}
if (item->result_type() == REAL_RESULT)
*f_info++ = new field_real(item, pc);
if (item->result_type() == DECIMAL_RESULT)
*f_info++= new field_decimal(item, pc);
if (item->result_type() == STRING_RESULT)
*f_info++ = new field_str(item, pc);
*f_info++= new_field;
}
}
DBUG_RETURN(pc);
......@@ -470,6 +478,9 @@ void field_decimal::add()
length= my_decimal_string_length(dec);
if (decimal_is_zero(dec))
empty++;
if (room_in_tree)
{
char buf[DECIMAL_MAX_FIELD_SIZE];
......@@ -502,7 +513,7 @@ void field_decimal::add()
cur_sum= 0;
min_length = max_length = length;
}
else
else if (!decimal_is_zero(dec))
{
int next_cur_sum= cur_sum ^ 1;
my_decimal sqr_buf;
......@@ -972,15 +983,17 @@ void field_decimal::get_opt_type(String *answer,
{
my_decimal zero;
char buff[MAX_FIELD_WIDTH];
uint length;
my_decimal_set_zero(&zero);
my_bool is_unsigned= (my_decimal_cmp(&zero, &min_arg) >= 0);
sprintf(buff, "DECIMAL(%d, %d)",
(int)(max_length - (item->decimals ? 1 : 0)), item->decimals);
length= my_sprintf(buff, (buff, "DECIMAL(%d, %d)",
(int) (max_length - (item->decimals ? 1 : 0)),
item->decimals));
if (is_unsigned)
strcat(buff, " UNSIGNED");
answer->append(buff, (uint) strlen(buff));
length= (uint) (strmov(buff+length, " UNSIGNED")- buff);
answer->append(buff, length);
}
......
......@@ -3400,8 +3400,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
thd->restore_backup_item_arena(arena, &backup);
if (*conds && !(*conds)->fixed)
{
if (!(*conds)->fixed &&
(*conds)->fix_fields(thd, tables, conds))
if ((*conds)->fix_fields(thd, tables, conds))
goto err_no_arena;
}
}
......@@ -3413,8 +3412,8 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
thd->restore_backup_item_arena(arena, &backup);
if (embedded->on_expr && !embedded->on_expr->fixed)
{
if (!embedded->on_expr->fixed &&
embedded->on_expr->fix_fields(thd, tables, &embedded->on_expr))
if (embedded->on_expr->fix_fields(thd, tables,
&embedded->on_expr))
goto err_no_arena;
}
}
......
......@@ -1366,10 +1366,9 @@ bool select_max_min_finder_subselect::cmp_real()
return (cache->null_value && !maxmin->null_value) ||
(!cache->null_value && !maxmin->null_value &&
val1 > val2);
else
return (maxmin->null_value && !cache->null_value) ||
(!cache->null_value && !maxmin->null_value &&
val1 < val2);
return (maxmin->null_value && !cache->null_value) ||
(!cache->null_value && !maxmin->null_value &&
val1 < val2);
}
bool select_max_min_finder_subselect::cmp_int()
......@@ -1380,30 +1379,23 @@ bool select_max_min_finder_subselect::cmp_int()
return (cache->null_value && !maxmin->null_value) ||
(!cache->null_value && !maxmin->null_value &&
val1 > val2);
else
return (maxmin->null_value && !cache->null_value) ||
(!cache->null_value && !maxmin->null_value &&
val1 < val2);
return (maxmin->null_value && !cache->null_value) ||
(!cache->null_value && !maxmin->null_value &&
val1 < val2);
}
bool select_max_min_finder_subselect::cmp_decimal()
{
String *val1, *val2, buf1, buf2;
Item *maxmin= ((Item_singlerow_subselect *)item)->el(0);
/*
as far as both operand is Item_cache buf1 & buf2 will not be used,
but added for safety
*/
my_decimal cval, *cvalue= cache->val_decimal(&cval);
my_decimal mval, *mvalue= maxmin->val_decimal(&mval);
if (fmax)
return (cache->null_value && !maxmin->null_value) ||
(!cache->null_value && !maxmin->null_value &&
my_decimal_cmp(cvalue, mvalue) > 0) ;
else
return (maxmin->null_value && !cache->null_value) ||
(!cache->null_value && !maxmin->null_value &&
my_decimal_cmp(cvalue,mvalue) < 0);
return (maxmin->null_value && !cache->null_value) ||
(!cache->null_value && !maxmin->null_value &&
my_decimal_cmp(cvalue,mvalue) < 0);
}
bool select_max_min_finder_subselect::cmp_str()
......@@ -1420,10 +1412,9 @@ bool select_max_min_finder_subselect::cmp_str()
return (cache->null_value && !maxmin->null_value) ||
(!cache->null_value && !maxmin->null_value &&
sortcmp(val1, val2, cache->collation.collation) > 0) ;
else
return (maxmin->null_value && !cache->null_value) ||
(!cache->null_value && !maxmin->null_value &&
sortcmp(val1, val2, cache->collation.collation) < 0);
return (maxmin->null_value && !cache->null_value) ||
(!cache->null_value && !maxmin->null_value &&
sortcmp(val1, val2, cache->collation.collation) < 0);
}
bool select_exists_subselect::send_data(List<Item> &items)
......
......@@ -7217,8 +7217,9 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
if (conds)
{
conds= and_conds(conds, table->on_expr);
if (!conds->fixed)
conds->fix_fields(join->thd, 0, &conds);
/* conds is always a new item as both cond and on_expr existed */
DBUG_ASSERT(!conds->fixed);
conds->fix_fields(join->thd, 0, &conds);
}
else
conds= table->on_expr;
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment