Commit d9304914 authored by Alexander Barkov's avatar Alexander Barkov

Fixing a few problems with data type and metadata for INT result functions...

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.
parent 9b79888d
......@@ -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
......
......@@ -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)
......@@ -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;
......@@ -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
......@@ -627,6 +627,11 @@ class Item: public Value_source,
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 @@ class Item: public Value_source,
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 @@ class Item_int :public Item_num
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*);
......
......@@ -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);
......
......@@ -396,6 +396,10 @@ class Item_hybrid_func: public Item_func,
: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 @@ class Item_func_case_expression: public Item_func_hybrid_field_type
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 @@ class Item_func_signed :public Item_int_func
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 @@ class Item_func_unsigned :public Item_func_signed
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 @@ class Item_func_unsigned :public Item_func_signed
{
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 @@ class Item_func_int_div :public Item_int_func
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 @@ class Item_func_mod :public Item_num_op
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 @@ class Item_func_min_max :public Item_hybrid_func
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 @@ class Item_func_user_var :public Item_hybrid_func
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);
};
......
......@@ -155,7 +155,7 @@ class Item_func_month :public Item_func
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 @@ class Item_func_seconds_hybrid: public Item_func_numhybrid
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; }
......
......@@ -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;
}
......
......@@ -564,6 +564,7 @@ class Type_handler
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.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment