Commit 331fd04c authored by Alexander's avatar Alexander Committed by Benjamin Eberlei

[DBAL-299] Fix duplicate named parameters and ordering

parent f1559554
......@@ -61,10 +61,10 @@ class SQLParserUtils
} else {
$name = "";
// TODO: Something faster/better to match this than regex?
for ($j = $i; ($j < $stmtLen && preg_match('(([:a-zA-Z0-9_]{1}))', $statement[$j])); $j++) {
for ($j = $i + 1; ($j < $stmtLen && preg_match('(([a-zA-Z0-9_]{1}))', $statement[$j])); $j++) {
$name .= $statement[$j];
}
$paramMap[$name][] = $i; // named parameters can be duplicated!
$paramMap[$i] = $name; // named parameters can be duplicated!
$i = $j;
}
++$count;
......@@ -139,28 +139,23 @@ class SQLParserUtils
$queryOffset= 0;
$typesOrd = array();
$paramsOrd = array();
foreach ($paramPos as $needle => $needlePos) {
$paramLen = strlen($needle);
$token = substr($needle,0,1);
$needle = substr($needle,1);
$value = $params[$needle];
foreach ($paramPos as $pos => $paramName) {
$paramLen = strlen($paramName) + 1;
$value = $params[$paramName];
if (!isset($arrayPositions[$needle])) {
foreach ($needlePos as $pos) {
if (!isset($arrayPositions[$paramName])) {
$pos += $queryOffset;
$queryOffset -= ($paramLen - 1);
$paramsOrd[] = $value;
$typesOrd[] = $types[$needle];
$typesOrd[] = $types[$paramName];
$query = substr($query, 0, $pos) . '?' . substr($query, ($pos + $paramLen));
}
} else {
$len = count($value);
$expandStr = implode(", ", array_fill(0, $len, "?"));
foreach ($needlePos as $pos) {
foreach ($value as $val) {
$paramsOrd[] = $val;
$typesOrd[] = $types[$needle] - Connection::ARRAY_PARAM_OFFSET;
$typesOrd[] = $types[$paramName] - Connection::ARRAY_PARAM_OFFSET;
}
$pos += $queryOffset;
......@@ -168,7 +163,6 @@ class SQLParserUtils
$query = substr($query, 0, $pos) . $expandStr . substr($query, ($pos + $paramLen));
}
}
}
$types = $typesOrd;
$params = $paramsOrd;
......
......@@ -30,11 +30,11 @@ class SQLParserUtilsTest extends \Doctrine\Tests\DbalTestCase
array("SELECT '?' FROM foo WHERE bar = ?", true, array(32)),
// named
array('SELECT :foo FROM :bar', false, array(':foo' => array(7), ':bar' => array(17))),
array('SELECT * FROM Foo WHERE bar IN (:name1, :name2)', false, array(':name1' => array(32), ':name2' => array(40))),
array('SELECT ":foo" FROM Foo WHERE bar IN (:name1, :name2)', false, array(':name1' => array(37), ':name2' => array(45))),
array("SELECT ':foo' FROM Foo WHERE bar IN (:name1, :name2)", false, array(':name1' => array(37), ':name2' => array(45))),
array('SELECT :foo_id', false, array(':foo_id' => array(7))), // Ticket DBAL-231
array('SELECT :foo FROM :bar', false, array(7 => 'foo', 17 => 'bar')),
array('SELECT * FROM Foo WHERE bar IN (:name1, :name2)', false, array(32 => 'name1', 40 => 'name2')),
array('SELECT ":foo" FROM Foo WHERE bar IN (:name1, :name2)', false, array(37 => 'name1', 45 => 'name2')),
array("SELECT ':foo' FROM Foo WHERE bar IN (:name1, :name2)", false, array(37 => 'name1', 45 => 'name2')),
array('SELECT :foo_id', false, array(7 => 'foo_id')), // Ticket DBAL-231
);
}
......@@ -181,6 +181,16 @@ class SQLParserUtilsTest extends \Doctrine\Tests\DbalTestCase
array(1, 2, 3, 1, 2, 3),
array(\PDO::PARAM_INT,\PDO::PARAM_INT, \PDO::PARAM_INT,\PDO::PARAM_INT,\PDO::PARAM_INT, \PDO::PARAM_INT)
),
// Named parameters : Same name, other name in between DBAL-299
array(
"SELECT * FROM Foo WHERE (:foo = 2) AND (:bar = 3) AND (:foo = 2)",
array('foo'=>2,'bar'=>3),
array('foo'=>\PDO::PARAM_INT,'bar'=>\PDO::PARAM_INT),
'SELECT * FROM Foo WHERE (? = 2) AND (? = 3) AND (? = 2)',
array(2, 3, 2),
array(\PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT)
),
);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment