Skip to content

Commit 5cc4330

Browse files
author
Xing Zhang
committed
Bug#28960901: ASSERTION FAILED: (TLEN % 2) == 0
At preparing phase, Arg_comparator::set_cmp_func() and Arg_comparator::set_compare_func() set the character set which is used to do string comparison. But user variable's character set at execution phase might have changed since it was estimated at preparing phase. This may cause assert failure if the comparing character set is ucs2/utf16/utf32 and the string's character can be single byte character. Fix: Convert the string to the charset which is determined at preparing phase. Change-Id: Ic2b67c6027ee1c5fcfd0502ca90ecb90ef326445
1 parent fcd6b92 commit 5cc4330

File tree

3 files changed

+51
-0
lines changed

3 files changed

+51
-0
lines changed

mysql-test/r/user_var.result

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,3 +835,26 @@ ERROR 42000: Result consisted of more than one row
835835
SET @x= 2;
836836
SELECT a FROM t1 WHERE a = @x INTO @x;
837837
DROP TABLE t1;
838+
#
839+
# Bug#28960901: ASSERTION FAILED: (TLEN % 2) == 0
840+
#
841+
CREATE TABLE t1(a VARCHAR(10) CHARSET latin1, b VARCHAR(20) CHARSET utf16);
842+
INSERT INTO t1 VALUES ('a', 'abcd');
843+
SELECT (@x:=b) FROM t1;
844+
(@x:=b)
845+
abcd
846+
Warnings:
847+
Warning 1287 Setting user variables within expressions is deprecated and will be removed in a future release. Consider alternatives: 'SET variable=expression, ...', or 'SELECT expression(s) INTO variables(s)'.
848+
SELECT * FROM t1 WHERE b = (SELECT (@x:=1) FROM t1) OR a = @x;
849+
a b
850+
Warnings:
851+
Warning 1287 Setting user variables within expressions is deprecated and will be removed in a future release. Consider alternatives: 'SET variable=expression, ...', or 'SELECT expression(s) INTO variables(s)'.
852+
Warning 1292 Truncated incorrect DOUBLE value: ''
853+
SELECT (@x:=a) FROM t1;
854+
(@x:=a)
855+
a
856+
Warnings:
857+
Warning 1287 Setting user variables within expressions is deprecated and will be removed in a future release. Consider alternatives: 'SET variable=expression, ...', or 'SELECT expression(s) INTO variables(s)'.
858+
SELECT * FROM t1 WHERE a = (SELECT (@x:=_utf16 0x1023) FROM t1) OR b = @x;
859+
ERROR HY000: Invalid latin1 character string: '\x10\x23'
860+
DROP TABLE t1;

mysql-test/t/user_var.test

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,3 +549,15 @@ SET @x= 2;
549549
eval $query3;
550550

551551
DROP TABLE t1;
552+
553+
--echo #
554+
--echo # Bug#28960901: ASSERTION FAILED: (TLEN % 2) == 0
555+
--echo #
556+
CREATE TABLE t1(a VARCHAR(10) CHARSET latin1, b VARCHAR(20) CHARSET utf16);
557+
INSERT INTO t1 VALUES ('a', 'abcd');
558+
SELECT (@x:=b) FROM t1;
559+
SELECT * FROM t1 WHERE b = (SELECT (@x:=1) FROM t1) OR a = @x;
560+
SELECT (@x:=a) FROM t1;
561+
--error ER_INVALID_CHARACTER_STRING
562+
SELECT * FROM t1 WHERE a = (SELECT (@x:=_utf16 0x1023) FROM t1) OR b = @x;
563+
DROP TABLE t1;

sql/item_func.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5794,6 +5794,22 @@ String *Item_func_get_user_var::val_str(String *str) {
57945794
DBUG_ENTER("Item_func_get_user_var::val_str");
57955795
if (!var_entry) DBUG_RETURN((String *)0); // No such variable
57965796
String *res = var_entry->val_str(&null_value, str, decimals);
5797+
if (res && !my_charset_same(res->charset(), collation.collation)) {
5798+
uint error;
5799+
if (str->copy(var_entry->ptr(), var_entry->length(),
5800+
var_entry->collation.collation, collation.collation,
5801+
&error) ||
5802+
error > 0) {
5803+
char tmp[32];
5804+
convert_to_printable(tmp, sizeof(tmp), var_entry->ptr(),
5805+
var_entry->length(), var_entry->collation.collation,
5806+
6);
5807+
my_error(ER_INVALID_CHARACTER_STRING, MYF(0), collation.collation->csname,
5808+
tmp);
5809+
DBUG_RETURN(nullptr);
5810+
}
5811+
DBUG_RETURN(str);
5812+
}
57975813
DBUG_RETURN(res);
57985814
}
57995815

0 commit comments

Comments
 (0)