summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/cast.result40
-rw-r--r--mysql-test/r/create.result4
-rw-r--r--mysql-test/r/metadata.result204
-rw-r--r--mysql-test/t/cast.test26
-rw-r--r--mysql-test/t/metadata.test112
-rw-r--r--sql/item.h17
-rw-r--r--sql/item_func.cc8
-rw-r--r--sql/item_func.h45
-rw-r--r--sql/item_timefunc.h7
-rw-r--r--sql/sql_type.cc26
-rw-r--r--sql/sql_type.h1
11 files changed, 451 insertions, 39 deletions
diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result
index 69979854d8e..3c9cbb18bcb 100644
--- a/mysql-test/r/cast.result
+++ b/mysql-test/r/cast.result
@@ -762,7 +762,7 @@ SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`CONCAT(CAST(REPEAT('9', 1000) AS SIGNED))` varchar(21) NOT NULL,
- `CONCAT(CAST(REPEAT('9', 1000) AS UNSIGNED))` varchar(21) NOT NULL
+ `CONCAT(CAST(REPEAT('9', 1000) AS UNSIGNED))` varchar(20) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
# End of test for Bug#13581962, Bug#14096619
@@ -1130,3 +1130,41 @@ c LENGTH(c)
DROP PROCEDURE p1;
SET sql_mode=DEFAULT;
+#
+# MDEV-12852 Out-of-range errors when CAST(1-2 AS UNSIGNED
+#
+SET sql_mode=STRICT_ALL_TABLES;
+CREATE TABLE t1 AS SELECT
+CAST(-1 AS UNSIGNED),
+CAST(1-2 AS UNSIGNED);
+Warnings:
+Note 1105 Cast to unsigned converted negative integer to it's positive complement
+Note 1105 Cast to unsigned converted negative integer to it's positive complement
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `CAST(-1 AS UNSIGNED)` bigint(20) unsigned NOT NULL,
+ `CAST(1-2 AS UNSIGNED)` bigint(20) unsigned NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+CAST(-1 AS UNSIGNED) CAST(1-2 AS UNSIGNED)
+18446744073709551615 18446744073709551615
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
+#
+# MDEV-12853 Out-of-range errors when CAST('-1' AS UNSIGNED
+#
+SET sql_mode=STRICT_ALL_TABLES;
+CREATE TABLE t1 AS SELECT CAST('-1' AS UNSIGNED);
+Warnings:
+Note 1105 Cast to unsigned converted negative integer to it's positive complement
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `CAST('-1' AS UNSIGNED)` bigint(20) unsigned NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+CAST('-1' AS UNSIGNED)
+18446744073709551615
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index 1a3289b2618..798faaa1198 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -482,8 +482,8 @@ from t1;
explain t2;
Field Type Null Key Default Extra
a int(11) YES NULL
-b bigint(11) NO NULL
-c bigint(10) unsigned NO NULL
+b int(11) NO NULL
+c int(10) unsigned NO NULL
d date YES NULL
e varchar(1) YES NULL
f datetime YES NULL
diff --git a/mysql-test/r/metadata.result b/mysql-test/r/metadata.result
index 7e57fa74663..b4450e6925d 100644
--- a/mysql-test/r/metadata.result
+++ b/mysql-test/r/metadata.result
@@ -568,3 +568,207 @@ def test t1 t1 @:=1e0 @:=1e0 5 3 1 N 36865 31 63
@:=1e0
1
DROP TABLE t1;
+#
+# MDEV-12869 Wrong metadata for integer additive and multiplicative operators
+#
+SELECT
+1+1,
+11+1,
+111+1,
+1111+1,
+11111+1,
+111111+1,
+1111111+1,
+11111111+1,
+111111111+1 LIMIT 0;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def 1+1 3 3 0 N 32897 0 63
+def 11+1 3 4 0 N 32897 0 63
+def 111+1 3 5 0 N 32897 0 63
+def 1111+1 3 6 0 N 32897 0 63
+def 11111+1 3 7 0 N 32897 0 63
+def 111111+1 3 8 0 N 32897 0 63
+def 1111111+1 3 9 0 N 32897 0 63
+def 11111111+1 8 10 0 N 32897 0 63
+def 111111111+1 8 11 0 N 32897 0 63
+1+1 11+1 111+1 1111+1 11111+1 111111+1 1111111+1 11111111+1 111111111+1
+SELECT
+1-1,
+11-1,
+111-1,
+1111-1,
+11111-1,
+111111-1,
+1111111-1,
+11111111-1,
+111111111-1 LIMIT 0;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def 1-1 3 3 0 N 32897 0 63
+def 11-1 3 4 0 N 32897 0 63
+def 111-1 3 5 0 N 32897 0 63
+def 1111-1 3 6 0 N 32897 0 63
+def 11111-1 3 7 0 N 32897 0 63
+def 111111-1 3 8 0 N 32897 0 63
+def 1111111-1 3 9 0 N 32897 0 63
+def 11111111-1 8 10 0 N 32897 0 63
+def 111111111-1 8 11 0 N 32897 0 63
+1-1 11-1 111-1 1111-1 11111-1 111111-1 1111111-1 11111111-1 111111111-1
+SELECT
+1*1,
+11*1,
+111*1,
+1111*1,
+11111*1,
+111111*1,
+1111111*1,
+11111111*1,
+111111111*1 LIMIT 0;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def 1*1 3 3 0 N 32897 0 63
+def 11*1 3 4 0 N 32897 0 63
+def 111*1 3 5 0 N 32897 0 63
+def 1111*1 3 6 0 N 32897 0 63
+def 11111*1 3 7 0 N 32897 0 63
+def 111111*1 3 8 0 N 32897 0 63
+def 1111111*1 3 9 0 N 32897 0 63
+def 11111111*1 8 10 0 N 32897 0 63
+def 111111111*1 8 11 0 N 32897 0 63
+1*1 11*1 111*1 1111*1 11111*1 111111*1 1111111*1 11111111*1 111111111*1
+SELECT
+1 MOD 1,
+11 MOD 1,
+111 MOD 1,
+1111 MOD 1,
+11111 MOD 1,
+111111 MOD 1,
+1111111 MOD 1,
+11111111 MOD 1,
+111111111 MOD 1,
+1111111111 MOD 1,
+11111111111 MOD 1 LIMIT 0;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def 1 MOD 1 3 1 0 Y 32896 0 63
+def 11 MOD 1 3 2 0 Y 32896 0 63
+def 111 MOD 1 3 3 0 Y 32896 0 63
+def 1111 MOD 1 3 4 0 Y 32896 0 63
+def 11111 MOD 1 3 5 0 Y 32896 0 63
+def 111111 MOD 1 3 6 0 Y 32896 0 63
+def 1111111 MOD 1 3 7 0 Y 32896 0 63
+def 11111111 MOD 1 3 8 0 Y 32896 0 63
+def 111111111 MOD 1 3 9 0 Y 32896 0 63
+def 1111111111 MOD 1 8 10 0 Y 32896 0 63
+def 11111111111 MOD 1 8 11 0 Y 32896 0 63
+1 MOD 1 11 MOD 1 111 MOD 1 1111 MOD 1 11111 MOD 1 111111 MOD 1 1111111 MOD 1 11111111 MOD 1 111111111 MOD 1 1111111111 MOD 1 11111111111 MOD 1
+SELECT
+-(1),
+-(11),
+-(111),
+-(1111),
+-(11111),
+-(111111),
+-(1111111),
+-(11111111),
+-(111111111) LIMIT 0;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def -(1) 3 2 0 N 32897 0 63
+def -(11) 3 3 0 N 32897 0 63
+def -(111) 3 4 0 N 32897 0 63
+def -(1111) 3 5 0 N 32897 0 63
+def -(11111) 3 6 0 N 32897 0 63
+def -(111111) 3 7 0 N 32897 0 63
+def -(1111111) 3 8 0 N 32897 0 63
+def -(11111111) 3 9 0 N 32897 0 63
+def -(111111111) 8 10 0 N 32897 0 63
+-(1) -(11) -(111) -(1111) -(11111) -(111111) -(1111111) -(11111111) -(111111111)
+SELECT
+ABS(1),
+ABS(11),
+ABS(111),
+ABS(1111),
+ABS(11111),
+ABS(111111),
+ABS(1111111),
+ABS(11111111),
+ABS(111111111),
+ABS(1111111111) LIMIT 0;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def ABS(1) 3 1 0 N 32897 0 63
+def ABS(11) 3 2 0 N 32897 0 63
+def ABS(111) 3 3 0 N 32897 0 63
+def ABS(1111) 3 4 0 N 32897 0 63
+def ABS(11111) 3 5 0 N 32897 0 63
+def ABS(111111) 3 6 0 N 32897 0 63
+def ABS(1111111) 3 7 0 N 32897 0 63
+def ABS(11111111) 3 8 0 N 32897 0 63
+def ABS(111111111) 3 9 0 N 32897 0 63
+def ABS(1111111111) 8 10 0 N 32897 0 63
+ABS(1) ABS(11) ABS(111) ABS(1111) ABS(11111) ABS(111111) ABS(1111111) ABS(11111111) ABS(111111111) ABS(1111111111)
+SELECT
+CEILING(1),
+CEILING(11),
+CEILING(111),
+CEILING(1111),
+CEILING(11111),
+CEILING(111111),
+CEILING(1111111),
+CEILING(11111111),
+CEILING(111111111),
+CEILING(1111111111) LIMIT 0;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def CEILING(1) 3 3 0 N 32897 0 63
+def CEILING(11) 3 4 0 N 32897 0 63
+def CEILING(111) 3 5 0 N 32897 0 63
+def CEILING(1111) 3 6 0 N 32897 0 63
+def CEILING(11111) 3 7 0 N 32897 0 63
+def CEILING(111111) 3 8 0 N 32897 0 63
+def CEILING(1111111) 3 9 0 N 32897 0 63
+def CEILING(11111111) 8 10 0 N 32897 0 63
+def CEILING(111111111) 8 11 0 N 32897 0 63
+def CEILING(1111111111) 8 12 0 N 32897 0 63
+CEILING(1) CEILING(11) CEILING(111) CEILING(1111) CEILING(11111) CEILING(111111) CEILING(1111111) CEILING(11111111) CEILING(111111111) CEILING(1111111111)
+SELECT
+FLOOR(1),
+FLOOR(11),
+FLOOR(111),
+FLOOR(1111),
+FLOOR(11111),
+FLOOR(111111),
+FLOOR(1111111),
+FLOOR(11111111),
+FLOOR(111111111),
+FLOOR(1111111111) LIMIT 0;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def FLOOR(1) 3 3 0 N 32897 0 63
+def FLOOR(11) 3 4 0 N 32897 0 63
+def FLOOR(111) 3 5 0 N 32897 0 63
+def FLOOR(1111) 3 6 0 N 32897 0 63
+def FLOOR(11111) 3 7 0 N 32897 0 63
+def FLOOR(111111) 3 8 0 N 32897 0 63
+def FLOOR(1111111) 3 9 0 N 32897 0 63
+def FLOOR(11111111) 8 10 0 N 32897 0 63
+def FLOOR(111111111) 8 11 0 N 32897 0 63
+def FLOOR(1111111111) 8 12 0 N 32897 0 63
+FLOOR(1) FLOOR(11) FLOOR(111) FLOOR(1111) FLOOR(11111) FLOOR(111111) FLOOR(1111111) FLOOR(11111111) FLOOR(111111111) FLOOR(1111111111)
+SELECT
+ROUND(1),
+ROUND(11),
+ROUND(111),
+ROUND(1111),
+ROUND(11111),
+ROUND(111111),
+ROUND(1111111),
+ROUND(11111111),
+ROUND(111111111),
+ROUND(1111111111) LIMIT 0;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def ROUND(1) 3 1 0 N 32897 0 63
+def ROUND(11) 3 2 0 N 32897 0 63
+def ROUND(111) 3 3 0 N 32897 0 63
+def ROUND(1111) 3 4 0 N 32897 0 63
+def ROUND(11111) 3 5 0 N 32897 0 63
+def ROUND(111111) 3 6 0 N 32897 0 63
+def ROUND(1111111) 3 7 0 N 32897 0 63
+def ROUND(11111111) 3 8 0 N 32897 0 63
+def ROUND(111111111) 3 9 0 N 32897 0 63
+def ROUND(1111111111) 8 10 0 N 32897 0 63
+ROUND(1) ROUND(11) ROUND(111) ROUND(1111) ROUND(11111) ROUND(111111) ROUND(1111111) ROUND(11111111) ROUND(111111111) ROUND(1111111111)
diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test
index e56433b3d54..17e8be839a8 100644
--- a/mysql-test/t/cast.test
+++ b/mysql-test/t/cast.test
@@ -561,3 +561,29 @@ CALL p1('8FFFFFFFFFFFFFFF');
DROP PROCEDURE p1;
SET sql_mode=DEFAULT;
+
+
+--echo #
+--echo # MDEV-12852 Out-of-range errors when CAST(1-2 AS UNSIGNED
+--echo #
+
+SET sql_mode=STRICT_ALL_TABLES;
+CREATE TABLE t1 AS SELECT
+ CAST(-1 AS UNSIGNED),
+ CAST(1-2 AS UNSIGNED);
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
+
+
+--echo #
+--echo # MDEV-12853 Out-of-range errors when CAST('-1' AS UNSIGNED
+--echo #
+
+SET sql_mode=STRICT_ALL_TABLES;
+CREATE TABLE t1 AS SELECT CAST('-1' AS UNSIGNED);
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
diff --git a/mysql-test/t/metadata.test b/mysql-test/t/metadata.test
index 073f617dc16..d5d95cf7e8c 100644
--- a/mysql-test/t/metadata.test
+++ b/mysql-test/t/metadata.test
@@ -353,3 +353,115 @@ CREATE TABLE t1 AS SELECT @:=1e0;
SELECT * FROM t1;
DROP TABLE t1;
--disable_metadata
+
+--echo #
+--echo # MDEV-12869 Wrong metadata for integer additive and multiplicative operators
+--echo #
+
+--enable_metadata
+SELECT
+ 1+1,
+ 11+1,
+ 111+1,
+ 1111+1,
+ 11111+1,
+ 111111+1,
+ 1111111+1,
+ 11111111+1,
+ 111111111+1 LIMIT 0;
+
+SELECT
+ 1-1,
+ 11-1,
+ 111-1,
+ 1111-1,
+ 11111-1,
+ 111111-1,
+ 1111111-1,
+ 11111111-1,
+ 111111111-1 LIMIT 0;
+
+SELECT
+ 1*1,
+ 11*1,
+ 111*1,
+ 1111*1,
+ 11111*1,
+ 111111*1,
+ 1111111*1,
+ 11111111*1,
+ 111111111*1 LIMIT 0;
+
+SELECT
+ 1 MOD 1,
+ 11 MOD 1,
+ 111 MOD 1,
+ 1111 MOD 1,
+ 11111 MOD 1,
+ 111111 MOD 1,
+ 1111111 MOD 1,
+ 11111111 MOD 1,
+ 111111111 MOD 1,
+ 1111111111 MOD 1,
+ 11111111111 MOD 1 LIMIT 0;
+
+SELECT
+ -(1),
+ -(11),
+ -(111),
+ -(1111),
+ -(11111),
+ -(111111),
+ -(1111111),
+ -(11111111),
+ -(111111111) LIMIT 0;
+
+SELECT
+ ABS(1),
+ ABS(11),
+ ABS(111),
+ ABS(1111),
+ ABS(11111),
+ ABS(111111),
+ ABS(1111111),
+ ABS(11111111),
+ ABS(111111111),
+ ABS(1111111111) LIMIT 0;
+
+SELECT
+ CEILING(1),
+ CEILING(11),
+ CEILING(111),
+ CEILING(1111),
+ CEILING(11111),
+ CEILING(111111),
+ CEILING(1111111),
+ CEILING(11111111),
+ CEILING(111111111),
+ CEILING(1111111111) LIMIT 0;
+
+SELECT
+ FLOOR(1),
+ FLOOR(11),
+ FLOOR(111),
+ FLOOR(1111),
+ FLOOR(11111),
+ FLOOR(111111),
+ FLOOR(1111111),
+ FLOOR(11111111),
+ FLOOR(111111111),
+ FLOOR(1111111111) LIMIT 0;
+
+SELECT
+ ROUND(1),
+ ROUND(11),
+ ROUND(111),
+ ROUND(1111),
+ ROUND(11111),
+ ROUND(111111),
+ ROUND(1111111),
+ ROUND(11111111),
+ ROUND(111111111),
+ ROUND(1111111111) LIMIT 0;
+
+--disable_metadata
diff --git a/sql/item.h b/sql/item.h
index dd72d232cce..2700dfc1fe9 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -627,6 +627,11 @@ protected:
return (null_value= item->get_date_with_conversion(ltime, fuzzydate));
}
+ const Type_handler *type_handler_long_or_longlong() const
+ {
+ return Type_handler::type_handler_long_or_longlong(max_char_length());
+ }
+
public:
/*
Cache val_str() into the own buffer, e.g. to evaluate constant
@@ -1210,6 +1215,10 @@ public:
return const_item() ? type_handler()->Item_datetime_precision(this) :
MY_MIN(decimals, TIME_SECOND_PART_DIGITS);
}
+ virtual longlong val_int_min() const
+ {
+ return LONGLONG_MIN;
+ }
/*
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.
@@ -3234,17 +3243,13 @@ public:
Item_int(THD *thd, const char *str_arg, uint length=64);
enum Type type() const { return INT_ITEM; }
const Type_handler *type_handler() const
- {
- // The same condition is repeated in Item::create_tmp_field()
- if (max_length > MY_INT32_NUM_DECIMAL_DIGITS - 2)
- return &type_handler_longlong;
- return &type_handler_long;
- }
+ { return type_handler_long_or_longlong(); }
Field *create_tmp_field(bool group, TABLE *table)
{ return tmp_table_field_from_field_type(table); }
Field *create_field_for_create_select(TABLE *table)
{ return tmp_table_field_from_field_type(table); }
longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
+ longlong val_int_min() const { DBUG_ASSERT(fixed == 1); return value; }
double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; }
my_decimal *val_decimal(my_decimal *);
String *val_str(String*);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 95015d4e074..7b0d5532cbc 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1740,8 +1740,8 @@ my_decimal *Item_func_neg::decimal_op(my_decimal *decimal_value)
void Item_func_neg::fix_length_and_dec_int()
{
- set_handler(&type_handler_longlong);
max_length= args[0]->max_length + 1;
+ set_handler(type_handler_long_or_longlong());
/*
If this is in integer context keep the context as integer if possible
@@ -1834,9 +1834,9 @@ my_decimal *Item_func_abs::decimal_op(my_decimal *decimal_value)
void Item_func_abs::fix_length_and_dec_int()
{
- set_handler(&type_handler_longlong);
max_length= args[0]->max_length;
unsigned_flag= args[0]->unsigned_flag;
+ set_handler(type_handler_long_or_longlong());
}
@@ -2117,7 +2117,7 @@ void Item_func_int_val::fix_length_and_dec_int_or_decimal()
else
{
unsigned_flag= args[0]->unsigned_flag;
- set_handler(&type_handler_longlong);
+ set_handler(type_handler_long_or_longlong());
}
}
@@ -2308,9 +2308,9 @@ void Item_func_round::fix_arg_int()
int length_can_increase= MY_TEST(!truncate && val1_is_negative);
max_length= args[0]->max_length + length_can_increase;
// Here we can keep INT_RESULT
- set_handler(&type_handler_longlong);
unsigned_flag= args[0]->unsigned_flag;
decimals= 0;
+ set_handler(type_handler_long_or_longlong());
}
else
fix_length_and_dec_decimal(decimals_to_set);
diff --git a/sql/item_func.h b/sql/item_func.h
index 39a12e004e9..9055a9e5e98 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -396,6 +396,10 @@ public:
:Item_func(thd, item), Type_handler_hybrid_field_type(item) { }
const Type_handler *type_handler() const
{ return Type_handler_hybrid_field_type::type_handler(); }
+ Field *create_tmp_field(bool group, TABLE *table)
+ { return tmp_table_field_from_field_type(table); }
+ Field *create_field_for_create_select(TABLE *table)
+ { return tmp_table_field_from_field_type(table); }
Field::geometry_type get_geometry_type() const
{ return Type_geometry_attributes::get_geometry_type(); };
void set_geometry_type(uint type)
@@ -624,10 +628,6 @@ public:
Item_func_case_expression(THD *thd, List<Item> &list):
Item_func_hybrid_field_type(thd, list)
{ }
- Field *create_tmp_field(bool group, TABLE *table)
- { return tmp_table_field_from_field_type(table); }
- Field *create_field_for_create_select(TABLE *table)
- { return tmp_table_field_from_field_type(table); }
};
@@ -700,13 +700,14 @@ class Item_num_op :public Item_func_numhybrid
unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
result_precision();
decimals= 0;
+ set_handler(type_handler_long_or_longlong());
}
void fix_length_and_dec_temporal()
{
set_handler(&type_handler_newdecimal);
fix_length_and_dec_decimal();
if (decimals == 0)
- set_handler(&type_handler_longlong);
+ set_handler(type_handler_long_or_longlong());
}
bool need_parentheses_in_default() { return true; }
};
@@ -839,15 +840,8 @@ public:
unsigned_flag= 0;
}
const char *func_name() const { return "cast_as_signed"; }
- const Type_handler *type_handler() const { return &type_handler_longlong; }
- Field *create_tmp_field(bool group, TABLE *table)
- {
- return create_tmp_field_int(table,
- MY_INT32_NUM_DECIMAL_DIGITS - 2 +
- unsigned_flag);
- }
- Field *create_field_for_create_select(TABLE *table)
- { return Item_func_signed::create_tmp_field(false, table); }
+ const Type_handler *type_handler() const
+ { return type_handler_long_or_longlong(); }
longlong val_int()
{
longlong value= args[0]->val_int_signed_typecast();
@@ -899,6 +893,12 @@ public:
unsigned_flag= 1;
}
const char *func_name() const { return "cast_as_unsigned"; }
+ const Type_handler *type_handler() const
+ {
+ if (max_char_length() <= MY_INT32_NUM_DECIMAL_DIGITS - 1)
+ return &type_handler_long;
+ return &type_handler_longlong;
+ }
longlong val_int()
{
longlong value= args[0]->val_int_unsigned_typecast();
@@ -909,6 +909,7 @@ public:
{
args[0]->type_handler()->Item_func_unsigned_fix_length_and_dec(this);
}
+ uint decimal_precision() const { return max_length; }
virtual void print(String *str, enum_query_type query_type);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_unsigned>(thd, mem_root, this); }
@@ -1072,12 +1073,7 @@ public:
const char *func_name() const { return "DIV"; }
enum precedence precedence() const { return MUL_PRECEDENCE; }
const Type_handler *type_handler() const
- {
- // The same condition is repeated in Item::create_tmp_field()
- if (max_length > MY_INT32_NUM_DECIMAL_DIGITS - 2)
- return &type_handler_longlong;
- return &type_handler_long;
- }
+ { return type_handler_long_or_longlong(); }
void fix_length_and_dec();
void print(String *str, enum_query_type query_type)
{
@@ -1118,6 +1114,7 @@ public:
max_length= MY_MAX(args[0]->max_length, args[1]->max_length);
decimals= 0;
unsigned_flag= args[0]->unsigned_flag;
+ set_handler(type_handler_long_or_longlong());
}
bool check_partition_func_processor(void *int_arg) {return FALSE;}
bool check_vcol_func_processor(void *arg) { return FALSE;}
@@ -1469,10 +1466,6 @@ public:
Item_func_min_max(THD *thd, List<Item> &list, int cmp_sign_arg):
Item_hybrid_func(thd, list), cmp_sign(cmp_sign_arg)
{}
- Field *create_tmp_field(bool group, TABLE *table)
- { return tmp_table_field_from_field_type(table); }
- Field *create_field_for_create_select(TABLE *table)
- { return tmp_table_field_from_field_type(table); }
String *val_str_native(String *str);
double val_real_native();
longlong val_int_native();
@@ -2244,6 +2237,10 @@ public:
Item_func_user_var(THD *thd, Item_func_user_var *item)
:Item_hybrid_func(thd, item),
m_var_entry(item->m_var_entry), name(item->name) { }
+ Field *create_tmp_field(bool group, TABLE *table)
+ { return Item::create_tmp_field(group, table); }
+ Field *create_field_for_create_select(TABLE *table)
+ { return Item::create_field_for_create_select(table); }
bool check_vcol_func_processor(void *arg);
};
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 55193bce207..2e7142336a4 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -155,7 +155,7 @@ public:
return str;
}
const char *func_name() const { return "month"; }
- const Type_handler *type_handler() const { return &type_handler_longlong; }
+ const Type_handler *type_handler() const { return &type_handler_long; }
void fix_length_and_dec()
{
decimals= 0;
@@ -449,7 +449,10 @@ public:
decimals= dec;
max_length=17 + (decimals ? decimals + 1 : 0);
maybe_null= true;
- set_handler_by_result_type(decimals ? DECIMAL_RESULT : INT_RESULT);
+ if (decimals)
+ set_handler(&type_handler_newdecimal);
+ else
+ set_handler(type_handler_long_or_longlong());
}
double real_op() { DBUG_ASSERT(0); return 0; }
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
diff --git a/sql/sql_type.cc b/sql/sql_type.cc
index d9c75fea9a7..504fab21845 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -528,6 +528,14 @@ Type_handler_hybrid_field_type::aggregate_for_result(const Type_handler *other)
}
+const Type_handler *
+Type_handler::type_handler_long_or_longlong(uint max_char_length)
+{
+ if (max_char_length <= MY_INT32_NUM_DECIMAL_DIGITS - 2)
+ return &type_handler_long;
+ return &type_handler_longlong;
+}
+
/*
This method is called for CASE (and its abbreviations) and LEAST/GREATEST
when data type aggregation returned LONGLONG and there were some BIT
@@ -4168,6 +4176,16 @@ bool Type_handler::
bool Type_handler::
Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const
{
+ const Item *arg= item->arguments()[0];
+ if (!arg->unsigned_flag && arg->val_int_min() < 0)
+ {
+ /*
+ Negative arguments produce long results:
+ CAST(1-2 AS UNSIGNED) -> 18446744073709551615
+ */
+ item->max_length= MAX_BIGINT_WIDTH;
+ return false;
+ }
item->fix_length_and_dec_generic();
return false;
}
@@ -4184,6 +4202,14 @@ bool Type_handler_string_result::
bool Type_handler_string_result::
Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const
{
+ const Item *arg= item->arguments()[0];
+ if (!arg->unsigned_flag && // Not HEX hybrid
+ arg->max_char_length() > 1) // Can be negative
+ {
+ // String arguments can give long results: '-1' -> 18446744073709551614
+ item->max_length= MAX_BIGINT_WIDTH;
+ return false;
+ }
item->fix_length_and_dec_string();
return false;
}
diff --git a/sql/sql_type.h b/sql/sql_type.h
index 374f250f443..aeaec7ff95f 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -564,6 +564,7 @@ public:
static const Type_handler *blob_type_handler(uint max_octet_length);
static const Type_handler *string_type_handler(uint max_octet_length);
static const Type_handler *bit_and_int_mixture_handler(uint max_char_len);
+ static const Type_handler *type_handler_long_or_longlong(uint max_char_len);
/**
Return a string type handler for Item
If too_big_for_varchar() returns a BLOB variant, according to length.