MDEV-6688 Illegal mix of collation with bit string B'01100001'
This commit is contained in:
parent
36f50be970
commit
e42f4e3199
@ -5996,5 +5996,17 @@ id select_type table type possible_keys key key_len ref rows Extra
|
||||
DEALLOCATE PREPARE stmt;
|
||||
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
|
||||
#
|
||||
|
@ -1710,6 +1710,16 @@ EXECUTE stmt USING @arg;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
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 # End of 10.0 tests
|
||||
--echo #
|
||||
|
52
sql/item.h
52
sql/item.h
@ -2711,6 +2711,23 @@ public:
|
||||
|
||||
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:
|
||||
Item_string(const char *str,uint length,
|
||||
CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE,
|
||||
@ -2860,21 +2877,6 @@ public:
|
||||
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)
|
||||
{ return Item::check_well_formed_result(&str_value, send_error); }
|
||||
|
||||
@ -2906,8 +2908,24 @@ public:
|
||||
}
|
||||
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);
|
||||
|
||||
%type <lex_str>
|
||||
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
|
||||
IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
|
||||
NCHAR_STRING opt_component key_cache_name
|
||||
@ -1666,7 +1666,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||
remember_name remember_end opt_db text_or_password
|
||||
|
||||
%type <string>
|
||||
text_string opt_gconcat_separator
|
||||
text_string hex_or_bin_String opt_gconcat_separator
|
||||
|
||||
%type <num>
|
||||
type type_with_opt_collate int_type real_type order_dir lock_option
|
||||
@ -6517,11 +6517,6 @@ now_or_signed_literal:
|
||||
{ $$=$1; }
|
||||
;
|
||||
|
||||
hex_num_or_string:
|
||||
HEX_NUM {}
|
||||
| HEX_STRING {}
|
||||
;
|
||||
|
||||
charset:
|
||||
CHAR_SYM SET {}
|
||||
| CHARSET {}
|
||||
@ -13253,14 +13248,10 @@ text_literal:
|
||||
}
|
||||
| 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);
|
||||
if (str == NULL)
|
||||
if ($$ == NULL)
|
||||
MYSQL_YYABORT;
|
||||
str->set_repertoire_from_value();
|
||||
str->set_cs_specified(TRUE);
|
||||
|
||||
$$= str;
|
||||
}
|
||||
| text_literal TEXT_STRING_literal
|
||||
{
|
||||
@ -13289,7 +13280,12 @@ text_string:
|
||||
if ($$ == NULL)
|
||||
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);
|
||||
if (tmp == NULL)
|
||||
@ -13394,60 +13390,12 @@ literal:
|
||||
if ($$ == NULL)
|
||||
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);
|
||||
if (tmp == NULL)
|
||||
Item_string_with_introducer *item_str;
|
||||
item_str= new (thd->mem_root) Item_string_with_introducer($2, $1);
|
||||
if (!item_str || !item_str->check_well_formed_result(true))
|
||||
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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user