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:
parent
9b79888df8
commit
d9304914be
@ -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;
|
||||
|
@ -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
|
||||
|
17
sql/item.h
17
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*);
|
||||
|
@ -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 @@ 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);
|
||||
};
|
||||
|
||||
|
@ -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; }
|
||||
|
@ -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 @@ 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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user