summaryrefslogtreecommitdiff
path: root/sql/item.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item.cc')
-rw-r--r--sql/item.cc76
1 files changed, 41 insertions, 35 deletions
diff --git a/sql/item.cc b/sql/item.cc
index 7d0a5fbdccc..f5c7f2d7c05 100644
--- a/sql/item.cc
+++ b/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);