I've included a DB-fiddle, and you can adjust the input parameter accordingly. This returns how I would expect it to, and differs from the results I am seeing in PDO.
I have the following minified table-view and query:
CREATE TABLE `tagged` {
`tag` SMALLINT(5) UNSIGNED NOT NULL
}
Table has an assortment of values, but you can use 1-10 for tags in the DB:
INSERT INTO tagged (tag) VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10)
query:
SELECT tagged.tag,
(@t := :tag),
@t AS temp_var,
(@t IS NULL OR FIND_IN_SET(tagged.tag, @t) > 0) AS is_match
FROM tagged
HAVING is_match = 1
LIMIT 150
This seems well and good when run in a client, command line, jdbc, etc. If I put in an input of ''
or NULL
, I get all results. Similarly an input of '1'
yields only tags of 1
, and an input of '1,4'
would retrieve all tags with 1 or 4.
The way the query restricts these results is via the is_match = 1
in the HAVING
clause. When run with PDO, the parameter seems to bind correctly but it completely ignores the condition in the clause:
Array
(
[0] => stdClass Object
(
[tag] => 3
[(@t := ?)] => 1,4
[temp_var] => 1,4
[is_match] => 0 ## should not have been returned
)
[1] => stdClass Object
(
[tag] => 4
[(@t := ?)] => 1,4
[temp_var] => 1,4
[is_match] => 1
)
PHP code used to run this (simplified):
$conn = /* pdo connection object */;
$stmt = $conn->prepare(DB::queryOf('test')); //uses our above query from a file
$stmt->bindValue(':tag', $args['tag'], PDO::PARAM_STR); //hardcode binding '1,4'
$stmt->execute(); //also tried plain #execute($args)
return $stmt->fetchAll(PDO::FETCH_OBJ);
Is there something I'm missing? I am binding a direct string parameter, and it seems the temporary variable is there and set correctly. Why is PDO returning the results for elements where is_match
= 0
?