Commit 071aece9 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-14376 Explicit CAST(CHAR(N)) erroneously escalates warnings to errors in STRICT_ALL_TABLES

parent 06117977
...@@ -587,3 +587,140 @@ SHOW CREATE TABLE t1; ...@@ -587,3 +587,140 @@ SHOW CREATE TABLE t1;
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
SET sql_mode=DEFAULT; SET sql_mode=DEFAULT;
--echo #
--echo # MDEV-14376 Explicit CAST(CHAR(N)) erroneously escalates warnings to errors in STRICT_ALL_TABLES
--echo #
SET sql_mode=STRICT_ALL_TABLES;
SELECT CAST('xxx' AS CHAR(1));
CREATE OR REPLACE TABLE t1 (a VARCHAR(1));
INSERT INTO t1 VALUES (CAST('xxx' AS CHAR(1)));
DROP TABLE t1;
CREATE OR REPLACE TABLE t1 (a VARCHAR(3));
INSERT INTO t1 VALUES ('xxx');
UPDATE t1 SET a=CAST(a AS CHAR(1));
DROP TABLE t1;
DELIMITER $$;
BEGIN NOT ATOMIC
DECLARE a VARCHAR(30) CHARACTER SET latin1;
SET a=CAST('xxx' AS CHAR(1));
END;
$$
DELIMITER ;$$
DELIMITER $$;
BEGIN NOT ATOMIC
DECLARE a VARCHAR(30) CHARACTER SET latin1;
SET a=CAST(_latin1'xxx' AS CHAR(1) CHARACTER SET latin1);
END;
$$
DELIMITER ;$$
DELIMITER $$;
BEGIN NOT ATOMIC
DECLARE a VARCHAR(30) CHARACTER SET latin1;
SET a=CAST(_latin1'xxx' AS CHAR(1) CHARACTER SET utf8);
END;
$$
DELIMITER ;$$
DELIMITER $$;
BEGIN NOT ATOMIC
DECLARE a VARCHAR(30) CHARACTER SET utf8;
SET a=CAST('xxx' AS CHAR(1));
END;
$$
DELIMITER ;$$
DELIMITER $$;
BEGIN NOT ATOMIC
DECLARE a VARCHAR(30) CHARACTER SET utf8;
SET a=CAST(_latin1'xxx' AS CHAR(1) CHARACTER SET latin1);
END;
$$
DELIMITER ;$$
DELIMITER $$;
BEGIN NOT ATOMIC
DECLARE a VARCHAR(30) CHARACTER SET utf8;
SET a=CAST(_latin1'xxx' AS CHAR(1) CHARACTER SET utf8);
END;
$$
DELIMITER ;$$
--echo # Conversion problems still escalate warnings to errors (without right truncation)
DELIMITER $$;
--error ER_CANNOT_CONVERT_CHARACTER
BEGIN NOT ATOMIC
DECLARE a VARCHAR(30) CHARACTER SET utf8;
SET a=CAST(_utf8 0xD18F AS CHAR(1) CHARACTER SET latin1);
END;
$$
DELIMITER ;$$
--echo # Conversion problems still escalate warnings to errors (with right truncation)
DELIMITER $$;
--error ER_CANNOT_CONVERT_CHARACTER
BEGIN NOT ATOMIC
DECLARE a VARCHAR(30) CHARACTER SET utf8;
SET a=CAST(_utf8 0xD18FD18F AS CHAR(1) CHARACTER SET latin1);
END;
$$
DELIMITER ;$$
--echo # CAST(number AS CHAR) escalates warnings to errors on truncation
CREATE OR REPLACE TABLE t1 (a VARCHAR(10));
--error ER_TRUNCATED_WRONG_VALUE
INSERT INTO t1 VALUES (CAST(123 AS CHAR(1)));
DROP TABLE t1;
CREATE OR REPLACE TABLE t1 (a VARCHAR(10));
INSERT INTO t1 VALUES ('1');
--error ER_TRUNCATED_WRONG_VALUE
UPDATE t1 SET a=CAST(123 AS CHAR(1));
DROP TABLE t1;
DELIMITER $$;
--error ER_TRUNCATED_WRONG_VALUE
BEGIN NOT ATOMIC
DECLARE a VARCHAR(10);
SET a=CAST(123 AS CHAR(1));
END;
$$
DELIMITER ;$$
--echo # CAST(temporal AS CHAR) escalates warnings to errors on truncation
CREATE OR REPLACE TABLE t1 (a VARCHAR(10));
--error ER_TRUNCATED_WRONG_VALUE
INSERT INTO t1 VALUES (CAST(TIME'10:20:30' AS CHAR(1)));
DROP TABLE t1;
CREATE OR REPLACE TABLE t1 (a VARCHAR(10));
INSERT INTO t1 VALUES ('1');
--error ER_TRUNCATED_WRONG_VALUE
UPDATE t1 SET a=CAST(TIME'10:20:30' AS CHAR(1));
DROP TABLE t1;
DELIMITER $$;
--error ER_TRUNCATED_WRONG_VALUE
BEGIN NOT ATOMIC
DECLARE a VARCHAR(10);
SET a=CAST(TIME'10:20:30' AS CHAR(1));
END;
$$
DELIMITER ;$$
SET sql_mode=DEFAULT;
...@@ -2434,6 +2434,8 @@ void Item_char_typecast::check_truncation_with_warn(String *src, uint dstlen) ...@@ -2434,6 +2434,8 @@ void Item_char_typecast::check_truncation_with_warn(String *src, uint dstlen)
THD *thd= current_thd; THD *thd= current_thd;
char char_type[40]; char char_type[40];
ErrConvString err(src); ErrConvString err(src);
bool save_abort_on_warning= thd->abort_on_warning;
thd->abort_on_warning&= !m_suppress_warning_to_error_escalation;
my_snprintf(char_type, sizeof(char_type), "%s(%lu)", my_snprintf(char_type, sizeof(char_type), "%s(%lu)",
cast_cs == &my_charset_bin ? "BINARY" : "CHAR", cast_cs == &my_charset_bin ? "BINARY" : "CHAR",
(ulong) cast_length); (ulong) cast_length);
...@@ -2441,6 +2443,7 @@ void Item_char_typecast::check_truncation_with_warn(String *src, uint dstlen) ...@@ -2441,6 +2443,7 @@ void Item_char_typecast::check_truncation_with_warn(String *src, uint dstlen)
ER_TRUNCATED_WRONG_VALUE, ER_TRUNCATED_WRONG_VALUE,
ER_THD(thd, ER_TRUNCATED_WRONG_VALUE), char_type, ER_THD(thd, ER_TRUNCATED_WRONG_VALUE), char_type,
err.ptr()); err.ptr());
thd->abort_on_warning= save_abort_on_warning;
} }
} }
...@@ -2551,7 +2554,7 @@ void Item_char_typecast::fix_length_and_dec_numeric() ...@@ -2551,7 +2554,7 @@ void Item_char_typecast::fix_length_and_dec_numeric()
} }
void Item_char_typecast::fix_length_and_dec_str() void Item_char_typecast::fix_length_and_dec_generic()
{ {
fix_length_and_dec_internal(from_cs= args[0]->dynamic_result() ? fix_length_and_dec_internal(from_cs= args[0]->dynamic_result() ?
0 : 0 :
......
...@@ -1089,6 +1089,7 @@ class Item_char_typecast :public Item_str_func ...@@ -1089,6 +1089,7 @@ class Item_char_typecast :public Item_str_func
CHARSET_INFO *cast_cs, *from_cs; CHARSET_INFO *cast_cs, *from_cs;
bool charset_conversion; bool charset_conversion;
String tmp_value; String tmp_value;
bool m_suppress_warning_to_error_escalation;
bool has_explicit_length() const { return cast_length != ~0U; } bool has_explicit_length() const { return cast_length != ~0U; }
String *reuse(String *src, uint32 length); String *reuse(String *src, uint32 length);
String *copy(String *src, CHARSET_INFO *cs); String *copy(String *src, CHARSET_INFO *cs);
...@@ -1097,14 +1098,20 @@ class Item_char_typecast :public Item_str_func ...@@ -1097,14 +1098,20 @@ class Item_char_typecast :public Item_str_func
void fix_length_and_dec_internal(CHARSET_INFO *fromcs); void fix_length_and_dec_internal(CHARSET_INFO *fromcs);
public: public:
Item_char_typecast(THD *thd, Item *a, uint length_arg, CHARSET_INFO *cs_arg): Item_char_typecast(THD *thd, Item *a, uint length_arg, CHARSET_INFO *cs_arg):
Item_str_func(thd, a), cast_length(length_arg), cast_cs(cs_arg) {} Item_str_func(thd, a), cast_length(length_arg), cast_cs(cs_arg),
m_suppress_warning_to_error_escalation(false) {}
enum Functype functype() const { return CHAR_TYPECAST_FUNC; } enum Functype functype() const { return CHAR_TYPECAST_FUNC; }
bool eq(const Item *item, bool binary_cmp) const; bool eq(const Item *item, bool binary_cmp) const;
const char *func_name() const { return "cast_as_char"; } const char *func_name() const { return "cast_as_char"; }
CHARSET_INFO *cast_charset() const { return cast_cs; } CHARSET_INFO *cast_charset() const { return cast_cs; }
String *val_str(String *a); String *val_str(String *a);
void fix_length_and_dec_generic();
void fix_length_and_dec_numeric(); void fix_length_and_dec_numeric();
void fix_length_and_dec_str(); void fix_length_and_dec_str()
{
fix_length_and_dec_generic();
m_suppress_warning_to_error_escalation= true;
}
void fix_length_and_dec() void fix_length_and_dec()
{ {
args[0]->type_handler()->Item_char_typecast_fix_length_and_dec(this); args[0]->type_handler()->Item_char_typecast_fix_length_and_dec(this);
......
...@@ -4339,7 +4339,7 @@ bool Type_handler:: ...@@ -4339,7 +4339,7 @@ bool Type_handler::
bool Type_handler:: bool Type_handler::
Item_char_typecast_fix_length_and_dec(Item_char_typecast *item) const Item_char_typecast_fix_length_and_dec(Item_char_typecast *item) const
{ {
item->fix_length_and_dec_str(); item->fix_length_and_dec_generic();
return false; return false;
} }
...@@ -4352,6 +4352,14 @@ bool Type_handler_numeric:: ...@@ -4352,6 +4352,14 @@ bool Type_handler_numeric::
} }
bool Type_handler_string_result::
Item_char_typecast_fix_length_and_dec(Item_char_typecast *item) const
{
item->fix_length_and_dec_str();
return false;
}
bool Type_handler:: bool Type_handler::
Item_time_typecast_fix_length_and_dec(Item_time_typecast *item) const Item_time_typecast_fix_length_and_dec(Item_time_typecast *item) const
{ {
......
...@@ -1717,6 +1717,7 @@ class Type_handler_string_result: public Type_handler ...@@ -1717,6 +1717,7 @@ class Type_handler_string_result: public Type_handler
MYSQL_TIME *, ulonglong fuzzydate) const; MYSQL_TIME *, ulonglong fuzzydate) const;
bool Item_func_between_fix_length_and_dec(Item_func_between *func) const; bool Item_func_between_fix_length_and_dec(Item_func_between *func) const;
longlong Item_func_between_val_int(Item_func_between *func) const; longlong Item_func_between_val_int(Item_func_between *func) const;
bool Item_char_typecast_fix_length_and_dec(Item_char_typecast *) const;
cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const; cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const; in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const;
bool Item_func_in_fix_comparator_compatible_types(THD *thd, bool Item_func_in_fix_comparator_compatible_types(THD *thd,
......
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