Commit e42f4e31 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-6688 Illegal mix of collation with bit string B'01100001'

parent 36f50be9
...@@ -5996,5 +5996,17 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -5996,5 +5996,17 @@ id select_type table type possible_keys key key_len ref rows Extra
DEALLOCATE PREPARE stmt; DEALLOCATE PREPARE stmt;
DROP TABLE t1; DROP TABLE t1;
# #
# MDEV-6688 Illegal mix of collation with bit string B'01100001'
#
CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1, b INT);
INSERT INTO t1 VALUES ('a',1);
SELECT CONCAT(a, IF(b>10, _utf8 X'61', _utf8 X'61')) FROM t1;
CONCAT(a, IF(b>10, _utf8 X'61', _utf8 X'61'))
aa
SELECT CONCAT(a, IF(b>10, _utf8 X'61', _utf8 B'01100001')) FROM t1;
CONCAT(a, IF(b>10, _utf8 X'61', _utf8 B'01100001'))
aa
DROP TABLE t1;
#
# End of 10.0 tests # End of 10.0 tests
# #
...@@ -1710,6 +1710,16 @@ EXECUTE stmt USING @arg; ...@@ -1710,6 +1710,16 @@ EXECUTE stmt USING @arg;
DEALLOCATE PREPARE stmt; DEALLOCATE PREPARE stmt;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # MDEV-6688 Illegal mix of collation with bit string B'01100001'
--echo #
CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1, b INT);
INSERT INTO t1 VALUES ('a',1);
SELECT CONCAT(a, IF(b>10, _utf8 X'61', _utf8 X'61')) FROM t1;
SELECT CONCAT(a, IF(b>10, _utf8 X'61', _utf8 B'01100001')) FROM t1;
DROP TABLE t1;
--echo # --echo #
--echo # End of 10.0 tests --echo # End of 10.0 tests
--echo # --echo #
...@@ -2711,6 +2711,23 @@ class Item_static_float_func :public Item_float ...@@ -2711,6 +2711,23 @@ class Item_static_float_func :public Item_float
class Item_string :public Item_basic_constant class Item_string :public Item_basic_constant
{ {
bool m_cs_specified;
protected:
/**
Set the value of m_cs_specified attribute.
m_cs_specified attribute shows whether character-set-introducer was
explicitly specified in the original query for this text literal or
not. The attribute makes sense (is used) only for views.
This operation is to be called from the parser during parsing an input
query.
*/
inline void set_cs_specified(bool cs_specified)
{
m_cs_specified= cs_specified;
}
public: public:
Item_string(const char *str,uint length, Item_string(const char *str,uint length,
CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE, CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE,
...@@ -2860,21 +2877,6 @@ class Item_string :public Item_basic_constant ...@@ -2860,21 +2877,6 @@ class Item_string :public Item_basic_constant
return m_cs_specified; return m_cs_specified;
} }
/**
Set the value of m_cs_specified attribute.
m_cs_specified attribute shows whether character-set-introducer was
explicitly specified in the original query for this text literal or
not. The attribute makes sense (is used) only for views.
This operation is to be called from the parser during parsing an input
query.
*/
inline void set_cs_specified(bool cs_specified)
{
m_cs_specified= cs_specified;
}
String *check_well_formed_result(bool send_error) String *check_well_formed_result(bool send_error)
{ return Item::check_well_formed_result(&str_value, send_error); } { return Item::check_well_formed_result(&str_value, send_error); }
...@@ -2906,8 +2908,24 @@ class Item_string :public Item_basic_constant ...@@ -2906,8 +2908,24 @@ class Item_string :public Item_basic_constant
} }
return MYSQL_TYPE_STRING; // Not a temporal literal return MYSQL_TYPE_STRING; // Not a temporal literal
} }
private: };
bool m_cs_specified;
class Item_string_with_introducer :public Item_string
{
public:
Item_string_with_introducer(const char *str, uint length, CHARSET_INFO *cs)
:Item_string(str, length, cs)
{
set_repertoire_from_value();
set_cs_specified(true);
}
Item_string_with_introducer(const String *str, CHARSET_INFO *tocs)
:Item_string(str->ptr(), str->length(), tocs)
{
set_repertoire_from_value();
set_cs_specified(true);
}
}; };
......
...@@ -1648,7 +1648,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -1648,7 +1648,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <lex_str> %type <lex_str>
IDENT IDENT_QUOTED TEXT_STRING DECIMAL_NUM FLOAT_NUM NUM LONG_NUM IDENT IDENT_QUOTED TEXT_STRING DECIMAL_NUM FLOAT_NUM NUM LONG_NUM
HEX_NUM HEX_STRING hex_num_or_string HEX_NUM HEX_STRING
LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident ident_or_text LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident ident_or_text
IDENT_sys TEXT_STRING_sys TEXT_STRING_literal IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
NCHAR_STRING opt_component key_cache_name NCHAR_STRING opt_component key_cache_name
...@@ -1666,7 +1666,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -1666,7 +1666,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
remember_name remember_end opt_db text_or_password remember_name remember_end opt_db text_or_password
%type <string> %type <string>
text_string opt_gconcat_separator text_string hex_or_bin_String opt_gconcat_separator
%type <num> %type <num>
type type_with_opt_collate int_type real_type order_dir lock_option type type_with_opt_collate int_type real_type order_dir lock_option
...@@ -6517,11 +6517,6 @@ now_or_signed_literal: ...@@ -6517,11 +6517,6 @@ now_or_signed_literal:
{ $$=$1; } { $$=$1; }
; ;
hex_num_or_string:
HEX_NUM {}
| HEX_STRING {}
;
charset: charset:
CHAR_SYM SET {} CHAR_SYM SET {}
| CHARSET {} | CHARSET {}
...@@ -13253,14 +13248,10 @@ text_literal: ...@@ -13253,14 +13248,10 @@ text_literal:
} }
| UNDERSCORE_CHARSET TEXT_STRING | UNDERSCORE_CHARSET TEXT_STRING
{ {
Item_string *str= new (thd->mem_root) Item_string($2.str, $$= new (thd->mem_root) Item_string_with_introducer($2.str,
$2.length, $1); $2.length, $1);
if (str == NULL) if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
str->set_repertoire_from_value();
str->set_cs_specified(TRUE);
$$= str;
} }
| text_literal TEXT_STRING_literal | text_literal TEXT_STRING_literal
{ {
...@@ -13289,7 +13280,12 @@ text_string: ...@@ -13289,7 +13280,12 @@ text_string:
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| HEX_NUM | hex_or_bin_String { $$= $1; }
;
hex_or_bin_String:
HEX_NUM
{ {
Item *tmp= new (thd->mem_root) Item_hex_hybrid($1.str, $1.length); Item *tmp= new (thd->mem_root) Item_hex_hybrid($1.str, $1.length);
if (tmp == NULL) if (tmp == NULL)
...@@ -13394,60 +13390,12 @@ literal: ...@@ -13394,60 +13390,12 @@ literal:
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| UNDERSCORE_CHARSET hex_num_or_string | UNDERSCORE_CHARSET hex_or_bin_String
{ {
Item *tmp= new (thd->mem_root) Item_hex_string($2.str, $2.length); Item_string_with_introducer *item_str;
if (tmp == NULL) item_str= new (thd->mem_root) Item_string_with_introducer($2, $1);
if (!item_str || !item_str->check_well_formed_result(true))
MYSQL_YYABORT; MYSQL_YYABORT;
/*
it is OK only emulate fix_fieds, because we need only
value of constant
*/
tmp->quick_fix_field();
String *str= tmp->val_str((String*) 0);
Item_string *item_str;
item_str= new (thd->mem_root)
Item_string(NULL, /* name will be set in select_item */
str ? str->ptr() : "",
str ? str->length() : 0,
$1);
if (!item_str ||
!item_str->check_well_formed_result(true))
{
MYSQL_YYABORT;
}
item_str->set_repertoire_from_value();
item_str->set_cs_specified(TRUE);
$$= item_str;
}
| UNDERSCORE_CHARSET BIN_NUM
{
Item *tmp= new (thd->mem_root) Item_bin_string($2.str, $2.length);
if (tmp == NULL)
MYSQL_YYABORT;
/*
it is OK only emulate fix_fieds, because we need only
value of constant
*/
tmp->quick_fix_field();
String *str= tmp->val_str((String*) 0);
Item_string *item_str;
item_str= new (thd->mem_root)
Item_string(NULL, /* name will be set in select_item */
str ? str->ptr() : "",
str ? str->length() : 0,
$1);
if (!item_str ||
!item_str->check_well_formed_result(true))
{
MYSQL_YYABORT;
}
item_str->set_cs_specified(TRUE);
$$= item_str; $$= item_str;
} }
......
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