1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

MDEV-15957 Unexpected "Data too long" when doing CREATE..SELECT with stored func

Problems:

1. Unlike Item_field::fix_fields(),
  Item_sum_sp::fix_length_and_dec() and Item_func_sp::fix_length_and_dec()
  did not run the code which resided in adjust_max_effective_column_length(),
  therefore they did not extend max_length for the integer return data types
  from the user-specified length to the maximum length according to
  the data type capacity.

2. The code in adjust_max_effective_column_length() was not correct
   for TEXT data, because Field_blob::max_display_length()
   multiplies to mbmaxlen. So TEXT variants were unintentionally
   promoted to the next longer data type for multi-byte character
   sets: TINYTEXT->TEXT, TEXT->MEDIUMTEXT, MEDIUMTEXT->LONGTEXT.

3. Item_sum_sp::create_table_field_from_handler()
   Item_func_sp::create_table_field_from_handler()
   erroneously called tmp_table_field_from_field_type(),
   which converted VARCHAR(>512) to TEXT variants.
   So "CREATE..SELECT spfunc()" erroneously converted
   VARCHAR to TEXT. This was wrong, because stored
   functions have explicitly declared data types,
   which should be preserved.

Solution:

- Removing Type_std_attributes(const Field *)
  and using instead Type_std_attributes::set() in combination
  with field->type_str_attributes() all around the code, e.g.:
     Type_std_attributes::set(field->type_std_attributes())

  These two ways of copying attributes from a Field
  to an Item duplicated each other, and were slightly
  different in how to mix max_length and mbmaxlen.

- Removing adjust_max_effective_column_length() and
  fixing Field::type_std_attributes() to do all necessary
  type-specific calculations , so no further adjustments
  is needed.
  Field::type_std_attributes() is now called from all affected methods:
   Item_field::fix_fields()
   Item_sum_sp::fix_length_and_dec()
   Item_func_sp::fix_length_and_dec()
  This fixes the problem N1.

- Making Field::type_std_attributes() virtual, to make
  sure that type-specific adjustments a properly done
  by individual Field_xxx classes. Implementing
  Field_blob::type_std_attributes() in the way that
  no TEXT promotion is done.
  This fixes the problem N2.

- Fixing Item_sum_sp::create_table_field_from_handler()
  Item_func_sp::create_table_field_from_handler() to
  call create_table_field_from_handler() instead of
  tmp_table_field_from_field_type() to avoid
  VARCHAR->TEXT conversion on "CREATE..SELECT spfunc()".

- Recording mysql-test/suite/compat/oracle/r/sp-param.result
  as "CREATE..SELECT spfunc()" now correctly
  preserve the data type as specified in the RETURNS clause.

- Adding new tests
This commit is contained in:
Alexander Barkov
2018-04-23 09:31:17 +04:00
parent 9f84451d87
commit 6426b52ed4
14 changed files with 543 additions and 52 deletions

View File

@ -947,3 +947,179 @@ select f1('2001-01-01'),cast(f1('2001-01-01') as time);
f1('2001-01-01') cast(f1('2001-01-01') as time)
2001-01-01 00:00:00
drop function f1;
#
# MDEV-15957 Unexpected "Data too long" when doing CREATE..SELECT with stored functions
#
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2),(3);
CREATE AGGREGATE FUNCTION f1(x INT) RETURNS INT(3)
BEGIN
DECLARE res INT DEFAULT 0;
DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN res-200;
LOOP
FETCH GROUP NEXT ROW;
SET res= res + x;
END LOOP;
RETURN res;
END;
$$
CREATE TABLE t2 AS SELECT CONCAT(f1(a)) FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`CONCAT(f1(a))` varchar(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1,t2;
DROP FUNCTION f1;
CREATE AGGREGATE FUNCTION f1() RETURNS TINYTEXT CHARACTER SET latin1
BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN '';
LOOP
FETCH GROUP NEXT ROW;
END LOOP;
RETURN '';
END;
$$
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` tinytext DEFAULT NULL,
`c2` tinytext DEFAULT NULL,
`c3` varchar(255) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
DROP FUNCTION f1;
CREATE AGGREGATE FUNCTION f1() RETURNS TEXT CHARACTER SET latin1
BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN '';
LOOP
FETCH GROUP NEXT ROW;
END LOOP;
RETURN '';
END;
$$
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` text DEFAULT NULL,
`c2` text DEFAULT NULL,
`c3` text DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
DROP FUNCTION f1;
CREATE AGGREGATE FUNCTION f1() RETURNS MEDIUMTEXT CHARACTER SET latin1
BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN '';
LOOP
FETCH GROUP NEXT ROW;
END LOOP;
RETURN '';
END;
$$
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` mediumtext DEFAULT NULL,
`c2` mediumtext DEFAULT NULL,
`c3` mediumtext DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
DROP FUNCTION f1;
CREATE AGGREGATE FUNCTION f1() RETURNS LONGTEXT CHARACTER SET latin1
BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN '';
LOOP
FETCH GROUP NEXT ROW;
END LOOP;
RETURN '';
END;
$$
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` longtext DEFAULT NULL,
`c2` longtext DEFAULT NULL,
`c3` longtext DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
DROP FUNCTION f1;
CREATE AGGREGATE FUNCTION f1() RETURNS TINYTEXT CHARACTER SET utf8
BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN '';
LOOP
FETCH GROUP NEXT ROW;
END LOOP;
RETURN '';
END;
$$
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` tinytext CHARACTER SET utf8 DEFAULT NULL,
`c2` text CHARACTER SET utf8 DEFAULT NULL,
`c3` varchar(255) CHARACTER SET utf8 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
DROP FUNCTION f1;
CREATE AGGREGATE FUNCTION f1() RETURNS TEXT CHARACTER SET utf8
BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN '';
LOOP
FETCH GROUP NEXT ROW;
END LOOP;
RETURN '';
END;
$$
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` text CHARACTER SET utf8 DEFAULT NULL,
`c2` mediumtext CHARACTER SET utf8 DEFAULT NULL,
`c3` mediumtext CHARACTER SET utf8 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
DROP FUNCTION f1;
CREATE AGGREGATE FUNCTION f1() RETURNS MEDIUMTEXT CHARACTER SET utf8
BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN '';
LOOP
FETCH GROUP NEXT ROW;
END LOOP;
RETURN '';
END;
$$
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` mediumtext CHARACTER SET utf8 DEFAULT NULL,
`c2` longtext CHARACTER SET utf8 DEFAULT NULL,
`c3` longtext CHARACTER SET utf8 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
DROP FUNCTION f1;
CREATE AGGREGATE FUNCTION f1() RETURNS LONGTEXT CHARACTER SET utf8
BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN '';
LOOP
FETCH GROUP NEXT ROW;
END LOOP;
RETURN '';
END;
$$
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` longtext CHARACTER SET utf8 DEFAULT NULL,
`c2` longtext CHARACTER SET utf8 DEFAULT NULL,
`c3` longtext CHARACTER SET utf8 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
DROP FUNCTION f1;

View File

@ -783,3 +783,159 @@ end|
delimiter ;|
select f1('2001-01-01'),cast(f1('2001-01-01') as time);
drop function f1;
--echo #
--echo # MDEV-15957 Unexpected "Data too long" when doing CREATE..SELECT with stored functions
--echo #
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2),(3);
DELIMITER $$;
CREATE AGGREGATE FUNCTION f1(x INT) RETURNS INT(3)
BEGIN
DECLARE res INT DEFAULT 0;
DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN res-200;
LOOP
FETCH GROUP NEXT ROW;
SET res= res + x;
END LOOP;
RETURN res;
END;
$$
DELIMITER ;$$
CREATE TABLE t2 AS SELECT CONCAT(f1(a)) FROM t1;
SHOW CREATE TABLE t2;
DROP TABLE t1,t2;
DROP FUNCTION f1;
DELIMITER $$;
CREATE AGGREGATE FUNCTION f1() RETURNS TINYTEXT CHARACTER SET latin1
BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN '';
LOOP
FETCH GROUP NEXT ROW;
END LOOP;
RETURN '';
END;
$$
DELIMITER ;$$
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
DROP TABLE t1;
DROP FUNCTION f1;
DELIMITER $$;
CREATE AGGREGATE FUNCTION f1() RETURNS TEXT CHARACTER SET latin1
BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN '';
LOOP
FETCH GROUP NEXT ROW;
END LOOP;
RETURN '';
END;
$$
DELIMITER ;$$
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
DROP TABLE t1;
DROP FUNCTION f1;
DELIMITER $$;
CREATE AGGREGATE FUNCTION f1() RETURNS MEDIUMTEXT CHARACTER SET latin1
BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN '';
LOOP
FETCH GROUP NEXT ROW;
END LOOP;
RETURN '';
END;
$$
DELIMITER ;$$
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
DROP TABLE t1;
DROP FUNCTION f1;
DELIMITER $$;
CREATE AGGREGATE FUNCTION f1() RETURNS LONGTEXT CHARACTER SET latin1
BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN '';
LOOP
FETCH GROUP NEXT ROW;
END LOOP;
RETURN '';
END;
$$
DELIMITER ;$$
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
DROP TABLE t1;
DROP FUNCTION f1;
DELIMITER $$;
CREATE AGGREGATE FUNCTION f1() RETURNS TINYTEXT CHARACTER SET utf8
BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN '';
LOOP
FETCH GROUP NEXT ROW;
END LOOP;
RETURN '';
END;
$$
DELIMITER ;$$
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
DROP TABLE t1;
DROP FUNCTION f1;
DELIMITER $$;
CREATE AGGREGATE FUNCTION f1() RETURNS TEXT CHARACTER SET utf8
BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN '';
LOOP
FETCH GROUP NEXT ROW;
END LOOP;
RETURN '';
END;
$$
DELIMITER ;$$
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
DROP TABLE t1;
DROP FUNCTION f1;
DELIMITER $$;
CREATE AGGREGATE FUNCTION f1() RETURNS MEDIUMTEXT CHARACTER SET utf8
BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN '';
LOOP
FETCH GROUP NEXT ROW;
END LOOP;
RETURN '';
END;
$$
DELIMITER ;$$
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
DROP TABLE t1;
DROP FUNCTION f1;
DELIMITER $$;
CREATE AGGREGATE FUNCTION f1() RETURNS LONGTEXT CHARACTER SET utf8
BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN '';
LOOP
FETCH GROUP NEXT ROW;
END LOOP;
RETURN '';
END;
$$
DELIMITER ;$$
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
DROP TABLE t1;
DROP FUNCTION f1;

View File

@ -8571,3 +8571,107 @@ affected rows: 5
DROP PROCEDURE p1;
DROP PROCEDURE p2;
drop table t1;
#
# MDEV-15957 Unexpected "Data too long" when doing CREATE..SELECT with stored functions
#
CREATE TABLE t1 (a INT(3));
INSERT INTO t1 VALUES (-999);
CREATE FUNCTION f1(a INT(3)) RETURNS INT(3) RETURN a;
CREATE TABLE t2 AS SELECT CONCAT(a) AS c1, CONCAT(COALESCE(a)) AS c2, CONCAT(f1(a)) AS c3 FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`c1` varchar(11) DEFAULT NULL,
`c2` varchar(11) DEFAULT NULL,
`c3` varchar(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1,t2;
DROP FUNCTION f1;
CREATE FUNCTION f1() RETURNS TINYTEXT CHARACTER SET latin1 RETURN '';
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` tinytext DEFAULT NULL,
`c2` tinytext DEFAULT NULL,
`c3` varchar(255) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
DROP FUNCTION f1;
CREATE FUNCTION f1() RETURNS TEXT CHARACTER SET latin1 RETURN '';
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` text DEFAULT NULL,
`c2` text DEFAULT NULL,
`c3` text DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
DROP FUNCTION f1;
CREATE FUNCTION f1() RETURNS MEDIUMTEXT CHARACTER SET latin1 RETURN '';
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` mediumtext DEFAULT NULL,
`c2` mediumtext DEFAULT NULL,
`c3` mediumtext DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
DROP FUNCTION f1;
CREATE FUNCTION f1() RETURNS LONGTEXT CHARACTER SET latin1 RETURN '';
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` longtext DEFAULT NULL,
`c2` longtext DEFAULT NULL,
`c3` longtext DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
DROP FUNCTION f1;
CREATE FUNCTION f1() RETURNS TINYTEXT CHARACTER SET utf8 RETURN '';
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` tinytext CHARACTER SET utf8 DEFAULT NULL,
`c2` text CHARACTER SET utf8 DEFAULT NULL,
`c3` varchar(255) CHARACTER SET utf8 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
DROP FUNCTION f1;
CREATE FUNCTION f1() RETURNS TEXT CHARACTER SET utf8 RETURN '';
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` text CHARACTER SET utf8 DEFAULT NULL,
`c2` mediumtext CHARACTER SET utf8 DEFAULT NULL,
`c3` mediumtext CHARACTER SET utf8 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
DROP FUNCTION f1;
CREATE FUNCTION f1() RETURNS MEDIUMTEXT CHARACTER SET utf8 RETURN '';
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` mediumtext CHARACTER SET utf8 DEFAULT NULL,
`c2` longtext CHARACTER SET utf8 DEFAULT NULL,
`c3` longtext CHARACTER SET utf8 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
DROP FUNCTION f1;
CREATE FUNCTION f1() RETURNS LONGTEXT CHARACTER SET utf8 RETURN '';
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` longtext CHARACTER SET utf8 DEFAULT NULL,
`c2` longtext CHARACTER SET utf8 DEFAULT NULL,
`c3` longtext CHARACTER SET utf8 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
DROP FUNCTION f1;

View File

@ -10120,3 +10120,64 @@ CALL p2();
DROP PROCEDURE p1;
DROP PROCEDURE p2;
drop table t1;
--echo #
--echo # MDEV-15957 Unexpected "Data too long" when doing CREATE..SELECT with stored functions
--echo #
CREATE TABLE t1 (a INT(3));
INSERT INTO t1 VALUES (-999);
CREATE FUNCTION f1(a INT(3)) RETURNS INT(3) RETURN a;
CREATE TABLE t2 AS SELECT CONCAT(a) AS c1, CONCAT(COALESCE(a)) AS c2, CONCAT(f1(a)) AS c3 FROM t1;
SHOW CREATE TABLE t2;
DROP TABLE t1,t2;
DROP FUNCTION f1;
CREATE FUNCTION f1() RETURNS TINYTEXT CHARACTER SET latin1 RETURN '';
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
DROP TABLE t1;
DROP FUNCTION f1;
CREATE FUNCTION f1() RETURNS TEXT CHARACTER SET latin1 RETURN '';
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
DROP TABLE t1;
DROP FUNCTION f1;
CREATE FUNCTION f1() RETURNS MEDIUMTEXT CHARACTER SET latin1 RETURN '';
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
DROP TABLE t1;
DROP FUNCTION f1;
CREATE FUNCTION f1() RETURNS LONGTEXT CHARACTER SET latin1 RETURN '';
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
DROP TABLE t1;
DROP FUNCTION f1;
CREATE FUNCTION f1() RETURNS TINYTEXT CHARACTER SET utf8 RETURN '';
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
DROP TABLE t1;
DROP FUNCTION f1;
CREATE FUNCTION f1() RETURNS TEXT CHARACTER SET utf8 RETURN '';
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
DROP TABLE t1;
DROP FUNCTION f1;
CREATE FUNCTION f1() RETURNS MEDIUMTEXT CHARACTER SET utf8 RETURN '';
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
DROP TABLE t1;
DROP FUNCTION f1;
CREATE FUNCTION f1() RETURNS LONGTEXT CHARACTER SET utf8 RETURN '';
CREATE TABLE t1 AS SELECT f1() AS c1, COALESCE(f1()) AS c2, CONCAT(f1()) AS c3;
SHOW CREATE TABLE t1;
DROP TABLE t1;
DROP FUNCTION f1;

View File

@ -14,7 +14,7 @@ CREATE TABLE t1 AS SELECT f1(REPEAT('a',2000)) AS a;;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE "t1" (
"a" text DEFAULT NULL
"a" varchar(2000) DEFAULT NULL
)
DROP TABLE t1;
DROP FUNCTION f1;
@ -30,7 +30,7 @@ CREATE TABLE t1 AS SELECT f1(REPEAT('a',2000)) AS a;;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE "t1" (
"a" text CHARACTER SET utf8 DEFAULT NULL
"a" varchar(2000) CHARACTER SET utf8 DEFAULT NULL
)
DROP TABLE t1;
DROP FUNCTION f1;
@ -46,7 +46,7 @@ CREATE TABLE t1 AS SELECT f1(REPEAT('a',2000)) AS a;;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE "t1" (
"a" blob DEFAULT NULL
"a" varbinary(2000) DEFAULT NULL
)
DROP TABLE t1;
DROP FUNCTION f1;
@ -62,7 +62,7 @@ CREATE TABLE t1 AS SELECT f1(REPEAT('a',4000)) AS a;;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE "t1" (
"a" text DEFAULT NULL
"a" varchar(4000) DEFAULT NULL
)
DROP TABLE t1;
DROP FUNCTION f1;
@ -78,7 +78,7 @@ CREATE TABLE t1 AS SELECT f1(REPEAT('a',4000)) AS a;;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE "t1" (
"a" text DEFAULT NULL
"a" varchar(4000) DEFAULT NULL
)
DROP TABLE t1;
DROP FUNCTION f1;
@ -94,7 +94,7 @@ CREATE TABLE t1 AS SELECT f1(REPEAT('a',4000)) AS a;;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE "t1" (
"a" text CHARACTER SET utf8 DEFAULT NULL
"a" varchar(4000) CHARACTER SET utf8 DEFAULT NULL
)
DROP TABLE t1;
DROP FUNCTION f1;
@ -110,7 +110,7 @@ CREATE TABLE t1 AS SELECT f1(REPEAT('a',4000)) AS a;;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE "t1" (
"a" blob DEFAULT NULL
"a" varbinary(4000) DEFAULT NULL
)
DROP TABLE t1;
DROP FUNCTION f1;
@ -126,7 +126,7 @@ CREATE TABLE t1 AS SELECT f1(REPEAT('a',4000)) AS a;;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE "t1" (
"a" blob DEFAULT NULL
"a" varbinary(4000) DEFAULT NULL
)
DROP TABLE t1;
DROP FUNCTION f1;

View File

@ -770,7 +770,7 @@ public:
{
return DTCollation(charset(), derivation(), repertoire());
}
Type_std_attributes type_std_attributes() const
virtual Type_std_attributes type_std_attributes() const
{
return Type_std_attributes(field_length, decimals(),
MY_TEST(flags & UNSIGNED_FLAG),
@ -2002,6 +2002,24 @@ public:
int store_time_dec(const MYSQL_TIME *ltime, uint dec);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
virtual uint numeric_precision() const= 0;
Type_std_attributes type_std_attributes() const
{
/*
For integer data types, the user-specified length does not constrain the
supported range, so e.g. a column of the INT(1) data type supports the
full integer range anyway.
Choose the maximum from the user-specified length and the maximum
possible length determined by the data type capacity:
INT(1) -> 11
INT(10) -> 11
INT(40) -> 40
*/
uint32 length1= max_display_length();
uint32 length2= field_length;
return Type_std_attributes(MY_MAX(length1, length2), decimals(),
MY_TEST(flags & UNSIGNED_FLAG),
dtcollation());
}
Information_schema_numeric_attributes
information_schema_numeric_attributes() const
{
@ -3581,6 +3599,12 @@ public:
}
enum ha_base_keytype key_type() const
{ return binary() ? HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2; }
Type_std_attributes type_std_attributes() const
{
return Type_std_attributes(Field_blob::max_display_length(), decimals(),
MY_TEST(flags & UNSIGNED_FLAG),
dtcollation());
}
Information_schema_character_attributes
information_schema_character_attributes() const
{

View File

@ -3165,45 +3165,16 @@ Item_field::Item_field(THD *thd, Item_field *item)
}
/**
Calculate the max column length not taking into account the
limitations over integer types.
When storing data into fields the server currently just ignores the
limits specified on integer types, e.g. 1234 can safely be stored in
an int(2) and will not cause an error.
Thus when creating temporary tables and doing transformations
we must adjust the maximum field length to reflect this fact.
We take the un-restricted maximum length and adjust it similarly to
how the declared length is adjusted wrt unsignedness etc.
TODO: this all needs to go when we disable storing 1234 in int(2).
@param field_par Original field the use to calculate the lengths
@param max_length Item's calculated explicit max length
@return The adjusted max length
*/
inline static uint32
adjust_max_effective_column_length(Field *field_par, uint32 max_length)
{
uint32 new_max_length= field_par->max_display_length();
/* Adjust only if the actual precision based one is bigger than specified */
return new_max_length > max_length ? new_max_length : max_length;
}
void Item_field::set_field(Field *field_par)
{
field=result_field=field_par; // for easy coding with fields
maybe_null=field->maybe_null();
Type_std_attributes::set(field_par);
Type_std_attributes::set(field_par->type_std_attributes());
table_name= *field_par->table_name;
field_name= field_par->field_name;
db_name= field_par->table->s->db.str;
alias_name_used= field_par->table->alias_name_used;
max_length= adjust_max_effective_column_length(field_par, max_length);
fixed= 1;
if (field->table->s->tmp_table == SYSTEM_TMP_TABLE)
any_privileges= 0;

View File

@ -2822,7 +2822,7 @@ public:
const char *table_name_arg):
Item(thd), field(par_field), db_name(db_arg), table_name(table_name_arg)
{
Type_std_attributes::set(par_field);
Type_std_attributes::set(par_field->type_std_attributes());
}
enum Type type() const { return FIELD_ITEM; }
double val_real() { return field->val_real(); }

View File

@ -2838,7 +2838,7 @@ public:
{
return result_type() != STRING_RESULT ?
sp_result_field :
tmp_table_field_from_field_type(table);
create_table_field_from_handler(table);
}
void make_send_field(THD *thd, Send_field *tmp_field);

View File

@ -1386,7 +1386,7 @@ Item_sum_sp::fix_length_and_dec()
{
DBUG_ENTER("Item_sum_sp::fix_length_and_dec");
DBUG_ASSERT(sp_result_field);
Type_std_attributes::set(sp_result_field);
Type_std_attributes::set(sp_result_field->type_std_attributes());
Item_sum::fix_length_and_dec();
DBUG_VOID_RETURN;
}

View File

@ -1297,6 +1297,10 @@ public:
{
return SP_AGGREGATE_FUNC;
}
Field *create_field_for_create_select(TABLE *table)
{
return create_table_field_from_handler(table);
}
void fix_length_and_dec();
bool fix_fields(THD *thd, Item **ref);
const char *func_name() const;

View File

@ -905,8 +905,13 @@ sp_head::create_result_field(uint field_max_length, const LEX_CSTRING *field_nam
Perhaps we should refactor prepare_create_field() to set
Create_field::length to maximum octet length for BLOBs,
instead of packed length).
Note, for integer data types, field_max_length can be bigger
than the user specified length, e.g. a field of the INT(1) data type
is translated to the item with max_length=11.
*/
DBUG_ASSERT(field_max_length <= m_return_field_def.length ||
m_return_field_def.type_handler()->cmp_type() == INT_RESULT ||
(current_thd->stmt_arena->is_stmt_execute() &&
m_return_field_def.length == 8 &&
(m_return_field_def.pack_flag &

View File

@ -160,15 +160,6 @@ void Temporal_with_date::make_from_item(THD *thd, Item *item, sql_mode_t flags)
}
void Type_std_attributes::set(const Field *field)
{
decimals= field->decimals();
unsigned_flag= MY_TEST(field->flags & UNSIGNED_FLAG);
collation.set(field->charset(), field->derivation(), field->repertoire());
fix_char_length(field->char_length());
}
uint Type_std_attributes::count_max_decimals(Item **item, uint nitems)
{
uint res= 0;

View File

@ -617,7 +617,6 @@ public:
{
*this= other;
}
void set(const Field *field);
uint32 max_char_length() const
{ return max_length / collation.collation->mbmaxlen; }
void fix_length_and_charset(uint32 max_char_length_arg, CHARSET_INFO *cs)