Commit d9638d6d authored by Guilherme Blanco's avatar Guilherme Blanco

Merge pull request #64 from FabioBatSilva/named-params

Named Parameters As Positional
parents f91395b6 64803fff
......@@ -99,7 +99,7 @@ class SQLParserUtils
}
}
if (!$arrayPositions || count($params) != count($types)) {
if ((!$arrayPositions && $isPositional) || (count($params) != count($types))) {
return array($query, $params, $types);
}
......@@ -134,8 +134,44 @@ class SQLParserUtils
$paramOffset += ($len - 1); // Grows larger by number of parameters minus the replaced needle.
$queryOffset += (strlen($expandStr) - 1);
}
} else {
throw new DBALException("Array parameters are not supported for named placeholders.");
$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));
}
} 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));
}
}
}
$types = $typesOrd;
$params = $paramsOrd;
}
return array($query, $params, $types);
......
<?php
namespace Doctrine\Tests\DBAL\Functional\Ticket;
use Doctrine\DBAL\Connection;
use\PDO;
require_once __DIR__ . '/../../TestInit.php';
/**
* @group DDC-1372
*/
class NamedParametersTest extends \Doctrine\Tests\DbalFunctionalTestCase
{
public function ticketProvider()
{
return array(
array(
'SELECT * FROM ddc1372_foobar f WHERE f.foo = :foo AND f.bar IN (:bar)',
array('foo'=>1,'bar'=> array(1, 2, 3)),
array('foo'=>PDO::PARAM_INT,'bar'=> Connection::PARAM_INT_ARRAY,),
array(
array('id'=>1,'foo'=>1,'bar'=>1),
array('id'=>2,'foo'=>1,'bar'=>2),
array('id'=>3,'foo'=>1,'bar'=>3),
)
),
array(
'SELECT * FROM ddc1372_foobar f WHERE f.foo = :foo AND f.bar IN (:bar)',
array('foo'=>1,'bar'=> array(1, 2, 3)),
array('bar'=> Connection::PARAM_INT_ARRAY,'foo'=>PDO::PARAM_INT),
array(
array('id'=>1,'foo'=>1,'bar'=>1),
array('id'=>2,'foo'=>1,'bar'=>2),
array('id'=>3,'foo'=>1,'bar'=>3),
)
),
array(
'SELECT * FROM ddc1372_foobar f WHERE f.bar IN (:bar) AND f.foo = :foo',
array('foo'=>1,'bar'=> array(1, 2, 3)),
array('bar'=> Connection::PARAM_INT_ARRAY,'foo'=>PDO::PARAM_INT),
array(
array('id'=>1,'foo'=>1,'bar'=>1),
array('id'=>2,'foo'=>1,'bar'=>2),
array('id'=>3,'foo'=>1,'bar'=>3),
)
),
array(
'SELECT * FROM ddc1372_foobar f WHERE f.bar IN (:bar) AND f.foo = :foo',
array('foo'=>1,'bar'=> array('1', '2', '3')),
array('bar'=> Connection::PARAM_STR_ARRAY,'foo'=>PDO::PARAM_INT),
array(
array('id'=>1,'foo'=>1,'bar'=>1),
array('id'=>2,'foo'=>1,'bar'=>2),
array('id'=>3,'foo'=>1,'bar'=>3),
)
),
array(
'SELECT * FROM ddc1372_foobar f WHERE f.bar IN (:bar) AND f.foo IN (:foo)',
array('foo'=>array('1'),'bar'=> array(1, 2, 3,4)),
array('bar'=> Connection::PARAM_STR_ARRAY,'foo'=>Connection::PARAM_INT_ARRAY),
array(
array('id'=>1,'foo'=>1,'bar'=>1),
array('id'=>2,'foo'=>1,'bar'=>2),
array('id'=>3,'foo'=>1,'bar'=>3),
array('id'=>4,'foo'=>1,'bar'=>4),
)
),
array(
'SELECT * FROM ddc1372_foobar f WHERE f.bar IN (:bar) AND f.foo IN (:foo)',
array('foo'=>1,'bar'=> 2),
array('bar'=>PDO::PARAM_INT,'foo'=>PDO::PARAM_INT),
array(
array('id'=>2,'foo'=>1,'bar'=>2),
)
),
array(
'SELECT * FROM ddc1372_foobar f WHERE f.bar = :arg AND f.foo <> :arg',
array('arg'=>'1'),
array('arg'=>PDO::PARAM_STR),
array(
array('id'=>5,'foo'=>2,'bar'=>1),
)
),
array(
'SELECT * FROM ddc1372_foobar f WHERE f.bar NOT IN (:arg) AND f.foo IN (:arg)',
array('arg'=>array(1, 2)),
array('arg'=>Connection::PARAM_INT_ARRAY),
array(
array('id'=>3,'foo'=>1,'bar'=>3),
array('id'=>4,'foo'=>1,'bar'=>4),
)
),
);
}
public function setUp()
{
parent::setUp();
if (!$this->_conn->getSchemaManager()->tablesExist("ddc1372_foobar")) {
try {
$table = new \Doctrine\DBAL\Schema\Table("ddc1372_foobar");
$table->addColumn('id', 'integer');
$table->addColumn('foo','string');
$table->addColumn('bar','string');
$sm = $this->_conn->getSchemaManager();
$sm->createTable($table);
$this->_conn->insert('ddc1372_foobar', array(
'id' => 1, 'foo' => 1, 'bar' => 1
));
$this->_conn->insert('ddc1372_foobar', array(
'id' => 2, 'foo' => 1, 'bar' => 2
));
$this->_conn->insert('ddc1372_foobar', array(
'id' => 3, 'foo' => 1, 'bar' => 3
));
$this->_conn->insert('ddc1372_foobar', array(
'id' => 4, 'foo' => 1, 'bar' => 4
));
$this->_conn->insert('ddc1372_foobar', array(
'id' => 5, 'foo' => 2, 'bar' => 1
));
$this->_conn->insert('ddc1372_foobar', array(
'id' => 6, 'foo' => 2, 'bar' => 2
));
} catch(\Exception $e) {
$this->fail($e->getMessage());
}
}
}
/**
* @dataProvider ticketProvider
* @param string $query
* @param array $params
* @param array $types
* @param array $expected
*/
public function testTicket($query,$params,$types,$expected)
{
$stmt = $this->_conn->executeQuery($query, $params, $types);
$result = $stmt->fetchAll(\PDO::FETCH_ASSOC);
$this->assertEquals($result, $expected);
}
}
\ No newline at end of file
......@@ -9,6 +9,7 @@ require_once __DIR__ . '/../TestInit.php';
/**
* @group DBAL-78
* @group DDC-1372
*/
class SQLParserUtilsTest extends \Doctrine\Tests\DbalTestCase
{
......@@ -96,6 +97,89 @@ class SQLParserUtilsTest extends \Doctrine\Tests\DbalTestCase
array(1, 2, 3, 4, 5),
array(\PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT)
),
// Named parameters : Very simple with param int
array(
"SELECT * FROM Foo WHERE foo = :foo",
array('foo'=>1),
array('foo'=>\PDO::PARAM_INT),
'SELECT * FROM Foo WHERE foo = ?',
array(1),
array(\PDO::PARAM_INT)
),
// Named parameters : Very simple with param int and string
array(
"SELECT * FROM Foo WHERE foo = :foo AND bar = :bar",
array('bar'=>'Some String','foo'=>1),
array('foo'=>\PDO::PARAM_INT,'bar'=>\PDO::PARAM_STR),
'SELECT * FROM Foo WHERE foo = ? AND bar = ?',
array(1,'Some String'),
array(\PDO::PARAM_INT, \PDO::PARAM_STR)
),
// Named parameters : Very simple with one needle
array(
"SELECT * FROM Foo WHERE foo IN (:foo)",
array('foo'=>array(1, 2, 3)),
array('foo'=>Connection::PARAM_INT_ARRAY),
'SELECT * FROM Foo WHERE foo IN (?, ?, ?)',
array(1, 2, 3),
array(\PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT)
),
// Named parameters: One non-list before d one after list-needle
array(
"SELECT * FROM Foo WHERE foo = :foo AND bar IN (:bar)",
array('foo'=>"string", 'bar'=>array(1, 2, 3)),
array('foo'=>\PDO::PARAM_STR, 'bar'=>Connection::PARAM_INT_ARRAY),
'SELECT * FROM Foo WHERE foo = ? AND bar IN (?, ?, ?)',
array("string", 1, 2, 3),
array(\PDO::PARAM_STR, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT)
),
// Named parameters: One non-list after list-needle
array(
"SELECT * FROM Foo WHERE bar IN (:bar) AND baz = :baz",
array('bar'=>array(1, 2, 3), 'baz'=>"foo"),
array('bar'=>Connection::PARAM_INT_ARRAY, 'baz'=>\PDO::PARAM_STR),
'SELECT * FROM Foo WHERE bar IN (?, ?, ?) AND baz = ?',
array(1, 2, 3, "foo"),
array(\PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_STR)
),
// Named parameters: One non-list before and one after list-needle
array(
"SELECT * FROM Foo WHERE foo = :foo AND bar IN (:bar) AND baz = :baz",
array('bar'=>array(1, 2, 3),'foo'=>1, 'baz'=>4),
array('bar'=>Connection::PARAM_INT_ARRAY, 'foo'=>\PDO::PARAM_INT, 'baz'=>\PDO::PARAM_INT),
'SELECT * FROM Foo WHERE foo = ? AND bar IN (?, ?, ?) AND baz = ?',
array(1, 1, 2, 3, 4),
array(\PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT)
),
// Named parameters: Two lists
array(
"SELECT * FROM Foo WHERE foo IN (:a, :b)",
array('b'=>array(4, 5),'a'=>array(1, 2, 3)),
array('a'=>Connection::PARAM_INT_ARRAY, 'b'=>Connection::PARAM_INT_ARRAY),
'SELECT * FROM Foo WHERE foo IN (?, ?, ?, ?, ?)',
array(1, 2, 3, 4, 5),
array(\PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT)
),
// Named parameters : With the same name arg type string
array(
"SELECT * FROM Foo WHERE foo <> :arg AND bar = :arg",
array('arg'=>"Some String"),
array('arg'=>\PDO::PARAM_STR),
'SELECT * FROM Foo WHERE foo <> ? AND bar = ?',
array("Some String","Some String"),
array(\PDO::PARAM_STR,\PDO::PARAM_STR,)
),
// Named parameters : With the same name arg
array(
"SELECT * FROM Foo WHERE foo IN (:arg) AND NOT bar IN (:arg)",
array('arg'=>array(1, 2, 3)),
array('arg'=>Connection::PARAM_INT_ARRAY),
'SELECT * FROM Foo WHERE foo IN (?, ?, ?) AND NOT bar IN (?, ?, ?)',
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)
),
);
}
......
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