summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2016-06-27 15:41:51 +0200
committerSergei Golubchik <serg@mariadb.org>2016-06-30 11:43:02 +0200
commit23d03a1b1e486da353f20964a1b91068bec209c0 (patch)
tree7fcbd95cf634b24e7f162a9b38559f32e31df6b5 /sql
parent60916a8b9e81b9e9de14fa737848419f45ff899a (diff)
downloadmariadb-git-23d03a1b1e486da353f20964a1b91068bec209c0.tar.gz
parse negative numbers into one item
use Item->neg to convert generate negative Item_num's instead of Item_func_neg(Item_num). Based on the following commit: Author: Monty <monty@mariadb.org> Date: Mon May 30 22:44:00 2016 +0300 Make negative number their own token The negation (-) operator will call Item->neg() one underlying numeric constants and remove itself (like the NOT() function does today for other NOT functions. This simplifies things - -1 is not anymore an expression but a basic_const_item - improves optimizer - DEFAULT -1 doesn't need special handling anymore - When we add DEFAULT expressions, -1 will be treated exactly like 1 - printing of items doesn't anymore put braces around all negative numbers Other things fixed: - Fixed that longlong converted to decimal's has a more appropriate size - Fixed that "-0.0" read into a decimal is interpreted as 0.0
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc12
-rw-r--r--sql/item.cc59
-rw-r--r--sql/item.h16
-rw-r--r--sql/sql_yacc.yy2
4 files changed, 70 insertions, 19 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 0e2bc724db0..f15e9979ff2 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -9769,12 +9769,6 @@ bool Column_definition::check(THD *thd)
}
}
- if (length > MAX_FIELD_BLOBLENGTH)
- {
- my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), field_name, MAX_FIELD_BLOBLENGTH);
- DBUG_RETURN(TRUE);
- }
-
if (def)
{
/*
@@ -10080,6 +10074,12 @@ bool Column_definition::check(THD *thd)
field_name, max_field_charlength); /* purecov: inspected */
DBUG_RETURN(TRUE);
}
+ else if (length > MAX_FIELD_BLOBLENGTH)
+ {
+ my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), field_name, MAX_FIELD_BLOBLENGTH);
+ DBUG_RETURN(1);
+ }
+
if ((~allowed_type_modifier) & flags & conditional_type_modifiers)
{
my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
diff --git a/sql/item.cc b/sql/item.cc
index 6566f3ca533..05d4cc86f7a 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -5998,9 +5998,64 @@ Item *Item_int_with_ref::clone_item(THD *thd)
}
-Item_num *Item_uint::neg(THD *thd)
+Item *Item::neg(THD *thd)
{
- Item_decimal *item= new (thd->mem_root) Item_decimal(thd, value, 1);
+ return new (thd->mem_root) Item_func_neg(thd, this);
+}
+
+Item *Item_int::neg(THD *thd)
+{
+ /*
+ The following if should never be true with code generated by
+ our parser as LONGLONG_MIN values will be stored as decimal.
+ The code is here in case someone generates an int from inside
+ MariaDB
+ */
+ if (unlikely(value == LONGLONG_MIN))
+ {
+ /* Precision for int not big enough; Convert constant to decimal */
+ Item_decimal *item= new (thd->mem_root) Item_decimal(thd, value, 0);
+ return item ? item->neg(thd) : item;
+ }
+ if (value > 0)
+ max_length++;
+ else if (value < 0 && max_length)
+ max_length--;
+ value= -value;
+ name= 0;
+ return this;
+}
+
+Item *Item_decimal::neg(THD *thd)
+{
+ my_decimal_neg(&decimal_value);
+ unsigned_flag= 0;
+ name= 0;
+ max_length= my_decimal_precision_to_length_no_truncation(
+ decimal_value.intg + decimals, decimals, unsigned_flag);
+ return this;
+}
+
+Item *Item_float::neg(THD *thd)
+{
+ if (value > 0)
+ max_length++;
+ else if (value < 0 && max_length)
+ max_length--;
+ value= -value;
+ name= presentation= 0 ;
+ return this;
+}
+
+Item *Item_uint::neg(THD *thd)
+{
+ Item_decimal *item;
+ if (((ulonglong)value) <= LONGLONG_MAX)
+ return new (thd->mem_root) Item_int(thd, -value, max_length+1);
+ if (value == LONGLONG_MIN)
+ return new (thd->mem_root) Item_int(thd, value, max_length+1);
+ if (!(item= new (thd->mem_root) Item_decimal(thd, value, 1)))
+ return 0;
return item->neg(thd);
}
diff --git a/sql/item.h b/sql/item.h
index 67d683b15ff..22e44719706 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1846,6 +1846,8 @@ public:
/* how much position should be reserved for Exists2In transformation */
virtual uint exists2in_reserved_items() { return 0; };
+ virtual Item *neg(THD *thd);
+
/**
Inform the item that it is located under a NOT, which is a top-level item.
*/
@@ -2261,7 +2263,6 @@ class Item_num: public Item_basic_constant
{
public:
Item_num(THD *thd): Item_basic_constant(thd) { collation.set_numeric(); }
- virtual Item_num *neg(THD *thd)= 0;
Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs);
bool check_partition_func_processor(uchar *int_arg) { return FALSE;}
bool check_vcol_func_processor(uchar *arg) { return FALSE;}
@@ -2834,7 +2835,7 @@ public:
bool basic_const_item() const { return 1; }
Item *clone_item(THD *thd);
virtual void print(String *str, enum_query_type query_type);
- Item_num *neg(THD *thd) { value= -value; return this; }
+ Item *neg(THD *thd);
uint decimal_precision() const
{ return (uint) (max_length - MY_TEST(value < 0)); }
bool eq(const Item *item, bool binary_cmp) const
@@ -2855,7 +2856,7 @@ public:
String *val_str(String*);
Item *clone_item(THD *thd);
virtual void print(String *str, enum_query_type query_type);
- Item_num *neg(THD *thd);
+ Item *neg(THD *thd);
uint decimal_precision() const { return max_length; }
};
@@ -2899,12 +2900,7 @@ public:
bool basic_const_item() const { return 1; }
Item *clone_item(THD *thd);
virtual void print(String *str, enum_query_type query_type);
- Item_num *neg(THD *thd)
- {
- my_decimal_neg(&decimal_value);
- unsigned_flag= !decimal_value.sign();
- return this;
- }
+ Item *neg(THD *thd);
uint decimal_precision() const { return decimal_value.precision(); }
bool eq(const Item *, bool binary_cmp) const;
void set_decimal_value(my_decimal *value_par);
@@ -2954,7 +2950,7 @@ public:
my_decimal *val_decimal(my_decimal *);
bool basic_const_item() const { return 1; }
Item *clone_item(THD *thd);
- Item_num *neg(THD *thd) { value= -value; return this; }
+ Item *neg(THD *thd);
virtual void print(String *str, enum_query_type query_type);
bool eq(const Item *item, bool binary_cmp) const
{ return real_eq(value, item); }
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 7ab11716f93..c971373d31b 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -9461,7 +9461,7 @@ simple_expr:
}
| '-' simple_expr %prec NEG
{
- $$= new (thd->mem_root) Item_func_neg(thd, $2);
+ $$= $2->neg(thd);
if ($$ == NULL)
MYSQL_YYABORT;
}