Merge
BitKeeper/etc/logging_ok: auto-union sql/item.cc: Auto merged sql/item_func.cc: Auto merged sql/mysqld.cc: Auto merged sql/set_var.cc: Auto merged sql/sql_parse.cc: Auto merged sql/item.h: SCCS merged
This commit is contained in:
commit
54d57ffd2f
@ -82,6 +82,7 @@ hf@bisonxp.(none)
|
||||
hf@deer.(none)
|
||||
hf@deer.mysql.r18.ru
|
||||
hf@genie.(none)
|
||||
holyfoot@mysql.com
|
||||
igor@hundin.mysql.fi
|
||||
igor@linux.local
|
||||
igor@rurik.mysql.com
|
||||
|
@ -39,7 +39,7 @@ int decimal2longlong(decimal_t *from, longlong *to);
|
||||
int longlong2decimal(longlong from, decimal_t *to);
|
||||
int decimal2double(decimal_t *from, double *to);
|
||||
int double2decimal(double from, decimal_t *to);
|
||||
void decimal_optimize_fraction(decimal_t *from);
|
||||
int decimal_actual_fraction(decimal_t *from);
|
||||
int decimal2bin(decimal_t *from, char *to, int precision, int scale);
|
||||
int bin2decimal(char *from, decimal_t *to, int precision, int scale);
|
||||
|
||||
|
92
sql/field.cc
92
sql/field.cc
@ -2229,12 +2229,6 @@ void Field_decimal::sql_type(String &res) const
|
||||
** Field_new_decimal
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
Constructors of new decimal field. In case of using NOT_FIXED_DEC it try
|
||||
to use maximally allowed length (DECIMAL_MAX_LENGTH) and number of digits
|
||||
after decimal point maximally close to half of this range
|
||||
(min(DECIMAL_MAX_LENGTH/2, NOT_FIXED_DEC-1))
|
||||
*/
|
||||
Field_new_decimal::Field_new_decimal(char *ptr_arg,
|
||||
uint32 len_arg, uchar *null_ptr_arg,
|
||||
uchar null_bit_arg,
|
||||
@ -2243,17 +2237,15 @@ Field_new_decimal::Field_new_decimal(char *ptr_arg,
|
||||
struct st_table *table_arg,
|
||||
uint8 dec_arg,bool zero_arg,
|
||||
bool unsigned_arg)
|
||||
:Field_num(ptr_arg,
|
||||
(dec_arg == NOT_FIXED_DEC || len_arg > DECIMAL_MAX_LENGTH ?
|
||||
DECIMAL_MAX_LENGTH : len_arg),
|
||||
:Field_num(ptr_arg, len_arg,
|
||||
null_ptr_arg, null_bit_arg,
|
||||
unireg_check_arg, field_name_arg, table_arg,
|
||||
(dec_arg == NOT_FIXED_DEC ?
|
||||
min(DECIMAL_MAX_LENGTH / 2, NOT_FIXED_DEC - 1) :
|
||||
dec_arg),
|
||||
zero_arg, unsigned_arg)
|
||||
dec_arg, zero_arg, unsigned_arg)
|
||||
{
|
||||
bin_size= my_decimal_get_binary_size(field_length, dec);
|
||||
precision= my_decimal_length_to_precision(len_arg, dec_arg, unsigned_arg);
|
||||
DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION) &&
|
||||
(dec <= DECIMAL_MAX_SCALE));
|
||||
bin_size= my_decimal_get_binary_size(precision, dec);
|
||||
}
|
||||
|
||||
|
||||
@ -2261,18 +2253,18 @@ Field_new_decimal::Field_new_decimal(uint32 len_arg,
|
||||
bool maybe_null,
|
||||
const char *name,
|
||||
struct st_table *t_arg,
|
||||
uint8 dec_arg)
|
||||
:Field_num((char*) 0,
|
||||
(dec_arg == NOT_FIXED_DEC|| len_arg > DECIMAL_MAX_LENGTH ?
|
||||
DECIMAL_MAX_LENGTH : len_arg),
|
||||
uint8 dec_arg,
|
||||
bool unsigned_arg)
|
||||
:Field_num((char*) 0, len_arg,
|
||||
maybe_null ? (uchar*) "": 0, 0,
|
||||
NONE, name, t_arg,
|
||||
(dec_arg == NOT_FIXED_DEC ?
|
||||
min(DECIMAL_MAX_LENGTH / 2, NOT_FIXED_DEC - 1) :
|
||||
dec_arg),
|
||||
0, 0)
|
||||
dec_arg,
|
||||
0, unsigned_arg)
|
||||
{
|
||||
bin_size= my_decimal_get_binary_size(field_length, dec);
|
||||
precision= my_decimal_length_to_precision(len_arg, dec_arg, unsigned_arg);
|
||||
DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION) &&
|
||||
(dec <= DECIMAL_MAX_SCALE));
|
||||
bin_size= my_decimal_get_binary_size(precision, dec);
|
||||
}
|
||||
|
||||
|
||||
@ -2295,7 +2287,7 @@ void Field_new_decimal::set_value_on_overflow(my_decimal *decimal_value,
|
||||
bool sign)
|
||||
{
|
||||
DBUG_ENTER("Field_new_decimal::set_value_on_overflow");
|
||||
max_my_decimal(decimal_value, field_length, decimals());
|
||||
max_my_decimal(decimal_value, precision, decimals());
|
||||
if (sign)
|
||||
{
|
||||
if (unsigned_flag)
|
||||
@ -2326,10 +2318,14 @@ void Field_new_decimal::set_value_on_overflow(my_decimal *decimal_value,
|
||||
|
||||
bool Field_new_decimal::store_value(const my_decimal *decimal_value)
|
||||
{
|
||||
my_decimal *dec= (my_decimal*)decimal_value;
|
||||
int error= 0;
|
||||
DBUG_ENTER("Field_new_decimal::store_value");
|
||||
dbug_print_decimal("enter", "value: %s", dec);
|
||||
#ifndef DBUG_OFF
|
||||
{
|
||||
char dbug_buff[DECIMAL_MAX_STR_LENGTH+1];
|
||||
DBUG_PRINT("enter", ("value: %s", dbug_decimal_as_string(dbug_buff, decimal_value)));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check that we do not try to write negative value in unsigned field */
|
||||
if (unsigned_flag && decimal_value->sign())
|
||||
@ -2337,25 +2333,27 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value)
|
||||
DBUG_PRINT("info", ("unsigned overflow"));
|
||||
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
|
||||
error= 1;
|
||||
dec= &decimal_zero;
|
||||
decimal_value= &decimal_zero;
|
||||
}
|
||||
DBUG_PRINT("info", ("saving with precision %d, scale: %d",
|
||||
(int)field_length, (int)decimals()));
|
||||
dbug_print_decimal("info", "value: %s", dec);
|
||||
#ifndef DBUG_OFF
|
||||
{
|
||||
char dbug_buff[DECIMAL_MAX_STR_LENGTH+1];
|
||||
DBUG_PRINT("info", ("saving with precision %d, scale: %d, value %s",
|
||||
(int)precision, (int)dec,
|
||||
dbug_decimal_as_string(dbug_buff, decimal_value)));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (warn_if_overflow(my_decimal2binary(E_DEC_FATAL_ERROR &
|
||||
~E_DEC_OVERFLOW,
|
||||
dec, ptr,
|
||||
field_length,
|
||||
decimals())))
|
||||
if (warn_if_overflow(my_decimal2binary(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
|
||||
decimal_value, ptr, precision, dec)))
|
||||
{
|
||||
my_decimal buff;
|
||||
DBUG_PRINT("info", ("overflow"));
|
||||
set_value_on_overflow(&buff, dec->sign());
|
||||
my_decimal2binary(E_DEC_FATAL_ERROR, &buff, ptr, field_length, decimals());
|
||||
set_value_on_overflow(&buff, decimal_value->sign());
|
||||
my_decimal2binary(E_DEC_FATAL_ERROR, &buff, ptr, precision, dec);
|
||||
error= 1;
|
||||
}
|
||||
DBUG_EXECUTE("info", print_decimal_buff(dec, (byte *) ptr, bin_size););
|
||||
DBUG_EXECUTE("info", print_decimal_buff(decimal_value, (byte *) ptr, bin_size););
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
@ -2387,7 +2385,11 @@ int Field_new_decimal::store(const char *from, uint length,
|
||||
break;
|
||||
}
|
||||
|
||||
dbug_print_decimal("enter", "value: %s", &decimal_value);
|
||||
#ifndef DBUG_OFF
|
||||
char dbug_buff[DECIMAL_MAX_STR_LENGTH+1];
|
||||
DBUG_PRINT("enter", ("value: %s",
|
||||
dbug_decimal_as_string(dbug_buff, &decimal_value)));
|
||||
#endif
|
||||
store_value(&decimal_value);
|
||||
DBUG_RETURN(err);
|
||||
}
|
||||
@ -2477,8 +2479,7 @@ my_decimal* Field_new_decimal::val_decimal(my_decimal *decimal_value)
|
||||
{
|
||||
DBUG_ENTER("Field_new_decimal::val_decimal");
|
||||
binary2my_decimal(E_DEC_FATAL_ERROR, ptr, decimal_value,
|
||||
field_length,
|
||||
decimals());
|
||||
precision, dec);
|
||||
DBUG_EXECUTE("info", print_decimal_buff(decimal_value, (byte *) ptr,
|
||||
bin_size););
|
||||
DBUG_RETURN(decimal_value);
|
||||
@ -2489,12 +2490,9 @@ String *Field_new_decimal::val_str(String *val_buffer,
|
||||
String *val_ptr __attribute__((unused)))
|
||||
{
|
||||
my_decimal decimal_value;
|
||||
int fixed_precision= (zerofill ?
|
||||
(field_length + (decimals() ? 1 : 0)) :
|
||||
0);
|
||||
uint fixed_precision= zerofill ? precision : 0;
|
||||
my_decimal2string(E_DEC_FATAL_ERROR, val_decimal(&decimal_value),
|
||||
fixed_precision, decimals(), '0',
|
||||
val_buffer);
|
||||
fixed_precision, dec, '0', val_buffer);
|
||||
return val_buffer;
|
||||
}
|
||||
|
||||
@ -2516,7 +2514,7 @@ void Field_new_decimal::sql_type(String &str) const
|
||||
{
|
||||
CHARSET_INFO *cs= str.charset();
|
||||
str.length(cs->cset->snprintf(cs, (char*) str.ptr(), str.alloced_length(),
|
||||
"decimal(%d,%d)", field_length, (int)dec));
|
||||
"decimal(%d,%d)", precision, (int)dec));
|
||||
add_zerofill_and_unsigned(str);
|
||||
}
|
||||
|
||||
|
16
sql/field.h
16
sql/field.h
@ -300,8 +300,6 @@ public:
|
||||
int warn_if_overflow(int op_result);
|
||||
/* maximum possible display length */
|
||||
virtual uint32 max_length()= 0;
|
||||
/* length of field value symbolic representation (in bytes) */
|
||||
virtual uint32 representation_length() { return field_length; }
|
||||
/* convert decimal to longlong with overflow check */
|
||||
longlong convert_decimal2longlong(const my_decimal *val, bool unsigned_flag,
|
||||
int *err);
|
||||
@ -438,7 +436,13 @@ public:
|
||||
/* New decimal/numeric field which use fixed point arithmetic */
|
||||
class Field_new_decimal :public Field_num {
|
||||
public:
|
||||
/* The maximum number of decimal digits can be stored */
|
||||
uint precision;
|
||||
uint bin_size;
|
||||
/* Constructors take max_length of the field as a parameter - not the */
|
||||
/* precision as the number of decimal digits allowed */
|
||||
/* So for example we need to count length from precision handling */
|
||||
/* CREATE TABLE ( DECIMAL(x,y)) */
|
||||
Field_new_decimal(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
|
||||
uchar null_bit_arg,
|
||||
enum utype unireg_check_arg, const char *field_name_arg,
|
||||
@ -446,7 +450,8 @@ public:
|
||||
uint8 dec_arg, bool zero_arg, bool unsigned_arg);
|
||||
Field_new_decimal(uint32 len_arg, bool maybe_null_arg,
|
||||
const char *field_name_arg,
|
||||
struct st_table *table_arg, uint8 dec_arg);
|
||||
struct st_table *table_arg, uint8 dec_arg,
|
||||
bool unsigned_arg);
|
||||
enum_field_types type() const { return FIELD_TYPE_NEWDECIMAL;}
|
||||
enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
|
||||
Item_result result_type () const { return DECIMAL_RESULT; }
|
||||
@ -465,10 +470,7 @@ public:
|
||||
void sort_string(char *buff, uint length);
|
||||
bool zero_pack() const { return 0; }
|
||||
void sql_type(String &str) const;
|
||||
uint32 max_length()
|
||||
{ return field_length + 1 + (dec ? 1 : 0) + (field_length == dec ? 1 : 0); }
|
||||
uint32 representation_length()
|
||||
{ return field_length + 1 + (dec ? 1 : 0) + (field_length == dec ? 1 : 0); };
|
||||
uint32 max_length() { return field_length; }
|
||||
uint size_of() const { return sizeof(*this); }
|
||||
uint32 pack_length() const { return (uint32) bin_size; }
|
||||
};
|
||||
|
@ -3621,7 +3621,7 @@ static int create_ndb_column(NDBCOL &col,
|
||||
case MYSQL_TYPE_NEWDECIMAL:
|
||||
{
|
||||
Field_new_decimal *f= (Field_new_decimal*)field;
|
||||
uint precision= f->field_length;
|
||||
uint precision= f->precision;
|
||||
uint scale= f->decimals();
|
||||
if (field->flags & UNSIGNED_FLAG)
|
||||
{
|
||||
|
76
sql/item.cc
76
sql/item.cc
@ -80,7 +80,7 @@ Hybrid_type_traits_decimal::fix_length_and_dec(Item *item, Item *arg) const
|
||||
{
|
||||
item->decimals= arg->decimals;
|
||||
item->max_length= min(arg->max_length + DECIMAL_LONGLONG_DIGITS,
|
||||
DECIMAL_MAX_LENGTH);
|
||||
DECIMAL_MAX_STR_LENGTH);
|
||||
}
|
||||
|
||||
|
||||
@ -348,6 +348,17 @@ Item::Item(THD *thd, Item *item):
|
||||
}
|
||||
|
||||
|
||||
uint Item::decimal_precision() const
|
||||
{
|
||||
Item_result restype= result_type();
|
||||
|
||||
if ((restype == DECIMAL_RESULT) || (restype == INT_RESULT))
|
||||
return min(my_decimal_length_to_precision(max_length, decimals, unsigned_flag),
|
||||
DECIMAL_MAX_PRECISION);
|
||||
return min(max_length, DECIMAL_MAX_PRECISION);
|
||||
}
|
||||
|
||||
|
||||
void Item::print_item_w_name(String *str)
|
||||
{
|
||||
print(str);
|
||||
@ -943,10 +954,8 @@ bool DTCollation::aggregate(DTCollation &dt, uint flags)
|
||||
return 1;
|
||||
}
|
||||
if (collation->state & MY_CS_BINSORT)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (dt.collation->state & MY_CS_BINSORT)
|
||||
if (dt.collation->state & MY_CS_BINSORT)
|
||||
{
|
||||
set(dt);
|
||||
return 0;
|
||||
@ -1026,7 +1035,7 @@ void Item_field::set_field(Field *field_par)
|
||||
field=result_field=field_par; // for easy coding with fields
|
||||
maybe_null=field->maybe_null();
|
||||
decimals= field->decimals();
|
||||
max_length= field_par->representation_length();
|
||||
max_length= field_par->field_length;
|
||||
table_name= *field_par->table_name;
|
||||
field_name= field_par->field_name;
|
||||
db_name= field_par->table->s->db;
|
||||
@ -1371,18 +1380,18 @@ Item_decimal::Item_decimal(const char *str_arg, uint length,
|
||||
str2my_decimal(E_DEC_FATAL_ERROR, str_arg, length, charset, &decimal_value);
|
||||
name= (char*) str_arg;
|
||||
decimals= (uint8) decimal_value.frac;
|
||||
max_length= my_decimal_max_length(&decimal_value);
|
||||
fixed= 1;
|
||||
unsigned_flag= !decimal_value.sign();
|
||||
max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
|
||||
decimals, unsigned_flag);
|
||||
}
|
||||
|
||||
Item_decimal::Item_decimal(longlong val, bool unsig)
|
||||
{
|
||||
int2my_decimal(E_DEC_FATAL_ERROR, val, unsig, &decimal_value);
|
||||
decimals= (uint8) decimal_value.frac;
|
||||
max_length= my_decimal_max_length(&decimal_value);
|
||||
fixed= 1;
|
||||
unsigned_flag= !decimal_value.sign();
|
||||
max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
|
||||
decimals, unsigned_flag);
|
||||
}
|
||||
|
||||
|
||||
@ -1390,9 +1399,9 @@ Item_decimal::Item_decimal(double val, int precision, int scale)
|
||||
{
|
||||
double2my_decimal(E_DEC_FATAL_ERROR, val, &decimal_value);
|
||||
decimals= (uint8) decimal_value.frac;
|
||||
max_length= my_decimal_max_length(&decimal_value);
|
||||
fixed= 1;
|
||||
unsigned_flag= !decimal_value.sign();
|
||||
max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
|
||||
decimals, unsigned_flag);
|
||||
}
|
||||
|
||||
|
||||
@ -1404,7 +1413,6 @@ Item_decimal::Item_decimal(const char *str, const my_decimal *val_arg,
|
||||
decimals= (uint8) decimal_par;
|
||||
max_length= length;
|
||||
fixed= 1;
|
||||
unsigned_flag= !decimal_value.sign();
|
||||
}
|
||||
|
||||
|
||||
@ -1412,19 +1420,20 @@ Item_decimal::Item_decimal(my_decimal *value_par)
|
||||
{
|
||||
my_decimal2decimal(value_par, &decimal_value);
|
||||
decimals= (uint8) decimal_value.frac;
|
||||
max_length= my_decimal_max_length(value_par);
|
||||
fixed= 1;
|
||||
unsigned_flag= !decimal_value.sign();
|
||||
max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
|
||||
decimals, !decimal_value.sign());
|
||||
}
|
||||
|
||||
|
||||
Item_decimal::Item_decimal(const char *bin, int precision, int scale)
|
||||
{
|
||||
binary2my_decimal(E_DEC_FATAL_ERROR, bin, &decimal_value, precision, scale);
|
||||
binary2my_decimal(E_DEC_FATAL_ERROR, bin,
|
||||
&decimal_value, precision, scale);
|
||||
decimals= (uint8) decimal_value.frac;
|
||||
max_length= my_decimal_max_length(&decimal_value);
|
||||
fixed= 1;
|
||||
unsigned_flag= !decimal_value.sign();
|
||||
max_length= my_decimal_precision_to_length(precision, decimals,
|
||||
!decimal_value.sign());
|
||||
}
|
||||
|
||||
|
||||
@ -1702,7 +1711,8 @@ void Item_param::set_decimal(const char *str, ulong 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;
|
||||
max_length= my_decimal_precision_to_length(decimal_value.precision(),
|
||||
decimals, unsigned_flag);
|
||||
maybe_null= 0;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
@ -1853,7 +1863,8 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)
|
||||
my_decimal2decimal(ent_value, &decimal_value);
|
||||
state= DECIMAL_VALUE;
|
||||
decimals= ent_value->frac;
|
||||
max_length= ent_value->intg + decimals + 2;
|
||||
max_length= my_decimal_precision_to_length(ent_value->precision(),
|
||||
decimals, unsigned_flag);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -3271,11 +3282,8 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table)
|
||||
|
||||
switch (field_type()) {
|
||||
case MYSQL_TYPE_DECIMAL:
|
||||
return new Field_decimal((char*) 0, max_length, null_ptr, 0, Field::NONE,
|
||||
name, table, decimals, 0, unsigned_flag);
|
||||
case MYSQL_TYPE_NEWDECIMAL:
|
||||
return new Field_new_decimal((char*) 0, max_length - (decimals?1:0),
|
||||
null_ptr, 0,
|
||||
return new Field_new_decimal((char*) 0, max_length, null_ptr, 0,
|
||||
Field::NONE, name, table, decimals, 0,
|
||||
unsigned_flag);
|
||||
case MYSQL_TYPE_TINY:
|
||||
@ -5031,6 +5039,7 @@ Item_type_holder::Item_type_holder(THD *thd, Item *item)
|
||||
/* fix variable decimals which always is NOT_FIXED_DEC */
|
||||
if (Field::result_merge_type(fld_type) == INT_RESULT)
|
||||
decimals= 0;
|
||||
prev_decimal_int_part= item->decimal_int_part();
|
||||
}
|
||||
|
||||
|
||||
@ -5153,18 +5162,12 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
|
||||
}
|
||||
if (Field::result_merge_type(fld_type) == DECIMAL_RESULT)
|
||||
{
|
||||
int item_length= display_length(item);
|
||||
int intp1= item_length - min(item->decimals, NOT_FIXED_DEC - 1);
|
||||
int intp2= max_length - min(decimals, NOT_FIXED_DEC - 1);
|
||||
/* can't be overflow because it work only for decimals (no strings) */
|
||||
int dec_length= max(intp1, intp2) + decimals;
|
||||
max_length= max(max_length, (uint) max(item_length, dec_length));
|
||||
/*
|
||||
we can't allow decimals to be NOT_FIXED_DEC, to prevent creation
|
||||
decimal with max precision (see Field_new_decimal constcuctor)
|
||||
*/
|
||||
if (decimals >= NOT_FIXED_DEC)
|
||||
decimals= NOT_FIXED_DEC - 1;
|
||||
decimals= min(max(decimals, item->decimals), DECIMAL_MAX_SCALE);
|
||||
int precision= min(max(prev_decimal_int_part, item->decimal_int_part())
|
||||
+ decimals, DECIMAL_MAX_PRECISION);
|
||||
unsigned_flag&= item->unsigned_flag;
|
||||
max_length= my_decimal_precision_to_length(precision, decimals,
|
||||
unsigned_flag);
|
||||
}
|
||||
else
|
||||
max_length= max(max_length, display_length(item));
|
||||
@ -5185,6 +5188,9 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
|
||||
}
|
||||
maybe_null|= item->maybe_null;
|
||||
get_full_info(item);
|
||||
|
||||
/* Remember decimal integer part to be used in DECIMAL_RESULT handleng */
|
||||
prev_decimal_int_part= decimal_int_part();
|
||||
DBUG_PRINT("info", ("become type: %d len: %u dec: %u",
|
||||
(int) fld_type, max_length, (uint) decimals));
|
||||
DBUG_RETURN(FALSE);
|
||||
|
@ -442,6 +442,9 @@ public:
|
||||
virtual cond_result eq_cmp_result() const { return COND_OK; }
|
||||
inline uint float_length(uint decimals_par) const
|
||||
{ return decimals != NOT_FIXED_DEC ? (DBL_DIG+2+decimals_par) : DBL_DIG+8;}
|
||||
virtual uint decimal_precision() const;
|
||||
inline int decimal_int_part() const
|
||||
{ return my_decimal_int_part(decimal_precision(), decimals); }
|
||||
/*
|
||||
Returns true if this is constant (during query execution, i.e. its value
|
||||
will not change until next fix_fields) and its value is known.
|
||||
@ -972,6 +975,7 @@ public:
|
||||
void cleanup() {}
|
||||
void print(String *str);
|
||||
Item_num *neg() { value= -value; return this; }
|
||||
uint decimal_precision() const { return (uint)(max_length - test(value < 0)); }
|
||||
bool eq(const Item *, bool binary_cmp) const;
|
||||
};
|
||||
|
||||
@ -1001,6 +1005,7 @@ public:
|
||||
int save_in_field(Field *field, bool no_conversions);
|
||||
void print(String *str);
|
||||
Item_num *neg ();
|
||||
uint decimal_precision() const { return max_length; }
|
||||
};
|
||||
|
||||
|
||||
@ -1040,6 +1045,7 @@ public:
|
||||
unsigned_flag= !decimal_value.sign();
|
||||
return this;
|
||||
}
|
||||
uint decimal_precision() const { return decimal_value.precision(); }
|
||||
bool eq(const Item *, bool binary_cmp) const;
|
||||
};
|
||||
|
||||
@ -1802,6 +1808,9 @@ protected:
|
||||
enum_field_types fld_type;
|
||||
|
||||
void get_full_info(Item *item);
|
||||
|
||||
/* It is used to count decimal precision in join_types */
|
||||
int prev_decimal_int_part;
|
||||
public:
|
||||
Item_type_holder(THD*, Item*);
|
||||
|
||||
|
@ -1134,6 +1134,14 @@ Item_func_ifnull::fix_length_and_dec()
|
||||
cached_field_type= Item_func::field_type();
|
||||
}
|
||||
|
||||
|
||||
uint Item_func_ifnull::decimal_precision() const
|
||||
{
|
||||
int max_int_part=max(args[0]->decimal_int_part(),args[1]->decimal_int_part());
|
||||
return min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
|
||||
}
|
||||
|
||||
|
||||
enum_field_types Item_func_ifnull::field_type() const
|
||||
{
|
||||
return cached_field_type;
|
||||
@ -1251,6 +1259,14 @@ Item_func_if::fix_length_and_dec()
|
||||
}
|
||||
|
||||
|
||||
uint Item_func_if::decimal_precision() const
|
||||
{
|
||||
int precision=(max(args[1]->decimal_int_part(),args[2]->decimal_int_part())+
|
||||
decimals);
|
||||
return min(precision, DECIMAL_MAX_PRECISION);
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
Item_func_if::val_real()
|
||||
{
|
||||
@ -1304,7 +1320,8 @@ Item_func_nullif::fix_length_and_dec()
|
||||
{
|
||||
max_length=args[0]->max_length;
|
||||
decimals=args[0]->decimals;
|
||||
agg_result_type(&cached_result_type, args, 2);
|
||||
unsigned_flag= args[0]->unsigned_flag;
|
||||
cached_result_type= args[0]->result_type();
|
||||
if (cached_result_type == STRING_RESULT &&
|
||||
agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV))
|
||||
return;
|
||||
@ -1616,6 +1633,18 @@ void Item_func_case::fix_length_and_dec()
|
||||
}
|
||||
|
||||
|
||||
uint Item_func_case::decimal_precision() const
|
||||
{
|
||||
int max_int_part=0;
|
||||
for (uint i=0 ; i < ncases ; i+=2)
|
||||
set_if_bigger(max_int_part, args[i+1]->decimal_int_part());
|
||||
|
||||
if (else_expr_num != -1)
|
||||
set_if_bigger(max_int_part, args[else_expr_num]->decimal_int_part());
|
||||
return min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
|
||||
}
|
||||
|
||||
|
||||
/* TODO: Fix this so that it prints the whole CASE expression */
|
||||
|
||||
void Item_func_case::print(String *str)
|
||||
|
@ -95,6 +95,7 @@ public:
|
||||
Item_bool_func(THD *thd, Item_bool_func *item) :Item_int_func(thd, item) {}
|
||||
bool is_bool_func() { return 1; }
|
||||
void fix_length_and_dec() { decimals=0; max_length=1; }
|
||||
uint decimal_precision() const { return 1; }
|
||||
};
|
||||
|
||||
class Item_cache;
|
||||
@ -208,6 +209,7 @@ public:
|
||||
bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
|
||||
bool is_bool_func() { return 1; }
|
||||
CHARSET_INFO *compare_collation() { return cmp.cmp_collation.collation; }
|
||||
uint decimal_precision() const { return 1; }
|
||||
|
||||
friend class Arg_comparator;
|
||||
};
|
||||
@ -411,6 +413,7 @@ public:
|
||||
void fix_length_and_dec();
|
||||
void print(String *str);
|
||||
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
|
||||
uint decimal_precision() const { return 1; }
|
||||
};
|
||||
|
||||
|
||||
@ -445,6 +448,7 @@ public:
|
||||
longlong val_int();
|
||||
void fix_length_and_dec();
|
||||
const char *func_name() const { return "interval"; }
|
||||
uint decimal_precision() const { return 2; }
|
||||
};
|
||||
|
||||
|
||||
@ -485,6 +489,7 @@ public:
|
||||
void fix_length_and_dec();
|
||||
const char *func_name() const { return "ifnull"; }
|
||||
Field *tmp_table_field(TABLE *table);
|
||||
uint decimal_precision() const;
|
||||
};
|
||||
|
||||
|
||||
@ -507,6 +512,7 @@ public:
|
||||
return Item_func::fix_fields(thd, tlist, ref);
|
||||
}
|
||||
void fix_length_and_dec();
|
||||
uint decimal_precision() const;
|
||||
const char *func_name() const { return "if"; }
|
||||
table_map not_null_tables() const { return 0; }
|
||||
};
|
||||
@ -525,6 +531,7 @@ public:
|
||||
my_decimal *val_decimal(my_decimal *);
|
||||
enum Item_result result_type () const { return cached_result_type; }
|
||||
void fix_length_and_dec();
|
||||
uint decimal_precision() const { return args[0]->decimal_precision(); }
|
||||
const char *func_name() const { return "nullif"; }
|
||||
void print(String *str) { Item_func::print(str); }
|
||||
table_map not_null_tables() const { return 0; }
|
||||
@ -563,6 +570,7 @@ public:
|
||||
String *val_str(String *);
|
||||
my_decimal *val_decimal(my_decimal *);
|
||||
void fix_length_and_dec();
|
||||
uint decimal_precision() const;
|
||||
table_map not_null_tables() const { return 0; }
|
||||
enum Item_result result_type () const { return cached_result_type; }
|
||||
const char *func_name() const { return "case"; }
|
||||
@ -825,6 +833,7 @@ class Item_func_in :public Item_int_func
|
||||
}
|
||||
longlong val_int();
|
||||
void fix_length_and_dec();
|
||||
uint decimal_precision() const { return 1; }
|
||||
void cleanup()
|
||||
{
|
||||
DBUG_ENTER("Item_func_in::cleanup");
|
||||
|
171
sql/item_func.cc
171
sql/item_func.cc
@ -534,8 +534,10 @@ Field *Item_func::tmp_table_field(TABLE *t_arg)
|
||||
res= make_string_field(t_arg);
|
||||
break;
|
||||
case DECIMAL_RESULT:
|
||||
res= new Field_new_decimal(max_length + (decimals?1:0), maybe_null,
|
||||
name, t_arg, decimals);
|
||||
res= new Field_new_decimal(my_decimal_precision_to_length(decimal_precision(),
|
||||
decimals,
|
||||
unsigned_flag),
|
||||
maybe_null, name, t_arg, decimals, unsigned_flag);
|
||||
break;
|
||||
case ROW_RESULT:
|
||||
default:
|
||||
@ -590,19 +592,18 @@ void Item_func_numhybrid::fix_num_length_and_dec()
|
||||
|
||||
void Item_func::count_decimal_length()
|
||||
{
|
||||
uint32 length= 0;
|
||||
int max_int_part= 0;
|
||||
decimals= 0;
|
||||
unsigned_flag= 1;
|
||||
for (uint i=0 ; i < arg_count ; i++)
|
||||
{
|
||||
set_if_bigger(decimals, args[i]->decimals);
|
||||
set_if_bigger(length, (args[i]->max_length - args[i]->decimals));
|
||||
set_if_bigger(max_int_part, args[i]->decimal_int_part());
|
||||
set_if_smaller(unsigned_flag, args[i]->unsigned_flag);
|
||||
}
|
||||
max_length= length;
|
||||
length+= decimals;
|
||||
if (length < max_length) // If previous operation gave overflow
|
||||
max_length= UINT_MAX32;
|
||||
else
|
||||
max_length= length;
|
||||
int precision= min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
|
||||
max_length= my_decimal_precision_to_length(precision, decimals,
|
||||
unsigned_flag);
|
||||
}
|
||||
|
||||
|
||||
@ -616,8 +617,12 @@ void Item_func::count_decimal_length()
|
||||
void Item_func::count_only_length()
|
||||
{
|
||||
max_length= 0;
|
||||
unsigned_flag= 0;
|
||||
for (uint i=0 ; i < arg_count ; i++)
|
||||
{
|
||||
set_if_bigger(max_length, args[i]->max_length);
|
||||
set_if_bigger(unsigned_flag, args[i]->unsigned_flag);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -719,7 +724,6 @@ void Item_num_op::find_num_type(void)
|
||||
{
|
||||
decimals= 0;
|
||||
hybrid_type=INT_RESULT;
|
||||
unsigned_flag=args[0]->unsigned_flag | args[1]->unsigned_flag;
|
||||
result_precision();
|
||||
}
|
||||
DBUG_PRINT("info", ("Type: %s",
|
||||
@ -1075,9 +1079,17 @@ my_decimal *Item_func_plus::decimal_op(my_decimal *decimal_value)
|
||||
void Item_func_additive_op::result_precision()
|
||||
{
|
||||
decimals= max(args[0]->decimals, args[1]->decimals);
|
||||
max_length= (max(args[0]->max_length - args[0]->decimals,
|
||||
args[1]->max_length - args[1]->decimals) +
|
||||
decimals + 1);
|
||||
int max_int_part= max(args[0]->decimal_precision() - args[0]->decimals,
|
||||
args[1]->decimal_precision() - args[1]->decimals);
|
||||
int precision= min(max_int_part + 1 + decimals, DECIMAL_MAX_PRECISION);
|
||||
|
||||
/* Integer operations keep unsigned_flag if one of arguments is unsigned */
|
||||
if (result_type() == INT_RESULT)
|
||||
unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
|
||||
else
|
||||
unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
|
||||
max_length= my_decimal_precision_to_length(precision, decimals,
|
||||
unsigned_flag);
|
||||
}
|
||||
|
||||
|
||||
@ -1172,10 +1184,15 @@ my_decimal *Item_func_mul::decimal_op(my_decimal *decimal_value)
|
||||
|
||||
void Item_func_mul::result_precision()
|
||||
{
|
||||
decimals= args[0]->decimals + args[1]->decimals;
|
||||
max_length= ((args[0]->max_length - args[0]->decimals) +
|
||||
(args[1]->max_length - args[1]->decimals) +
|
||||
decimals);
|
||||
/* Integer operations keep unsigned_flag if one of arguments is unsigned */
|
||||
if (result_type() == INT_RESULT)
|
||||
unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
|
||||
else
|
||||
unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
|
||||
decimals= min(args[0]->decimals + args[1]->decimals, DECIMAL_MAX_SCALE);
|
||||
int precision= min(args[0]->decimal_precision() + args[1]->decimal_precision(),
|
||||
DECIMAL_MAX_PRECISION);
|
||||
max_length= my_decimal_precision_to_length(precision, decimals,unsigned_flag);
|
||||
}
|
||||
|
||||
|
||||
@ -1207,7 +1224,7 @@ my_decimal *Item_func_div::decimal_op(my_decimal *decimal_value)
|
||||
if ((null_value= args[1]->null_value))
|
||||
return 0;
|
||||
switch (my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value,
|
||||
val1, val2, DECIMAL_DIV_SCALE_INCREASE)) {
|
||||
val1, val2, prec_increment)) {
|
||||
case E_DEC_TRUNCATED:
|
||||
case E_DEC_OK:
|
||||
return decimal_value;
|
||||
@ -1222,11 +1239,16 @@ my_decimal *Item_func_div::decimal_op(my_decimal *decimal_value)
|
||||
|
||||
void Item_func_div::result_precision()
|
||||
{
|
||||
decimals= (args[0]->decimals + args[0]->decimals +
|
||||
DECIMAL_DIV_SCALE_INCREASE);
|
||||
max_length= ((args[0]->max_length - args[0]->decimals) +
|
||||
(args[1]->max_length - args[1]->decimals) +
|
||||
decimals);
|
||||
uint precision=min(args[0]->decimal_precision() + prec_increment,
|
||||
DECIMAL_MAX_PRECISION);
|
||||
/* Integer operations keep unsigned_flag if one of arguments is unsigned */
|
||||
if (result_type() == INT_RESULT)
|
||||
unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
|
||||
else
|
||||
unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
|
||||
decimals= min(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE);
|
||||
max_length= my_decimal_precision_to_length(precision, decimals,
|
||||
unsigned_flag);
|
||||
}
|
||||
|
||||
|
||||
@ -1234,10 +1256,11 @@ void Item_func_div::fix_length_and_dec()
|
||||
{
|
||||
DBUG_ENTER("Item_func_div::fix_length_and_dec");
|
||||
Item_num_op::fix_length_and_dec();
|
||||
prec_increment= current_thd->variables.div_precincrement;
|
||||
switch(hybrid_type) {
|
||||
case REAL_RESULT:
|
||||
{
|
||||
decimals=max(args[0]->decimals,args[1]->decimals)+2;
|
||||
decimals=max(args[0]->decimals,args[1]->decimals)+prec_increment;
|
||||
set_if_smaller(decimals, NOT_FIXED_DEC);
|
||||
max_length=args[0]->max_length - args[0]->decimals + decimals;
|
||||
uint tmp=float_length(decimals);
|
||||
@ -1383,7 +1406,6 @@ void Item_func_neg::fix_num_length_and_dec()
|
||||
decimals= args[0]->decimals;
|
||||
/* 1 add because sign can appear */
|
||||
max_length= args[0]->max_length + 1;
|
||||
unsigned_flag= 0;
|
||||
}
|
||||
|
||||
|
||||
@ -1409,6 +1431,7 @@ void Item_func_neg::fix_length_and_dec()
|
||||
hybrid_type= DECIMAL_RESULT;
|
||||
DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
|
||||
}
|
||||
unsigned_flag= 0;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
@ -1793,17 +1816,65 @@ my_decimal *Item_func_floor::decimal_op(my_decimal *decimal_value)
|
||||
}
|
||||
|
||||
|
||||
void Item_func_round::fix_num_length_and_dec()
|
||||
void Item_func_round::fix_length_and_dec()
|
||||
{
|
||||
unsigned_flag= args[0]->unsigned_flag;
|
||||
if (!args[1]->const_item())
|
||||
{
|
||||
max_length= args[0]->max_length;
|
||||
decimals= NOT_FIXED_DEC;
|
||||
if (args[1]->const_item())
|
||||
decimals= args[0]->decimals;
|
||||
hybrid_type= REAL_RESULT;
|
||||
return;
|
||||
}
|
||||
|
||||
int decimals_to_set= max(args[1]->val_int(), 0);
|
||||
if (args[0]->decimals == NOT_FIXED_DEC)
|
||||
{
|
||||
int tmp=(int) args[1]->val_int();
|
||||
if (tmp < 0)
|
||||
max_length= args[0]->max_length;
|
||||
decimals= min(decimals_to_set, NOT_FIXED_DEC);
|
||||
hybrid_type= REAL_RESULT;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (args[0]->result_type())
|
||||
{
|
||||
case REAL_RESULT:
|
||||
case STRING_RESULT:
|
||||
hybrid_type= REAL_RESULT;
|
||||
decimals= min(decimals_to_set, NOT_FIXED_DEC);
|
||||
max_length= float_length(decimals);
|
||||
break;
|
||||
case INT_RESULT:
|
||||
if (truncate || (args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS))
|
||||
{
|
||||
/* Here we can keep INT_RESULT */
|
||||
hybrid_type= INT_RESULT;
|
||||
int length_can_increase= !truncate && (args[1]->val_int() < 0);
|
||||
max_length= args[0]->max_length + length_can_increase;
|
||||
decimals= 0;
|
||||
break;
|
||||
}
|
||||
case DECIMAL_RESULT:
|
||||
{
|
||||
hybrid_type= DECIMAL_RESULT;
|
||||
int decimals_delta= args[0]->decimals - decimals_to_set;
|
||||
int precision= args[0]->decimal_precision();
|
||||
if (decimals_delta > 0)
|
||||
{
|
||||
int length_increase= truncate ? 0:1;
|
||||
precision-= decimals_delta - length_increase;
|
||||
decimals= decimals_to_set;
|
||||
}
|
||||
else
|
||||
decimals=min(tmp, NOT_FIXED_DEC);
|
||||
/* Decimals to set is bigger that the original scale */
|
||||
/* we keep original decimals value */
|
||||
decimals= args[0]->decimals;
|
||||
max_length= my_decimal_precision_to_length(precision, decimals,
|
||||
unsigned_flag);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
DBUG_ASSERT(0); /* This result type isn't handled */
|
||||
}
|
||||
}
|
||||
|
||||
@ -1881,7 +1952,9 @@ my_decimal *Item_func_round::decimal_op(my_decimal *decimal_value)
|
||||
my_decimal val, *value= args[0]->val_decimal(&val);
|
||||
int dec=(int) args[1]->val_int();
|
||||
if (dec > 0)
|
||||
decimals= dec; // to get correct output
|
||||
{
|
||||
decimals= min(dec, DECIMAL_MAX_SCALE); // to get correct output
|
||||
}
|
||||
if ((null_value= (args[0]->null_value || args[1]->null_value ||
|
||||
my_decimal_round(E_DEC_FATAL_ERROR, value, dec, truncate,
|
||||
decimal_value) > 1)))
|
||||
@ -1973,6 +2046,7 @@ double Item_func_units::val_real()
|
||||
|
||||
void Item_func_min_max::fix_length_and_dec()
|
||||
{
|
||||
int max_int_part=0;
|
||||
decimals=0;
|
||||
max_length=0;
|
||||
maybe_null=1;
|
||||
@ -1982,12 +2056,16 @@ void Item_func_min_max::fix_length_and_dec()
|
||||
{
|
||||
set_if_bigger(max_length, args[i]->max_length);
|
||||
set_if_bigger(decimals, args[i]->decimals);
|
||||
set_if_bigger(max_int_part, args[i]->decimal_int_part());
|
||||
if (!args[i]->maybe_null)
|
||||
maybe_null=0;
|
||||
cmp_type=item_cmp_type(cmp_type,args[i]->result_type());
|
||||
}
|
||||
if (cmp_type == STRING_RESULT)
|
||||
agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV);
|
||||
else if ((cmp_type == DECIMAL_RESULT) || (cmp_type == INT_RESULT))
|
||||
max_length= my_decimal_precision_to_length(max_int_part+decimals, decimals,
|
||||
unsigned_flag);
|
||||
}
|
||||
|
||||
|
||||
@ -3914,15 +3992,17 @@ void Item_func_get_user_var::fix_length_and_dec()
|
||||
switch (var_entry->type) {
|
||||
case REAL_RESULT:
|
||||
max_length= DBL_DIG + 8;
|
||||
break;
|
||||
case INT_RESULT:
|
||||
max_length= MAX_BIGINT_WIDTH;
|
||||
decimals=0;
|
||||
break;
|
||||
case STRING_RESULT:
|
||||
max_length= MAX_BLOB_WIDTH;
|
||||
break;
|
||||
case DECIMAL_RESULT:
|
||||
max_length= DECIMAL_MAX_LENGTH;
|
||||
decimals= min(DECIMAL_MAX_LENGTH / 2, NOT_FIXED_DEC - 1);
|
||||
max_length= DECIMAL_MAX_STR_LENGTH;
|
||||
decimals= DECIMAL_MAX_SCALE;
|
||||
break;
|
||||
case ROW_RESULT: // Keep compiler happy
|
||||
default:
|
||||
@ -4773,7 +4853,7 @@ Item_func_sp::fix_length_and_dec()
|
||||
if (result_field)
|
||||
{
|
||||
decimals= result_field->decimals();
|
||||
max_length= result_field->representation_length();
|
||||
max_length= result_field->field_length;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
@ -4785,29 +4865,12 @@ Item_func_sp::fix_length_and_dec()
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!field)
|
||||
field= sp_result_field();
|
||||
|
||||
decimals= field->decimals();
|
||||
max_length= field->representation_length();
|
||||
|
||||
switch (field->result_type()) {
|
||||
case STRING_RESULT:
|
||||
max_length= field->field_length;
|
||||
maybe_null= 1;
|
||||
case REAL_RESULT:
|
||||
case INT_RESULT:
|
||||
case DECIMAL_RESULT:
|
||||
break;
|
||||
case ROW_RESULT:
|
||||
default:
|
||||
// This case should never be chosen
|
||||
DBUG_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (field != result_field)
|
||||
delete field;
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -267,6 +267,8 @@ public:
|
||||
void fix_length_and_dec()
|
||||
{ max_length=args[0]->max_length; unsigned_flag=0; }
|
||||
void print(String *str);
|
||||
uint decimal_precision() const { return args[0]->decimal_precision(); }
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -296,7 +298,7 @@ public:
|
||||
longlong val_int();
|
||||
my_decimal *val_decimal(my_decimal*);
|
||||
enum Item_result result_type () const { return DECIMAL_RESULT; }
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_DECIMAL; }
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
|
||||
void fix_length_and_dec() {};
|
||||
};
|
||||
|
||||
@ -346,6 +348,7 @@ public:
|
||||
class Item_func_div :public Item_num_op
|
||||
{
|
||||
public:
|
||||
uint prec_increment;
|
||||
Item_func_div(Item *a,Item *b) :Item_num_op(a,b) {}
|
||||
longlong int_op() { DBUG_ASSERT(0); return 0; }
|
||||
double real_op();
|
||||
@ -390,6 +393,7 @@ public:
|
||||
const char *func_name() const { return "-"; }
|
||||
void fix_length_and_dec();
|
||||
void fix_num_length_and_dec();
|
||||
uint decimal_precision() const { return args[0]->decimal_precision(); }
|
||||
};
|
||||
|
||||
|
||||
@ -593,7 +597,7 @@ public:
|
||||
double real_op();
|
||||
longlong int_op();
|
||||
my_decimal *decimal_op(my_decimal *);
|
||||
void fix_num_length_and_dec();
|
||||
void fix_length_and_dec();
|
||||
};
|
||||
|
||||
|
||||
|
@ -156,8 +156,8 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table,
|
||||
collation.collation);
|
||||
return make_string_field(table);
|
||||
case DECIMAL_RESULT:
|
||||
return new Field_new_decimal(max_length - (decimals?1:0),
|
||||
maybe_null, name, table, decimals);
|
||||
return new Field_new_decimal(max_length, maybe_null, name, table,
|
||||
decimals, unsigned_flag);
|
||||
case ROW_RESULT:
|
||||
default:
|
||||
// This case should never be choosen
|
||||
@ -372,13 +372,16 @@ void Item_sum_sum::fix_length_and_dec()
|
||||
break;
|
||||
case INT_RESULT:
|
||||
case DECIMAL_RESULT:
|
||||
{
|
||||
/* SUM result can't be longer than length(arg) + length(MAX_ROWS) */
|
||||
max_length= min(args[0]->max_length + DECIMAL_LONGLONG_DIGITS,
|
||||
DECIMAL_MAX_LENGTH);
|
||||
int precision= args[0]->decimal_precision() + DECIMAL_LONGLONG_DIGITS;
|
||||
max_length= my_decimal_precision_to_length(precision, decimals,
|
||||
unsigned_flag);
|
||||
curr_dec_buff= 0;
|
||||
hybrid_type= DECIMAL_RESULT;
|
||||
my_decimal_set_zero(dec_buffs);
|
||||
break;
|
||||
}
|
||||
case ROW_RESULT:
|
||||
default:
|
||||
DBUG_ASSERT(0);
|
||||
@ -725,11 +728,12 @@ void
|
||||
Item_sum_avg_distinct::fix_length_and_dec()
|
||||
{
|
||||
Item_sum_distinct::fix_length_and_dec();
|
||||
prec_increment= current_thd->variables.div_precincrement;
|
||||
/*
|
||||
AVG() will divide val by count. We need to reserve digits
|
||||
after decimal point as the result can be fractional.
|
||||
*/
|
||||
decimals= min(decimals + 4, NOT_FIXED_DEC);
|
||||
decimals= min(decimals + prec_increment, NOT_FIXED_DEC);
|
||||
}
|
||||
|
||||
|
||||
@ -790,14 +794,19 @@ void Item_sum_avg::fix_length_and_dec()
|
||||
{
|
||||
Item_sum_sum::fix_length_and_dec();
|
||||
maybe_null=null_value=1;
|
||||
decimals= min(args[0]->decimals + 4, NOT_FIXED_DEC);
|
||||
prec_increment= current_thd->variables.div_precincrement;
|
||||
if (hybrid_type == DECIMAL_RESULT)
|
||||
{
|
||||
int precision= args[0]->decimal_precision() + prec_increment;
|
||||
decimals= min(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE);
|
||||
max_length= my_decimal_precision_to_length(precision, decimals,
|
||||
unsigned_flag);
|
||||
f_precision= min(precision+DECIMAL_LONGLONG_DIGITS, DECIMAL_MAX_PRECISION);
|
||||
f_scale= args[0]->decimals;
|
||||
max_length= DECIMAL_MAX_LENGTH + (f_scale ? 1 : 0);
|
||||
f_precision= DECIMAL_MAX_LENGTH;
|
||||
dec_bin_size= my_decimal_get_binary_size(f_precision, f_scale);
|
||||
}
|
||||
else
|
||||
decimals= min(args[0]->decimals + prec_increment, NOT_FIXED_DEC);
|
||||
}
|
||||
|
||||
|
||||
@ -822,8 +831,8 @@ Field *Item_sum_avg::create_tmp_field(bool group, TABLE *table,
|
||||
0, name, table, &my_charset_bin);
|
||||
}
|
||||
if (hybrid_type == DECIMAL_RESULT)
|
||||
return new Field_new_decimal(f_precision,
|
||||
maybe_null, name, table, f_scale);
|
||||
return new Field_new_decimal(max_length, maybe_null, name, table,
|
||||
decimals, unsigned_flag);
|
||||
return new Field_double(max_length, maybe_null, name, table, decimals);
|
||||
}
|
||||
|
||||
@ -868,7 +877,7 @@ my_decimal *Item_sum_avg::val_decimal(my_decimal *val)
|
||||
}
|
||||
sum_dec= Item_sum_sum::val_decimal(&sum);
|
||||
int2my_decimal(E_DEC_FATAL_ERROR, count, 0, &cnt);
|
||||
my_decimal_div(E_DEC_FATAL_ERROR, val, sum_dec, &cnt, 4);
|
||||
my_decimal_div(E_DEC_FATAL_ERROR, val, sum_dec, &cnt, prec_increment);
|
||||
return val;
|
||||
}
|
||||
|
||||
@ -905,7 +914,8 @@ Item *Item_sum_std::copy_or_same(THD* thd)
|
||||
|
||||
Item_sum_variance::Item_sum_variance(THD *thd, Item_sum_variance *item):
|
||||
Item_sum_num(thd, item), hybrid_type(item->hybrid_type),
|
||||
cur_dec(item->cur_dec), count(item->count), sample(item->sample)
|
||||
cur_dec(item->cur_dec), count(item->count), sample(item->sample),
|
||||
prec_increment(item->prec_increment)
|
||||
{
|
||||
if (hybrid_type == DECIMAL_RESULT)
|
||||
{
|
||||
@ -929,20 +939,21 @@ void Item_sum_variance::fix_length_and_dec()
|
||||
{
|
||||
DBUG_ENTER("Item_sum_variance::fix_length_and_dec");
|
||||
maybe_null= null_value= 1;
|
||||
decimals= min(args[0]->decimals + 4, NOT_FIXED_DEC);
|
||||
prec_increment= current_thd->variables.div_precincrement;
|
||||
switch (args[0]->result_type()) {
|
||||
case REAL_RESULT:
|
||||
case STRING_RESULT:
|
||||
decimals= min(args[0]->decimals + 4, NOT_FIXED_DEC);
|
||||
hybrid_type= REAL_RESULT;
|
||||
sum= 0.0;
|
||||
break;
|
||||
case INT_RESULT:
|
||||
case DECIMAL_RESULT:
|
||||
/*
|
||||
SUM result can't be longer than length(arg)*2 +
|
||||
digits_after_the_point_to_add
|
||||
*/
|
||||
max_length= args[0]->max_length*2 + 4;
|
||||
{
|
||||
int precision= args[0]->decimal_precision()*2 + prec_increment;
|
||||
decimals= min(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE);
|
||||
max_length= my_decimal_precision_to_length(precision, decimals,
|
||||
unsigned_flag);
|
||||
cur_dec= 0;
|
||||
hybrid_type= DECIMAL_RESULT;
|
||||
my_decimal_set_zero(dec_sum);
|
||||
@ -954,12 +965,15 @@ void Item_sum_variance::fix_length_and_dec()
|
||||
column_value * column_value
|
||||
*/
|
||||
f_scale0= args[0]->decimals;
|
||||
f_precision0= DECIMAL_MAX_LENGTH / 2;
|
||||
f_scale1= min(f_scale0 * 2, NOT_FIXED_DEC - 1);
|
||||
f_precision1= DECIMAL_MAX_LENGTH;
|
||||
f_precision0= min(args[0]->decimal_precision() + DECIMAL_LONGLONG_DIGITS,
|
||||
DECIMAL_MAX_PRECISION);
|
||||
f_scale1= min(args[0]->decimals * 2, DECIMAL_MAX_SCALE);
|
||||
f_precision1= min(args[0]->decimal_precision()*2 + DECIMAL_LONGLONG_DIGITS,
|
||||
DECIMAL_MAX_PRECISION);
|
||||
dec_bin_size0= my_decimal_get_binary_size(f_precision0, f_scale0);
|
||||
dec_bin_size1= my_decimal_get_binary_size(f_precision1, f_scale1);
|
||||
break;
|
||||
}
|
||||
case ROW_RESULT:
|
||||
default:
|
||||
DBUG_ASSERT(0);
|
||||
@ -997,8 +1011,8 @@ Field *Item_sum_variance::create_tmp_field(bool group, TABLE *table,
|
||||
0, name, table, &my_charset_bin);
|
||||
}
|
||||
if (hybrid_type == DECIMAL_RESULT)
|
||||
return new Field_new_decimal(DECIMAL_MAX_LENGTH,
|
||||
maybe_null, name, table, f_scale1 + 4);
|
||||
return new Field_new_decimal(max_length, maybe_null, name, table,
|
||||
decimals, unsigned_flag);
|
||||
return new Field_double(max_length, maybe_null,name,table,decimals);
|
||||
}
|
||||
|
||||
@ -1083,9 +1097,11 @@ my_decimal *Item_sum_variance::val_decimal(my_decimal *dec_buf)
|
||||
int2my_decimal(E_DEC_FATAL_ERROR, count-sample, 0, &count1_buf);
|
||||
my_decimal_mul(E_DEC_FATAL_ERROR, &sum_sqr_buf,
|
||||
dec_sum+cur_dec, dec_sum+cur_dec);
|
||||
my_decimal_div(E_DEC_FATAL_ERROR, dec_buf, &sum_sqr_buf, &count_buf, 2);
|
||||
my_decimal_div(E_DEC_FATAL_ERROR, dec_buf,
|
||||
&sum_sqr_buf, &count_buf, prec_increment);
|
||||
my_decimal_sub(E_DEC_FATAL_ERROR, &sum_sqr_buf, dec_sqr+cur_dec, dec_buf);
|
||||
my_decimal_div(E_DEC_FATAL_ERROR, dec_buf, &sum_sqr_buf, &count1_buf, 2);
|
||||
my_decimal_div(E_DEC_FATAL_ERROR, dec_buf,
|
||||
&sum_sqr_buf, &count1_buf, prec_increment);
|
||||
return dec_buf;
|
||||
}
|
||||
|
||||
@ -1930,9 +1946,11 @@ Item_avg_field::Item_avg_field(Item_result res_type, Item_sum_avg *item)
|
||||
name=item->name;
|
||||
decimals=item->decimals;
|
||||
max_length= item->max_length;
|
||||
unsigned_flag= item->unsigned_flag;
|
||||
field=item->result_field;
|
||||
maybe_null=1;
|
||||
hybrid_type= res_type;
|
||||
prec_increment= item->prec_increment;
|
||||
if (hybrid_type == DECIMAL_RESULT)
|
||||
{
|
||||
f_scale= item->f_scale;
|
||||
@ -1941,7 +1959,6 @@ Item_avg_field::Item_avg_field(Item_result res_type, Item_sum_avg *item)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double Item_avg_field::val_real()
|
||||
{
|
||||
// fix_fields() never calls for this Item
|
||||
@ -1982,7 +1999,8 @@ my_decimal *Item_avg_field::val_decimal(my_decimal *dec_buf)
|
||||
binary2my_decimal(E_DEC_FATAL_ERROR,
|
||||
field->ptr, &dec_field, f_precision, f_scale);
|
||||
int2my_decimal(E_DEC_FATAL_ERROR, count, 0, &dec_count);
|
||||
my_decimal_div(E_DEC_FATAL_ERROR, dec_buf, &dec_field, &dec_count, 4);
|
||||
my_decimal_div(E_DEC_FATAL_ERROR, dec_buf,
|
||||
&dec_field, &dec_count, prec_increment);
|
||||
return dec_buf;
|
||||
}
|
||||
|
||||
@ -2054,9 +2072,11 @@ Item_variance_field::Item_variance_field(Item_sum_variance *item)
|
||||
name=item->name;
|
||||
decimals=item->decimals;
|
||||
max_length=item->max_length;
|
||||
unsigned_flag= item->unsigned_flag;
|
||||
field=item->result_field;
|
||||
maybe_null=1;
|
||||
sample= item->sample;
|
||||
prec_increment= item->prec_increment;
|
||||
if ((hybrid_type= item->hybrid_type) == DECIMAL_RESULT)
|
||||
{
|
||||
f_scale0= item->f_scale0;
|
||||
@ -2116,9 +2136,10 @@ my_decimal *Item_variance_field::val_decimal(my_decimal *dec_buf)
|
||||
binary2my_decimal(E_DEC_FATAL_ERROR, field->ptr+dec_bin_size0,
|
||||
&dec_sqr, f_precision1, f_scale1);
|
||||
my_decimal_mul(E_DEC_FATAL_ERROR, &tmp, &dec_sum, &dec_sum);
|
||||
my_decimal_div(E_DEC_FATAL_ERROR, dec_buf, &tmp, &dec_count, 2);
|
||||
my_decimal_div(E_DEC_FATAL_ERROR, dec_buf, &tmp, &dec_count, prec_increment);
|
||||
my_decimal_sub(E_DEC_FATAL_ERROR, &dec_sum, &dec_sqr, dec_buf);
|
||||
my_decimal_div(E_DEC_FATAL_ERROR, dec_buf, &dec_sum, &dec1_count, 2);
|
||||
my_decimal_div(E_DEC_FATAL_ERROR, dec_buf,
|
||||
&dec_sum, &dec1_count, prec_increment);
|
||||
return dec_buf;
|
||||
}
|
||||
|
||||
|
@ -237,6 +237,7 @@ private:
|
||||
Item_sum_avg_distinct(THD *thd, Item_sum_avg_distinct *original)
|
||||
:Item_sum_distinct(thd, original) {}
|
||||
public:
|
||||
uint prec_increment;
|
||||
Item_sum_avg_distinct(Item *item_arg) : Item_sum_distinct(item_arg) {}
|
||||
|
||||
void fix_length_and_dec();
|
||||
@ -343,8 +344,8 @@ class Item_avg_field :public Item_result_field
|
||||
public:
|
||||
Field *field;
|
||||
Item_result hybrid_type;
|
||||
uint f_precision, f_scale;
|
||||
uint dec_bin_size;
|
||||
uint f_precision, f_scale, dec_bin_size;
|
||||
uint prec_increment;
|
||||
Item_avg_field(Item_result res_type, Item_sum_avg *item);
|
||||
enum Type type() const { return FIELD_AVG_ITEM; }
|
||||
double val_real();
|
||||
@ -366,12 +367,14 @@ class Item_sum_avg :public Item_sum_sum
|
||||
{
|
||||
public:
|
||||
ulonglong count;
|
||||
uint f_precision, f_scale;
|
||||
uint dec_bin_size;
|
||||
uint prec_increment;
|
||||
uint f_precision, f_scale, dec_bin_size;
|
||||
|
||||
Item_sum_avg(Item *item_par) :Item_sum_sum(item_par), count(0) {}
|
||||
Item_sum_avg(THD *thd, Item_sum_avg *item)
|
||||
:Item_sum_sum(thd, item), count(item->count) {}
|
||||
:Item_sum_sum(thd, item), count(item->count),
|
||||
prec_increment(item->prec_increment) {}
|
||||
|
||||
void fix_length_and_dec();
|
||||
enum Sumfunctype sum_func () const {return AVG_FUNC;}
|
||||
void clear();
|
||||
@ -402,6 +405,7 @@ public:
|
||||
uint f_precision1, f_scale1;
|
||||
uint dec_bin_size0, dec_bin_size1;
|
||||
uint sample;
|
||||
uint prec_increment;
|
||||
Item_variance_field(Item_sum_variance *item);
|
||||
enum Type type() const {return FIELD_VARIANCE_ITEM; }
|
||||
double val_real();
|
||||
@ -446,6 +450,7 @@ public:
|
||||
uint f_precision1, f_scale1;
|
||||
uint dec_bin_size0, dec_bin_size1;
|
||||
uint sample;
|
||||
uint prec_increment;
|
||||
|
||||
Item_sum_variance(Item *item_par, uint sample_arg) :Item_sum_num(item_par),
|
||||
hybrid_type(REAL_RESULT), cur_dec(0), count(0), sample(sample_arg)
|
||||
|
@ -81,7 +81,7 @@ int decimal_operation_results(int result)
|
||||
*/
|
||||
|
||||
int my_decimal2string(uint mask, const my_decimal *d,
|
||||
int fixed_prec, int fixed_dec,
|
||||
uint fixed_prec, uint fixed_dec,
|
||||
char filler, String *str)
|
||||
{
|
||||
int length= (fixed_prec ? (fixed_prec + 1) : my_decimal_string_length(d));
|
||||
@ -89,7 +89,7 @@ int my_decimal2string(uint mask, const my_decimal *d,
|
||||
if (str->alloc(length))
|
||||
return check_result(mask, E_DEC_OOM);
|
||||
result= decimal2string((decimal_t*) d, (char*) str->ptr(),
|
||||
&length, fixed_prec, fixed_dec,
|
||||
&length, (int)fixed_prec, fixed_dec,
|
||||
filler);
|
||||
str->length(length);
|
||||
return check_result(mask, result);
|
||||
@ -123,7 +123,7 @@ int my_decimal2binary(uint mask, const my_decimal *d, char *bin, int prec,
|
||||
int err1= E_DEC_OK, err2;
|
||||
my_decimal rounded;
|
||||
my_decimal2decimal(d, &rounded);
|
||||
decimal_optimize_fraction(&rounded);
|
||||
rounded.frac= decimal_actual_fraction(&rounded);
|
||||
if (scale < rounded.frac)
|
||||
{
|
||||
err1= E_DEC_TRUNCATED;
|
||||
@ -220,18 +220,16 @@ 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)
|
||||
const char *dbug_decimal_as_string(char *buff, const my_decimal *val)
|
||||
{
|
||||
char buff[DECIMAL_MAX_STR_LENGTH];
|
||||
String str(buff, sizeof(buff), &my_charset_bin);
|
||||
int length= DECIMAL_MAX_STR_LENGTH;
|
||||
if (!val)
|
||||
str.set("NULL", 4, &my_charset_bin);
|
||||
else
|
||||
my_decimal2string(0, val, 0, 0, 0, &str);
|
||||
DBUG_PRINT(tag, (format, (char*) str.ptr()));
|
||||
return "NULL";
|
||||
(void)decimal2string((decimal_t*) val, buff, &length, 0,0,0);
|
||||
return buff;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /*DBUG_OFF*/
|
||||
|
||||
|
||||
#endif /*MYSQL_CLIENT*/
|
||||
|
@ -35,27 +35,27 @@ C_MODE_END
|
||||
#define DECIMAL_LONG_DIGITS 10
|
||||
#define DECIMAL_LONG3_DIGITS 8
|
||||
|
||||
/* number of digits on which we increase scale of devision result */
|
||||
#define DECIMAL_DIV_SCALE_INCREASE 5
|
||||
|
||||
/* maximum length of buffer in our big digits (uint32) */
|
||||
#define DECIMAL_BUFF_LENGTH 8
|
||||
#define DECIMAL_BUFF_LENGTH 9
|
||||
/*
|
||||
maximum guaranteed length of number in decimal digits (number of our
|
||||
maximum guaranteed precision of number in decimal digits (number of our
|
||||
digits * number of decimal digits in one our big digit - number of decimal
|
||||
digits in one our big digit decreased on 1 (because we always put decimal
|
||||
point on the border of our big digits))
|
||||
*/
|
||||
#define DECIMAL_MAX_LENGTH ((8 * 9) - 8)
|
||||
#define DECIMAL_MAX_PRECISION ((DECIMAL_BUFF_LENGTH * 9) - 8*2)
|
||||
#define DECIMAL_MAX_SCALE 30
|
||||
#define DECIMAL_NOT_SPECIFIED 31
|
||||
|
||||
/*
|
||||
maximum length of string representation (number of maximum decimal
|
||||
digits + 1 position for sign + 1 position for decimal point)
|
||||
*/
|
||||
#define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_LENGTH + 2)
|
||||
#define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_PRECISION + 2)
|
||||
/*
|
||||
maximum size of packet length
|
||||
*/
|
||||
#define DECIMAL_MAX_FIELD_SIZE DECIMAL_MAX_LENGTH
|
||||
#define DECIMAL_MAX_FIELD_SIZE DECIMAL_MAX_PRECISION
|
||||
|
||||
|
||||
inline uint my_decimal_size(uint precision, uint scale)
|
||||
@ -68,6 +68,12 @@ inline uint my_decimal_size(uint precision, uint scale)
|
||||
}
|
||||
|
||||
|
||||
inline int my_decimal_int_part(uint precision, uint decimals)
|
||||
{
|
||||
return precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
my_decimal class limits 'decimal_t' type to what we need in MySQL
|
||||
It contains internally all necessary space needed by the instance so
|
||||
@ -99,15 +105,16 @@ public:
|
||||
|
||||
bool sign() const { return decimal_t::sign; }
|
||||
void sign(bool s) { decimal_t::sign= s; }
|
||||
uint precision() const { return intg + frac; }
|
||||
};
|
||||
|
||||
|
||||
#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);
|
||||
const char *dbug_decimal_as_string(char *buff, const my_decimal *val);
|
||||
#else
|
||||
#define dbug_print_decimal(A,B,C)
|
||||
#define dbug_decimal_as_string(A) NULL
|
||||
#endif
|
||||
|
||||
#ifndef MYSQL_CLIENT
|
||||
@ -126,6 +133,18 @@ inline int check_result(uint mask, int result)
|
||||
return result;
|
||||
}
|
||||
|
||||
inline uint my_decimal_length_to_precision(uint length, uint scale,
|
||||
bool unsigned_flag)
|
||||
{
|
||||
return (uint) (length - (scale>0 ? 1:0) - (unsigned_flag ? 0:1));
|
||||
}
|
||||
|
||||
inline uint32 my_decimal_precision_to_length(uint precision, uint8 scale,
|
||||
bool unsigned_flag)
|
||||
{
|
||||
set_if_smaller(precision, DECIMAL_MAX_PRECISION);
|
||||
return (uint32)(precision + (scale>0 ? 1:0) + (unsigned_flag ? 0:1));
|
||||
}
|
||||
|
||||
inline
|
||||
int my_decimal_string_length(const my_decimal *d)
|
||||
@ -209,8 +228,8 @@ int my_decimal_ceiling(uint mask, const my_decimal *from, my_decimal *to)
|
||||
|
||||
|
||||
#ifndef MYSQL_CLIENT
|
||||
int my_decimal2string(uint mask, const my_decimal *d, int fixed_prec,
|
||||
int fixed_dec, char filler, String *str);
|
||||
int my_decimal2string(uint mask, const my_decimal *d, uint fixed_prec,
|
||||
uint fixed_dec, char filler, String *str);
|
||||
#endif
|
||||
|
||||
inline
|
||||
@ -326,7 +345,8 @@ int my_decimal_cmp(const my_decimal *a, const my_decimal *b)
|
||||
inline
|
||||
void max_my_decimal(my_decimal *to, int precision, int frac)
|
||||
{
|
||||
DBUG_ASSERT(precision <= DECIMAL_MAX_LENGTH);
|
||||
DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION)&&
|
||||
(frac <= DECIMAL_MAX_SCALE));
|
||||
max_decimal(precision, frac, (decimal_t*) to);
|
||||
}
|
||||
|
||||
|
@ -4219,7 +4219,8 @@ enum options_mysqld
|
||||
OPT_PRELOAD_BUFFER_SIZE,
|
||||
OPT_QUERY_CACHE_LIMIT, OPT_QUERY_CACHE_MIN_RES_UNIT, OPT_QUERY_CACHE_SIZE,
|
||||
OPT_QUERY_CACHE_TYPE, OPT_QUERY_CACHE_WLOCK_INVALIDATE, OPT_RECORD_BUFFER,
|
||||
OPT_RECORD_RND_BUFFER, OPT_RELAY_LOG_SPACE_LIMIT, OPT_RELAY_LOG_PURGE,
|
||||
OPT_RECORD_RND_BUFFER, OPT_DIV_PRECINCREMENT, OPT_RELAY_LOG_SPACE_LIMIT,
|
||||
OPT_RELAY_LOG_PURGE,
|
||||
OPT_SLAVE_NET_TIMEOUT, OPT_SLAVE_COMPRESSED_PROTOCOL, OPT_SLOW_LAUNCH_TIME,
|
||||
OPT_SLAVE_TRANS_RETRIES, OPT_READONLY, OPT_DEBUGGING,
|
||||
OPT_SORT_BUFFER, OPT_TABLE_CACHE,
|
||||
@ -5451,6 +5452,11 @@ The minimum value for this variable is 4096.",
|
||||
(gptr*) &max_system_variables.read_rnd_buff_size, 0,
|
||||
GET_ULONG, REQUIRED_ARG, 256*1024L, IO_SIZE*2+MALLOC_OVERHEAD,
|
||||
~0L, MALLOC_OVERHEAD, IO_SIZE, 0},
|
||||
{"div_precision_increment", OPT_DIV_PRECINCREMENT,
|
||||
"Precision of the result of '/' operator will be increased on that value.",
|
||||
(gptr*) &global_system_variables.div_precincrement,
|
||||
(gptr*) &max_system_variables.div_precincrement, 0, GET_ULONG,
|
||||
REQUIRED_ARG, 4, 0, DECIMAL_MAX_SCALE, 0, 0, 0},
|
||||
{"record_buffer", OPT_RECORD_BUFFER,
|
||||
"Alias for read_buffer_size",
|
||||
(gptr*) &global_system_variables.read_buff_size,
|
||||
|
@ -298,6 +298,8 @@ sys_var_thd_ulong sys_read_buff_size("read_buffer_size",
|
||||
sys_var_bool_ptr sys_readonly("read_only", &opt_readonly);
|
||||
sys_var_thd_ulong sys_read_rnd_buff_size("read_rnd_buffer_size",
|
||||
&SV::read_rnd_buff_size);
|
||||
sys_var_thd_ulong sys_div_precincrement("div_precision_increment",
|
||||
&SV::div_precincrement);
|
||||
#ifdef HAVE_REPLICATION
|
||||
sys_var_bool_ptr sys_relay_log_purge("relay_log_purge",
|
||||
&relay_log_purge);
|
||||
@ -570,6 +572,7 @@ sys_var *sys_variables[]=
|
||||
&sys_connect_timeout,
|
||||
&sys_date_format,
|
||||
&sys_datetime_format,
|
||||
&sys_div_precincrement,
|
||||
&sys_default_week_format,
|
||||
&sys_delay_key_write,
|
||||
&sys_delayed_insert_limit,
|
||||
@ -758,6 +761,7 @@ struct show_var_st init_vars[]= {
|
||||
{"datadir", mysql_real_data_home, SHOW_CHAR},
|
||||
{sys_date_format.name, (char*) &sys_date_format, SHOW_SYS},
|
||||
{sys_datetime_format.name, (char*) &sys_datetime_format, SHOW_SYS},
|
||||
{sys_div_precincrement.name,(char*) &sys_div_precincrement,SHOW_SYS},
|
||||
{sys_default_week_format.name, (char*) &sys_default_week_format, SHOW_SYS},
|
||||
{sys_delay_key_write.name, (char*) &sys_delay_key_write, SHOW_SYS},
|
||||
{sys_delayed_insert_limit.name, (char*) &sys_delayed_insert_limit,SHOW_SYS},
|
||||
|
@ -164,7 +164,10 @@ sp_eval_func_item(THD *thd, Item *it, enum enum_field_types type)
|
||||
it= new Item_null();
|
||||
else
|
||||
it= new Item_decimal(val);
|
||||
dbug_print_decimal("info", "DECIMAL_RESULT: %s", val);
|
||||
#ifndef DBUG_OFF
|
||||
char dbug_buff[DECIMAL_MAX_STR_LENGTH+1];
|
||||
DBUG_PRINT("info", ("DECIMAL_RESULT: %s", dbug_decimal_as_string(dbug_buff, val)));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case STRING_RESULT:
|
||||
|
@ -523,6 +523,7 @@ struct system_variables
|
||||
ulong query_cache_type;
|
||||
ulong read_buff_size;
|
||||
ulong read_rnd_buff_size;
|
||||
ulong div_precincrement;
|
||||
ulong sortbuff_size;
|
||||
ulong table_type;
|
||||
ulong tmp_table_size;
|
||||
|
@ -5471,9 +5471,14 @@ new_create_field(THD *thd, char *field_name, enum_field_types type,
|
||||
}
|
||||
new_field->pack_length=
|
||||
my_decimal_get_binary_size(new_field->length, new_field->decimals);
|
||||
if (new_field->length <= DECIMAL_MAX_LENGTH &&
|
||||
if (new_field->length <= DECIMAL_MAX_PRECISION &&
|
||||
new_field->length >= new_field->decimals)
|
||||
{
|
||||
new_field->length=
|
||||
my_decimal_precision_to_length(new_field->length, new_field->decimals,
|
||||
type_modifier & UNSIGNED_FLAG);
|
||||
break;
|
||||
}
|
||||
my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
|
||||
DBUG_RETURN(NULL);
|
||||
case MYSQL_TYPE_VARCHAR:
|
||||
|
@ -7781,9 +7781,8 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
|
||||
new_field= item->make_string_field(table);
|
||||
break;
|
||||
case DECIMAL_RESULT:
|
||||
new_field= new Field_new_decimal(item->max_length - (item->decimals?1:0),
|
||||
maybe_null,
|
||||
item->name, table, item->decimals);
|
||||
new_field= new Field_new_decimal(item->max_length, maybe_null, item->name,
|
||||
table, item->decimals, item->unsigned_flag);
|
||||
break;
|
||||
case ROW_RESULT:
|
||||
default:
|
||||
|
@ -2362,10 +2362,10 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables,
|
||||
strlen((const char*) pos), cs);
|
||||
if (field->has_charset())
|
||||
{
|
||||
table->field[8]->store((longlong) field->representation_length()/
|
||||
table->field[8]->store((longlong) field->field_length/
|
||||
field->charset()->mbmaxlen);
|
||||
table->field[8]->set_notnull();
|
||||
table->field[9]->store((longlong) field->representation_length());
|
||||
table->field[9]->store((longlong) field->field_length);
|
||||
table->field[9]->set_notnull();
|
||||
}
|
||||
|
||||
@ -2373,7 +2373,8 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables,
|
||||
uint dec =field->decimals();
|
||||
switch (field->type()) {
|
||||
case FIELD_TYPE_NEWDECIMAL:
|
||||
table->field[10]->store((longlong) field->field_length);
|
||||
table->field[10]->store((longlong)
|
||||
((Field_new_decimal*)field)->precision);
|
||||
table->field[10]->set_notnull();
|
||||
table->field[11]->store((longlong) field->decimals());
|
||||
table->field[11]->set_notnull();
|
||||
|
@ -274,20 +274,20 @@ static dec1 *remove_leading_zeroes(decimal_t *from, int *intg_result)
|
||||
|
||||
|
||||
/*
|
||||
Remove ending 0 digits from fraction part
|
||||
Count actual length of fraction part (without ending zeroes)
|
||||
|
||||
SYNOPSIS
|
||||
decimal_optimize_fraction()
|
||||
decimal_actual_fraction()
|
||||
from number for processing
|
||||
*/
|
||||
|
||||
void decimal_optimize_fraction(decimal_t *from)
|
||||
int decimal_actual_fraction(decimal_t *from)
|
||||
{
|
||||
int frac= from->frac, i;
|
||||
dec1 *buf0= from->buf + ROUND_UP(from->intg) + ROUND_UP(frac) - 1;
|
||||
|
||||
if (frac == 0)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
i= ((frac - 1) % DIG_PER_DEC1 + 1);
|
||||
while (frac > 0 && *buf0 == 0)
|
||||
@ -302,7 +302,7 @@ void decimal_optimize_fraction(decimal_t *from)
|
||||
*buf0 % powers10[i++] == 0;
|
||||
frac--);
|
||||
}
|
||||
from->frac= frac;
|
||||
return frac;
|
||||
}
|
||||
|
||||
|
||||
@ -335,20 +335,12 @@ int decimal2string(decimal_t *from, char *to, int *to_len,
|
||||
int len, intg, frac= from->frac, i, intg_len, frac_len, fill;
|
||||
/* number digits before decimal point */
|
||||
int fixed_intg= (fixed_precision ?
|
||||
(fixed_precision -
|
||||
(from->sign ? 1 : 0) -
|
||||
(fixed_decimals ? 1 : 0) -
|
||||
fixed_decimals) :
|
||||
0);
|
||||
(fixed_precision - fixed_decimals) : 0);
|
||||
int error=E_DEC_OK;
|
||||
char *s=to;
|
||||
dec1 *buf, *buf0=from->buf, tmp;
|
||||
|
||||
DBUG_ASSERT(*to_len >= 2+from->sign);
|
||||
DBUG_ASSERT(fixed_precision == 0 ||
|
||||
(fixed_precision < *to_len &&
|
||||
fixed_precision > ((from->sign ? 1 : 0) +
|
||||
(fixed_decimals ? 1 : 0))));
|
||||
|
||||
/* removing leading zeroes */
|
||||
buf0= remove_leading_zeroes(from, &intg);
|
||||
@ -2609,7 +2601,7 @@ void test_fr(const char *s1, const char *orig)
|
||||
printf("%-40s => ", s);
|
||||
end= strend(s1);
|
||||
string2decimal(s1, &a, &end);
|
||||
decimal_optimize_fraction(&a);
|
||||
a.frac= decimal_actual_fraction(&a);
|
||||
print_decimal(&a, orig, 0, 0);
|
||||
printf("\n");
|
||||
}
|
||||
@ -2947,7 +2939,7 @@ int main()
|
||||
test_sh("123456789.987654321", 0, "123456789.987654321", 0);
|
||||
a.len= sizeof(buf1)/sizeof(dec1);
|
||||
|
||||
printf("==== decimal_optimize_fraction ====\n");
|
||||
printf("==== decimal_actual_fraction ====\n");
|
||||
test_fr("1.123456789000000000", "1.123456789");
|
||||
test_fr("1.12345678000000000", "1.12345678");
|
||||
test_fr("1.1234567000000000", "1.1234567");
|
||||
|
Loading…
x
Reference in New Issue
Block a user