Bug #68310 Unexpected behaviour with variables in where clause
Submitted: 7 Feb 2013 21:56 Modified: 8 Feb 2013 10:12
Reporter: alpha beta Email Updates:
Status: Not a Bug Impact on me:
None 
Category:MySQL Server: DML Severity:S2 (Serious)
Version:5.5.28 OS:Linux (ubuntu/debian 64bit)
Assigned to: CPU Architecture:Any
Tags: session variables, where clause

[7 Feb 2013 21:56] alpha beta
Description:
Let we have a table like that:

word,hash:

...
vicespeaker, fgeuw5890
vicepresident, asjfkl34
Vitzin, gfasw1p2
vicecounsil, q3i4pfas
viceanin, air9020
...

In next three cases I expect values of @a and @b

For beginning:
SET @a=0;
SET @b=0;

Case #1: -- -------------

SELECT *
FROM
`words`
WHERE
(`word` LIKE "vice%" AND @a:=@a+1) OR (`hash`='q3i4pfas' AND @b:=@b+1)

Case 2: -- ---------

SELECT *
FROM
`words`
WHERE
(`word`="vicecounsil" AND @a:=`word`) OR (`hash`='q3i4pfas' AND @b:=`hash`)

Result:
case 1: @a=5,@b=1; -- OK
case 2: @a="vicecounsil",@b="q3i4pfas" -- WTF?

Why do condition at the right of OR evaluates if left it true?

Next one case 3: make a mistake at left part

SELECT *
FROM
`words`
WHERE
(`word`="mistaken123" AND @a:=`word`) OR (`hash`='q3i4pfas' AND @b:=`hash`)

Result is satisfied: @a=0,@b="q3i4pfas".  -- OK

How to repeat:
Run next SQLs:
-- ---- definition

CREATE TABLE `words` (`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`word` VARCHAR(255) NOT NULL,
`hash` VARCHAR(255) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE=MyISAM;

INSERT INTO `words` (`word`,`hash`) VALUES
('vicespeaker', 'fgeuw5890'),
('vicepresident', 'asjfkl34'),
('Vitzin', 'gfasw1p2'),
('vicecounsil', 'q3i4pfas'),
('viceanin', 'air9020');

-- ----------- run next cases

SET @a=0;
SET @b=0;

SELECT *
FROM
`words`
WHERE
(`word` LIKE "vice%" AND @a:=@a+1) OR (`hash`='q3i4pfas' AND @b:=@b+1);

SELECT @a,@b;
-- ----------- see result @a,@b

SET @a=0;
SET @b=0;

SELECT *
FROM
`words`
WHERE
(`word`="vicecounsil" AND @a:=`word`) OR (`hash`='q3i4pfas' AND @b:=`hash`);

SELECT @a,@b;
-- ----------- see result @a,@b

SET @a=0;
SET @b=0;

SELECT *
FROM
`words`
WHERE
(`word`="mistaken123" AND @a:=`word`) OR (`hash`='q3i4pfas' AND @b:=`hash`);
-- ----------- see result @a,@b

Suggested fix:
I don't know. Make it be correct in case #2.
[8 Feb 2013 9:56] alpha beta
In case#1 @a=4, not @a=5. But it does not matter, my typo.
[8 Feb 2013 10:12] alpha beta
Yep, it is not bug! It is correct behavior when doing convertion string to integer.
The same as i do it explicit:
CAST((@a="some string") AS SIGNED) = 0

So right part around AND evaluates to 0 and ever get FALSE result
[8 Feb 2013 10:30] Hartmut Holzgraefe
> Why do condition at the right of OR evaluates if left it true?

Because the left term isn't true, @a is evaluated first, and is still 0, only then it gets the new value assigned ... same for @b on the right side

that query actually doesn't return any result rows, right?
[8 Feb 2013 10:32] Hartmut Holzgraefe
Simple test: 

mysql> select 1 and @a:='foo';
+-----------------+
| 1 and @a:='foo' |
+-----------------+
|               0 |
+-----------------+
1 row in set (0.00 sec)
[8 Feb 2013 11:15] Hartmut Holzgraefe
correcting myself, assignment comes before evaluation, but the real problem is that you are using the variables in a boolean context, so the assigned non-numeric string value gets cast to integer 0 and then to boolean false, making the full AND expression false on both sides:

mysql> select 1 and @a:='0';
+---------------+
| 1 and @a:='0' |
+---------------+
|             0 |
+---------------+
1 row in set (0.00 sec)

mysql> select 1 and @a:='1abc';
+---------------+
| 1 and @a:='1' |
+---------------+
|             1 |
+---------------+
1 row in set (0.00 sec)