Skip to content

Commit

Permalink
[DBAL-299] Fix duplicate named parameters and ordering
Browse files Browse the repository at this point in the history
  • Loading branch information
asm89 committed Jul 7, 2012
1 parent ab57a01 commit 3f96f01
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 30 deletions.
44 changes: 19 additions & 25 deletions lib/Doctrine/DBAL/SQLParserUtils.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ static public function getPlaceholderPositions($statement, $isPositional = true)
} 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;
Expand Down Expand Up @@ -140,34 +140,28 @@ static public function expandListParameters($query, $params, $types)
$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];

if (!isset($arrayPositions[$needle])) {
foreach ($needlePos as $pos) {
$pos += $queryOffset;
$queryOffset -= ($paramLen - 1);
$paramsOrd[] = $value;
$typesOrd[] = $types[$needle];
$query = substr($query, 0, $pos) . '?' . substr($query, ($pos + $paramLen));
}
foreach ($paramPos as $pos => $paramName) {
$paramLen = strlen($paramName) + 1;
$value = $params[$paramName];

if (!isset($arrayPositions[$paramName])) {
$pos += $queryOffset;
$queryOffset -= ($paramLen - 1);
$paramsOrd[] = $value;
$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;
}

$pos += $queryOffset;
$queryOffset += (strlen($expandStr) - $paramLen);
$query = substr($query, 0, $pos) . $expandStr . substr($query, ($pos + $paramLen));
foreach ($value as $val) {
$paramsOrd[] = $val;
$typesOrd[] = $types[$paramName] - Connection::ARRAY_PARAM_OFFSET;
}

$pos += $queryOffset;
$queryOffset += (strlen($expandStr) - $paramLen);
$query = substr($query, 0, $pos) . $expandStr . substr($query, ($pos + $paramLen));
}
}

Expand Down
20 changes: 15 additions & 5 deletions tests/Doctrine/Tests/DBAL/SQLParserUtilsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ static public function dataGetPlaceholderPositions()
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
);
}

Expand Down Expand Up @@ -181,6 +181,16 @@ static public function dataExpandListParameters()
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)
),
);
}

Expand Down

0 comments on commit 3f96f01

Please sign in to comment.