Fixing a few problems with data type and metadata for INT result functions (MDEV-12852, MDEV-12853, MDEV-12869)

This is a joint patch for:
MDEV-12852 Out-of-range errors when CAST(1-2 AS UNSIGNED
MDEV-12853 Out-of-range errors when CAST('-1' AS UNSIGNED
MDEV-12869 Wrong metadata for integer additive and multiplicative operators

1. Fixing all Item_func_numhybrid descendants to set the precise
   data type handler (type_handler_long or type_handler_longlong)
   at fix_fields() time. This fixes MDEV-12869.

2. Fixing Item_func_unsigned_typecast to set the precise data type handler
   at fix_fields() time. This fixes MDEV-12852 and MDEV-12853.
   This is done by:
   - fixing Type_handler::Item_func_unsigned_fix_length_and_dec()
     and Type_handler_string_result::Item_func_unsigned_fix_length_and_dec()
     to properly detect situations when a negative epxression is converted
     to UNSIGNED. In this case, length of the result is now always set to
     MAX_BIGINT_WIDTH without trying to use args[0]->max_length, as very
     short arguments can produce very long result in such conversion:
        CAST(-1 AS UNSIGNED) -> 18446744073709551614
   - adding a new virtual method "longlong Item::val_int_max() const",
     to preserve the old behavior for expressions like this:
        CAST(1 AS UNSIGNED)
     to stay under the INT data type (instead of BIGINT) for small
     positive integer literals. Using Item::unsigned_flag would not help,
     because Item_int does not set unsigned_flag to "true" for positive
     numbers.

3. Adding helper methods:
  * Item::type_handler_long_or_longlong()
  * Type_handler::type_handler_long_or_longlong()
  and reusing them in a few places, to reduce code duplication.

4. Making reorganation in create_tmp_field() and
   create_field_for_create_select() for Item_hybrid_func and descendants,
   to reduce duplicate code. They all now have a similar behavior in
   respect of creating fields. Only Item_func_user_var descendants have
   a different behavior. So moving the default behvior to Item_hybrid_func,
   and overriding behavior on Item_func_user_var level.
This commit is contained in:
Alexander Barkov 2017-05-23 12:45:47 +04:00
parent 9b79888df8
commit d9304914be
11 changed files with 451 additions and 39 deletions

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -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*);

View File

@ -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);

View File

@ -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);
};

View File

@ -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; }

View File

@ -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;
}

View File

@ -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.