| Bug #118237 | Inconsistent results when using prepared statement or session variables | ||
|---|---|---|---|
| Submitted: | 21 May 2025 8:44 | Modified: | 7 Feb 19:11 |
| Reporter: | Malt Chen | Email Updates: | |
| Status: | Not a Bug | Impact on me: | |
| Category: | MySQL Server: Charsets | Severity: | S3 (Non-critical) |
| Version: | 9.2 | OS: | Any |
| Assigned to: | CPU Architecture: | Any | |
[7 Feb 19:11]
Roy Lyseng
Thank you for the bug report. The behavior may seem inconsistent, but there is logic behind the decisions. The BINARY qualifier has two purposes: It sets character set as BINARY, and when used in an expression, it forces BINARY collation in the operation. But when BINARY is used in the variable assignment, only the former purpose is carried over, since the BINARY qualifier is not part of the expression. When a prepared statement or a procedure or function is used, the type of the dynamic parameter and argument is derived based on the context, which is given by the column. Thus, the type and properties of the variable do not affect how the collation is derived. Instead, the variable is coerced into the character set and collation of the column. If you really want the comparison to use a binary character set, you can rewrite the statements as follows with a prepared statement: prepare stmt from "select * from t1 where name = cast(? as binary)"; and inside a procedure or function: select * from t1 where name = cast(var as binary);

Description: The same SQL statement will get different results when 1. executed directly 2. using session variable 3. using prepared statement 4. using procedure. Item has different Derivation, which further leads to different collations when comparing conditions. Is this behavior reasonable or a bug? How to repeat: Run the following SQL statement to reproduce the behavior here: set names utf8mb4; create table t1(name char(20)); insert into t1 values ('john', 'John'); 1. executed directly select * from t1 where name = _binary 'john'; --get 2 rows because of DERIVATION_COERCIBLE select * from t1 where name = binary 'john'; --get 1 row because of DERIVATION_IMPLICIT 2. using session variable set @var1 = _binary 'john'; set @var2 = binary 'john'; select * from t1 where name = @var1; --get 1 row, inconsistent select * from t1 where name = @var2; --get 1 row 3. using prepared statement set @var1 = _binary 'john'; set @var2 = binary 'john'; prepare stmt from "select * from t1 where name = ?"; execute stmt using @var1; --get 2 rows execute stmt using @var2; --get 2 rows, inconsistent 4. using procedure delimiter // create procedure test_proc(var char(20)) begin select * from t1 where name = var; end// delimiter ; call test_proc(_binary 'john'); --get 2 rows call test_proc(binary 'john'); --get 2 rows, inconsistent Suggested fix: Should Item_func_get_user_var, Item_func_set_user_var, Item_param, Item_splocal set their collation from the source Item ?