Commit c84bbeda authored by Alexander Barkov's avatar Alexander Barkov

MDEV-12858 + MDEV+12859 + MDEV-12862 - a join patch fixing a few data type...

MDEV-12858 + MDEV+12859 + MDEV-12862 - a join patch fixing a few data type problems with CREATE..SELECT

MDEV-12858 Out-of-range error for CREATE..SELECT unsigned_int_column+1
MDEV-12859 Out-of-range error for CREATE..SELECT @A:=EXTRACT(MINUTE_MICROSECOND FROM..)
MDEV-12862 Data type of @A:=1e0 depends on the session character set

1. Moving a part of Item::create_tmp_field() into a new helper method
   Item::create_tmp_field_int() and reusing it in Item::create_tmp_field()
   and Item_func_signed::create_tmp_field().
   Fixing the code in Item::create_tmp_field_int() to call
   Type_handler::make_table_field() instead of doing "new Field_long[long]"
   directly. This change revealed a problem reported in MDEV-12862.

2. Changing the "long vs longlong" cut-off length for
     - Item_func::create_tmp_field()
     - Item_sum::create_tmp_field()
     - Item_func_get_user_var::create_tmp_field()
   from MY_INT32_NUM_DECIMAL_DIGITS to (MY_INT32_NUM_DECIMAL_DIGITS - 2).
   This fixes MDEV-12858.
   After this change, the "convert_int_length" parameter to
   Item::create_tmp_field() is not needed any more, because
   (MY_INT32_NUM_DECIMAL_DIGITS - 2) is always passed.
   So removing the "convert_int_length" parameter.

3. Fixing Item::create_tmp_field() to pass max_char_length() instead
   of max_length to the constructor of Field_double().
   This fixes MDEV-12862.

4. Additionally, fixing
   - Type_handler_{tiny|short|int24|long|longlong}::make_table_field()
   - Type_handler_{float|double}::make_table_field()
   to pass max_char_length() instead of max_length to Field contructors.
   This is needed by the change (1).

5. Adding new tests, and recording new correct results in the old tests in:
   - mysql-test/r/type_ranges.result
   - storage/tokudb/mysql-test/tokudb/r/type_ranges.result
parent feb15f4e
...@@ -877,3 +877,21 @@ d09 222222222 ...@@ -877,3 +877,21 @@ d09 222222222
d10 2222222222 d10 2222222222
DROP TABLE t1; DROP TABLE t1;
SET sql_mode=DEFAULT; SET sql_mode=DEFAULT;
#
# MDEV-12858 Out-of-range error for CREATE..SELECT unsigned_int_column+1
#
SET sql_mode=STRICT_ALL_TABLES;
CREATE OR REPLACE TABLE t1 (a INT UNSIGNED NOT NULL);
INSERT INTO t1 VALUES (0xFFFFFFFF);
CREATE OR REPLACE TABLE t2 AS SELECT a+1 AS a FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` bigint(11) unsigned NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT a, HEX(a) FROM t2;
a HEX(a)
4294967296 100000000
DROP TABLE t2;
DROP TABLE t1;
SET sql_mode=DEFAULT;
...@@ -549,3 +549,22 @@ def d09 3 9 9 Y 32896 0 63 ...@@ -549,3 +549,22 @@ def d09 3 9 9 Y 32896 0 63
def d10 8 10 10 Y 32896 0 63 def d10 8 10 10 Y 32896 0 63
d0l d09 d10 d0l d09 d10
2 222222222 2222222222 2 222222222 2222222222
#
# MDEV-12862 Data type of @a:=1e0 depends on the session character set
#
SET NAMES utf8;
CREATE TABLE t1 AS SELECT @:=1e0;
SELECT * FROM t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t1 t1 @:=1e0 @:=1e0 5 3 1 N 36865 31 63
@:=1e0
1
DROP TABLE t1;
SET NAMES latin1;
CREATE TABLE t1 AS SELECT @:=1e0;
SELECT * FROM t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t1 t1 @:=1e0 @:=1e0 5 3 1 N 36865 31 63
@:=1e0
1
DROP TABLE t1;
...@@ -272,7 +272,7 @@ drop table t2; ...@@ -272,7 +272,7 @@ drop table t2;
create table t2 (primary key (auto)) select auto+1 as auto,1 as t1, 'a' as t2, repeat('a',256) as t3, binary repeat('b',256) as t4, repeat('a',4096) as t5, binary repeat('b',4096) as t6, '' as t7, binary '' as t8 from t1; create table t2 (primary key (auto)) select auto+1 as auto,1 as t1, 'a' as t2, repeat('a',256) as t3, binary repeat('b',256) as t4, repeat('a',4096) as t5, binary repeat('b',4096) as t6, '' as t7, binary '' as t8 from t1;
show full columns from t2; show full columns from t2;
Field Type Collation Null Key Default Extra Privileges Comment Field Type Collation Null Key Default Extra Privileges Comment
auto int(11) unsigned NULL NO PRI NULL # auto bigint(11) unsigned NULL NO PRI NULL #
t1 int(1) NULL NO NULL # t1 int(1) NULL NO NULL #
t2 varchar(1) latin1_swedish_ci NO NULL # t2 varchar(1) latin1_swedish_ci NO NULL #
t3 varchar(256) latin1_swedish_ci YES NULL # t3 varchar(256) latin1_swedish_ci YES NULL #
......
...@@ -570,3 +570,22 @@ End of 5.5 tests ...@@ -570,3 +570,22 @@ End of 5.5 tests
# #
set @var= repeat('a',20000); set @var= repeat('a',20000);
1 1
#
# Start of 10.3 tests
#
#
# MDEV-12859 Out-of-range error for CREATE..SELECT @a:=EXTRACT(MINUTE_MICROSECOND FROM..
#
SET sql_mode=STRICT_ALL_TABLES;
CREATE OR REPLACE TABLE t1 AS
SELECT @a:=EXTRACT(MINUTE_MICROSECOND FROM '2001-01-01 11:22:33.999999') AS c1;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` bigint(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM t1;
c1
2233999999
DROP TABLE t1;
SET sql_mode=DEFAULT;
...@@ -640,3 +640,18 @@ SELECT * FROM t1; ...@@ -640,3 +640,18 @@ SELECT * FROM t1;
--horizontal_results --horizontal_results
DROP TABLE t1; DROP TABLE t1;
SET sql_mode=DEFAULT; SET sql_mode=DEFAULT;
--echo #
--echo # MDEV-12858 Out-of-range error for CREATE..SELECT unsigned_int_column+1
--echo #
SET sql_mode=STRICT_ALL_TABLES;
CREATE OR REPLACE TABLE t1 (a INT UNSIGNED NOT NULL);
INSERT INTO t1 VALUES (0xFFFFFFFF);
CREATE OR REPLACE TABLE t2 AS SELECT a+1 AS a FROM t1;
SHOW CREATE TABLE t2;
SELECT a, HEX(a) FROM t2;
DROP TABLE t2;
DROP TABLE t1;
SET sql_mode=DEFAULT;
...@@ -338,3 +338,18 @@ SELECT ...@@ -338,3 +338,18 @@ SELECT
222222222 DIV 1 AS d09, 222222222 DIV 1 AS d09,
2222222222 DIV 1 AS d10; 2222222222 DIV 1 AS d10;
--disable_metadata --disable_metadata
--echo #
--echo # MDEV-12862 Data type of @a:=1e0 depends on the session character set
--echo #
--enable_metadata
SET NAMES utf8;
CREATE TABLE t1 AS SELECT @:=1e0;
SELECT * FROM t1;
DROP TABLE t1;
SET NAMES latin1;
CREATE TABLE t1 AS SELECT @:=1e0;
SELECT * FROM t1;
DROP TABLE t1;
--disable_metadata
...@@ -501,3 +501,18 @@ eval select $tmp < $tmp2; ...@@ -501,3 +501,18 @@ eval select $tmp < $tmp2;
--enable_column_names --enable_column_names
--enable_query_log --enable_query_log
--echo #
--echo # Start of 10.3 tests
--echo #
--echo #
--echo # MDEV-12859 Out-of-range error for CREATE..SELECT @a:=EXTRACT(MINUTE_MICROSECOND FROM..
--echo #
SET sql_mode=STRICT_ALL_TABLES;
CREATE OR REPLACE TABLE t1 AS
SELECT @a:=EXTRACT(MINUTE_MICROSECOND FROM '2001-01-01 11:22:33.999999') AS c1;
SHOW CREATE TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;
SET sql_mode=DEFAULT;
...@@ -582,7 +582,7 @@ class Item: public Value_source, ...@@ -582,7 +582,7 @@ class Item: public Value_source,
return h->make_and_init_table_field(&name, Record_addr(maybe_null), return h->make_and_init_table_field(&name, Record_addr(maybe_null),
*this, table); *this, table);
} }
Field *create_tmp_field(bool group, TABLE *table, uint convert_int_length); Field *create_tmp_field_int(TABLE *table, uint convert_int_length);
void push_note_converted_to_negative_complement(THD *thd); void push_note_converted_to_negative_complement(THD *thd);
void push_note_converted_to_positive_complement(THD *thd); void push_note_converted_to_positive_complement(THD *thd);
...@@ -1637,14 +1637,7 @@ class Item: public Value_source, ...@@ -1637,14 +1637,7 @@ class Item: public Value_source,
// used in row subselects to get value of elements // used in row subselects to get value of elements
virtual void bring_value() {} virtual void bring_value() {}
virtual Field *create_tmp_field(bool group, TABLE *table) virtual Field *create_tmp_field(bool group, TABLE *table);
{
/*
Values with MY_INT32_NUM_DECIMAL_DIGITS digits may or may not fit into
Field_long : make them Field_longlong.
*/
return create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS - 2);
}
virtual Item_field *field_for_view_update() { return 0; } virtual Item_field *field_for_view_update() { return 0; }
......
...@@ -171,7 +171,7 @@ class Item_func :public Item_func_or_sum ...@@ -171,7 +171,7 @@ class Item_func :public Item_func_or_sum
Field *create_field_for_create_select(TABLE *table) Field *create_field_for_create_select(TABLE *table)
{ {
return result_type() != STRING_RESULT ? return result_type() != STRING_RESULT ?
create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS) : Item::create_tmp_field(false, table) :
tmp_table_field_from_field_type(table); tmp_table_field_from_field_type(table);
} }
Item *get_tmp_table_item(THD *thd); Item *get_tmp_table_item(THD *thd);
...@@ -842,7 +842,7 @@ class Item_func_signed :public Item_int_func ...@@ -842,7 +842,7 @@ class Item_func_signed :public Item_int_func
const Type_handler *type_handler() const { return &type_handler_longlong; } const Type_handler *type_handler() const { return &type_handler_longlong; }
Field *create_tmp_field(bool group, TABLE *table) Field *create_tmp_field(bool group, TABLE *table)
{ {
return Item::create_tmp_field(false, table, return create_tmp_field_int(table,
MY_INT32_NUM_DECIMAL_DIGITS - 2 + MY_INT32_NUM_DECIMAL_DIGITS - 2 +
unsigned_flag); unsigned_flag);
} }
...@@ -2352,7 +2352,7 @@ class Item_func_get_user_var :public Item_func_user_var, ...@@ -2352,7 +2352,7 @@ class Item_func_get_user_var :public Item_func_user_var,
type_handler_long_blob.make_and_init_table_field(&(Item::name), type_handler_long_blob.make_and_init_table_field(&(Item::name),
Record_addr(maybe_null), Record_addr(maybe_null),
*this, table) : *this, table) :
create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS); create_tmp_field(false, table);
} }
virtual void print(String *str, enum_query_type query_type); virtual void print(String *str, enum_query_type query_type);
/* /*
......
...@@ -510,7 +510,7 @@ class Item_sum :public Item_func_or_sum ...@@ -510,7 +510,7 @@ class Item_sum :public Item_func_or_sum
Item *get_tmp_table_item(THD *thd); Item *get_tmp_table_item(THD *thd);
Field *create_tmp_field(bool group, TABLE *table) Field *create_tmp_field(bool group, TABLE *table)
{ {
return Item::create_tmp_field(group, table, MY_INT32_NUM_DECIMAL_DIGITS); return Item::create_tmp_field(group, table);
} }
virtual bool collect_outer_ref_processor(void *param); virtual bool collect_outer_ref_processor(void *param);
bool init_sum_func_check(THD *thd); bool init_sum_func_check(THD *thd);
......
...@@ -15869,7 +15869,17 @@ Field *create_tmp_field_from_field(THD *thd, Field *org_field, ...@@ -15869,7 +15869,17 @@ Field *create_tmp_field_from_field(THD *thd, Field *org_field,
} }
Field *Item::create_tmp_field(bool group, TABLE *table, uint convert_int_length) Field *Item::create_tmp_field_int(TABLE *table, uint convert_int_length)
{
const Type_handler *h= &type_handler_long;
if (max_char_length() > convert_int_length)
h= &type_handler_longlong;
return h->make_and_init_table_field(&name, Record_addr(maybe_null),
*this, table);
}
Field *Item::create_tmp_field(bool group, TABLE *table)
{ {
Field *UNINIT_VAR(new_field); Field *UNINIT_VAR(new_field);
MEM_ROOT *mem_root= table->in_use->mem_root; MEM_ROOT *mem_root= table->in_use->mem_root;
...@@ -15878,23 +15888,11 @@ Field *Item::create_tmp_field(bool group, TABLE *table, uint convert_int_length) ...@@ -15878,23 +15888,11 @@ Field *Item::create_tmp_field(bool group, TABLE *table, uint convert_int_length)
case REAL_RESULT: case REAL_RESULT:
{ {
new_field= new (mem_root) new_field= new (mem_root)
Field_double(max_length, maybe_null, &name, decimals, TRUE); Field_double(max_char_length(), maybe_null, &name, decimals, TRUE);
break; break;
} }
case INT_RESULT: case INT_RESULT:
{ return create_tmp_field_int(table, MY_INT32_NUM_DECIMAL_DIGITS - 2);
/*
Select an integer type with the minimal fit precision.
convert_int_length is sign inclusive, don't consider the sign.
*/
if (max_char_length() > convert_int_length)
new_field= new (mem_root)
Field_longlong(max_char_length(), maybe_null, &name, unsigned_flag);
else
new_field= new (mem_root)
Field_long(max_char_length(), maybe_null, &name, unsigned_flag);
break;
}
case TIME_RESULT: case TIME_RESULT:
case DECIMAL_RESULT: case DECIMAL_RESULT:
case STRING_RESULT: case STRING_RESULT:
......
...@@ -1946,7 +1946,8 @@ Field *Type_handler_tiny::make_table_field(const LEX_CSTRING *name, ...@@ -1946,7 +1946,8 @@ Field *Type_handler_tiny::make_table_field(const LEX_CSTRING *name,
TABLE *table) const TABLE *table) const
{ {
return new (table->in_use->mem_root) return new (table->in_use->mem_root)
Field_tiny(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit, Field_tiny(addr.ptr, attr.max_char_length(),
addr.null_ptr, addr.null_bit,
Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag); Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag);
} }
...@@ -1958,7 +1959,8 @@ Field *Type_handler_short::make_table_field(const LEX_CSTRING *name, ...@@ -1958,7 +1959,8 @@ Field *Type_handler_short::make_table_field(const LEX_CSTRING *name,
{ {
return new (table->in_use->mem_root) return new (table->in_use->mem_root)
Field_short(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit, Field_short(addr.ptr, attr.max_char_length(),
addr.null_ptr, addr.null_bit,
Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag); Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag);
} }
...@@ -1969,7 +1971,8 @@ Field *Type_handler_int24::make_table_field(const LEX_CSTRING *name, ...@@ -1969,7 +1971,8 @@ Field *Type_handler_int24::make_table_field(const LEX_CSTRING *name,
TABLE *table) const TABLE *table) const
{ {
return new (table->in_use->mem_root) return new (table->in_use->mem_root)
Field_medium(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit, Field_medium(addr.ptr, attr.max_char_length(),
addr.null_ptr, addr.null_bit,
Field::NONE, name, Field::NONE, name,
0/*zerofill*/, attr.unsigned_flag); 0/*zerofill*/, attr.unsigned_flag);
} }
...@@ -1981,7 +1984,8 @@ Field *Type_handler_long::make_table_field(const LEX_CSTRING *name, ...@@ -1981,7 +1984,8 @@ Field *Type_handler_long::make_table_field(const LEX_CSTRING *name,
TABLE *table) const TABLE *table) const
{ {
return new (table->in_use->mem_root) return new (table->in_use->mem_root)
Field_long(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit, Field_long(addr.ptr, attr.max_char_length(),
addr.null_ptr, addr.null_bit,
Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag); Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag);
} }
...@@ -1992,7 +1996,7 @@ Field *Type_handler_longlong::make_table_field(const LEX_CSTRING *name, ...@@ -1992,7 +1996,7 @@ Field *Type_handler_longlong::make_table_field(const LEX_CSTRING *name,
TABLE *table) const TABLE *table) const
{ {
return new (table->in_use->mem_root) return new (table->in_use->mem_root)
Field_longlong(addr.ptr, attr.max_length, Field_longlong(addr.ptr, attr.max_char_length(),
addr.null_ptr, addr.null_bit, addr.null_ptr, addr.null_bit,
Field::NONE, name, Field::NONE, name,
0/*zerofill*/, attr.unsigned_flag); 0/*zerofill*/, attr.unsigned_flag);
...@@ -2005,7 +2009,8 @@ Field *Type_handler_float::make_table_field(const LEX_CSTRING *name, ...@@ -2005,7 +2009,8 @@ Field *Type_handler_float::make_table_field(const LEX_CSTRING *name,
TABLE *table) const TABLE *table) const
{ {
return new (table->in_use->mem_root) return new (table->in_use->mem_root)
Field_float(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit, Field_float(addr.ptr, attr.max_char_length(),
addr.null_ptr, addr.null_bit,
Field::NONE, name, Field::NONE, name,
attr.decimals, 0/*zerofill*/, attr.unsigned_flag); attr.decimals, 0/*zerofill*/, attr.unsigned_flag);
} }
...@@ -2017,7 +2022,7 @@ Field *Type_handler_double::make_table_field(const LEX_CSTRING *name, ...@@ -2017,7 +2022,7 @@ Field *Type_handler_double::make_table_field(const LEX_CSTRING *name,
TABLE *table) const TABLE *table) const
{ {
return new (table->in_use->mem_root) return new (table->in_use->mem_root)
Field_double(addr.ptr, attr.max_length, Field_double(addr.ptr, attr.max_char_length(),
addr.null_ptr, addr.null_bit, addr.null_ptr, addr.null_bit,
Field::NONE, name, Field::NONE, name,
attr.decimals, 0/*zerofill*/, attr.unsigned_flag); attr.decimals, 0/*zerofill*/, attr.unsigned_flag);
......
...@@ -273,7 +273,7 @@ drop table t2; ...@@ -273,7 +273,7 @@ drop table t2;
create table t2 (primary key (auto)) select auto+1 as auto,1 as t1, 'a' as t2, repeat('a',256) as t3, binary repeat('b',256) as t4, repeat('a',4096) as t5, binary repeat('b',4096) as t6, '' as t7, binary '' as t8 from t1; create table t2 (primary key (auto)) select auto+1 as auto,1 as t1, 'a' as t2, repeat('a',256) as t3, binary repeat('b',256) as t4, repeat('a',4096) as t5, binary repeat('b',4096) as t6, '' as t7, binary '' as t8 from t1;
show full columns from t2; show full columns from t2;
Field Type Collation Null Key Default Extra Privileges Comment Field Type Collation Null Key Default Extra Privileges Comment
auto int(11) unsigned NULL NO PRI NULL # auto bigint(11) unsigned NULL NO PRI NULL #
t1 int(1) NULL NO NULL # t1 int(1) NULL NO NULL #
t2 varchar(1) latin1_swedish_ci NO NULL # t2 varchar(1) latin1_swedish_ci NO NULL #
t3 varchar(256) latin1_swedish_ci NO NULL # t3 varchar(256) latin1_swedish_ci NO NULL #
......
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