diff --git a/UPGRADE_TO_2_3 b/UPGRADE_TO_2_3 index 7f860be93..28e734a84 100644 --- a/UPGRADE_TO_2_3 +++ b/UPGRADE_TO_2_3 @@ -7,3 +7,21 @@ and strip a trailing "s" character if there is one. # Merge copies non persisted properties too When merging an entity in UoW not only mapped properties are copied, but also others. + +# Query, QueryBuilder and NativeQuery parameters *BC break* + +From now on, parameters in queries is an ArrayCollection instead of a simple array. +This affects heavily the usage of setParameters(), because it will not append anymore +parameters to query, but will actually override the already defined ones. +Whenever you are retrieving a parameter (ie. $query->getParameter(1)), you will +receive an instance of Query\Parameter, which contains the methods "getName", +"getValue" and "getType". Parameters are also only converted to when necessary, and +not when they are set. + +Also, related functions were affected: + +* execute($parameters, $hydrationMode) the argument $parameters can be either an key=>value array or an ArrayCollection instance +* iterate($parameters, $hydrationMode) the argument $parameters can be either an key=>value array or an ArrayCollection instance +* setParameters($parameters) the argument $parameters can be either an key=>value array or an ArrayCollection instance +* getParameters() now returns ArrayCollection instead of array +* getParameter($key) now returns Parameter instance instead of parameter value \ No newline at end of file diff --git a/lib/Doctrine/ORM/AbstractQuery.php b/lib/Doctrine/ORM/AbstractQuery.php index 77ff57a08..d3e661071 100644 --- a/lib/Doctrine/ORM/AbstractQuery.php +++ b/lib/Doctrine/ORM/AbstractQuery.php @@ -19,15 +19,17 @@ namespace Doctrine\ORM; -use Doctrine\DBAL\Types\Type, - Doctrine\DBAL\Cache\QueryCacheProfile, - Doctrine\ORM\Query\QueryException, - Doctrine\Common\Util\ClassUtils; +use Doctrine\Common\Util\ClassUtils; +use Doctrine\Common\Collections\ArrayCollection; + +use Doctrine\DBAL\Types\Type; +use Doctrine\DBAL\Cache\QueryCacheProfile; + +use Doctrine\ORM\Query\QueryException; /** * Base contract for ORM queries. Base class for Query and NativeQuery. * - * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei @@ -62,14 +64,9 @@ abstract class AbstractQuery const HYDRATE_SIMPLEOBJECT = 5; /** - * @var array The parameter map of this query. + * @var \Doctrine\Common\Collections\ArrayCollection The parameter map of this query. */ - protected $_params = array(); - - /** - * @var array The parameter type map of this query. - */ - protected $_paramTypes = array(); + protected $parameters; /** * @var ResultSetMapping The user-specified ResultSetMapping to use. @@ -114,8 +111,18 @@ abstract class AbstractQuery public function __construct(EntityManager $em) { $this->_em = $em; + $this->parameters = new ArrayCollection(); } + /** + * Gets the SQL query that corresponds to this query object. + * The returned SQL syntax depends on the connection driver that is used + * by this query object at the time of this method call. + * + * @return string SQL query + */ + abstract public function getSQL(); + /** * Retrieves the associated EntityManager of this Query instance. * @@ -135,8 +142,8 @@ abstract class AbstractQuery */ public function free() { - $this->_params = array(); - $this->_paramTypes = array(); + $this->parameters = new ArrayCollection(); + $this->_hints = array(); } @@ -147,57 +154,55 @@ abstract class AbstractQuery */ public function getParameters() { - return $this->_params; - } - - /** - * Get all defined parameter types. - * - * @return array The defined query parameter types. - */ - public function getParameterTypes() - { - return $this->_paramTypes; + return $this->parameters; } /** * Gets a query parameter. * * @param mixed $key The key (index or name) of the bound parameter. + * * @return mixed The value of the bound parameter. */ public function getParameter($key) { - if (isset($this->_params[$key])) { - return $this->_params[$key]; - } + $filteredParameters = $this->parameters->filter( + function ($parameter) use ($key) + { + // Must not be identical because of string to integer conversion + return ($key == $parameter->getName()); + } + ); - return null; + return count($filteredParameters) ? $filteredParameters->first() : null; } /** - * Gets a query parameter type. + * Sets a collection of query parameters. * - * @param mixed $key The key (index or name) of the bound parameter. - * @return mixed The parameter type of the bound parameter. + * @param \Doctrine\Common\Collections\ArrayCollection|array $parameters + * + * @return \Doctrine\ORM\AbstractQuery This query instance. */ - public function getParameterType($key) + public function setParameters($parameters) { - if (isset($this->_paramTypes[$key])) { - return $this->_paramTypes[$key]; + // BC compatibility with 2.3- + if (is_array($parameters)) { + $parameterCollection = new ArrayCollection(); + + foreach ($parameters as $key => $value) { + $parameter = new Query\Parameter($key, $value); + + $parameterCollection->add($parameter); + } + + $parameters = $parameterCollection; } - return null; - } + $this->parameters = $parameters; - /** - * Gets the SQL query that corresponds to this query object. - * The returned SQL syntax depends on the connection driver that is used - * by this query object at the time of this method call. - * - * @return string SQL query - */ - abstract public function getSQL(); + return $this; + } /** * Sets a query parameter. @@ -207,19 +212,29 @@ abstract class AbstractQuery * @param string $type The parameter type. If specified, the given value will be run through * the type conversion of this type. This is usually not needed for * strings and numeric types. + * * @return \Doctrine\ORM\AbstractQuery This query instance. */ public function setParameter($key, $value, $type = null) { - $key = trim($key, ':'); - $value = $this->processParameterValue($value); + $filteredParameters = $this->parameters->filter( + function ($parameter) use ($key) + { + // Must not be identical because of string to integer conversion + return ($key == $parameter->getName()); + } + ); - if ($type === null) { - $type = Query\ParameterTypeInferer::inferType($value); + if (count($filteredParameters)) { + $parameter = $filteredParameters->first(); + $parameter->setValue($value, $type); + + return $this; } - $this->_paramTypes[$key] = $type; - $this->_params[$key] = $value; + $parameter = new Query\Parameter($key, $value, $type); + + $this->parameters->add($parameter); return $this; } @@ -230,7 +245,7 @@ abstract class AbstractQuery * @param mixed $value * @return array */ - private function processParameterValue($value) + public function processParameterValue($value) { switch (true) { case is_array($value): @@ -249,7 +264,7 @@ abstract class AbstractQuery } } - protected function convertObjectParameterToScalarValue($value) + private function convertObjectParameterToScalarValue($value) { $class = $this->_em->getClassMetadata(get_class($value)); @@ -275,22 +290,6 @@ abstract class AbstractQuery return $value; } - /** - * Sets a collection of query parameters. - * - * @param array $params - * @param array $types - * @return \Doctrine\ORM\AbstractQuery This query instance. - */ - public function setParameters(array $params, array $types = array()) - { - foreach ($params as $key => $value) { - $this->setParameter($key, $value, isset($types[$key]) ? $types[$key] : null); - } - - return $this; - } - /** * Sets the ResultSetMapping that should be used for hydration. * @@ -530,37 +529,37 @@ abstract class AbstractQuery /** * Gets the list of results for the query. * - * Alias for execute(array(), $hydrationMode = HYDRATE_OBJECT). + * Alias for execute(null, $hydrationMode = HYDRATE_OBJECT). * * @return array */ public function getResult($hydrationMode = self::HYDRATE_OBJECT) { - return $this->execute(array(), $hydrationMode); + return $this->execute(null, $hydrationMode); } /** * Gets the array of results for the query. * - * Alias for execute(array(), HYDRATE_ARRAY). + * Alias for execute(null, HYDRATE_ARRAY). * * @return array */ public function getArrayResult() { - return $this->execute(array(), self::HYDRATE_ARRAY); + return $this->execute(null, self::HYDRATE_ARRAY); } /** * Gets the scalar results for the query. * - * Alias for execute(array(), HYDRATE_SCALAR). + * Alias for execute(null, HYDRATE_SCALAR). * * @return array */ public function getScalarResult() { - return $this->execute(array(), self::HYDRATE_SCALAR); + return $this->execute(null, self::HYDRATE_SCALAR); } /** @@ -572,7 +571,7 @@ abstract class AbstractQuery */ public function getOneOrNullResult($hydrationMode = null) { - $result = $this->execute(array(), $hydrationMode); + $result = $this->execute(null, $hydrationMode); if ($this->_hydrationMode !== self::HYDRATE_SINGLE_SCALAR && ! $result) { return null; @@ -604,7 +603,7 @@ abstract class AbstractQuery */ public function getSingleResult($hydrationMode = null) { - $result = $this->execute(array(), $hydrationMode); + $result = $this->execute(null, $hydrationMode); if ($this->_hydrationMode !== self::HYDRATE_SINGLE_SCALAR && ! $result) { throw new NoResultException; @@ -673,18 +672,18 @@ abstract class AbstractQuery * Executes the query and returns an IterableResult that can be used to incrementally * iterate over the result. * - * @param array $params The query parameters. + * @param \Doctrine\Common\Collections\ArrayCollection|array $parameters The query parameters. * @param integer $hydrationMode The hydration mode to use. * @return \Doctrine\ORM\Internal\Hydration\IterableResult */ - public function iterate(array $params = array(), $hydrationMode = null) + public function iterate($parameters = null, $hydrationMode = null) { if ($hydrationMode !== null) { $this->setHydrationMode($hydrationMode); } - if ($params) { - $this->setParameters($params); + if ( ! empty($parameters)) { + $this->setParameters($parameters); } $stmt = $this->_doExecute(); @@ -697,18 +696,18 @@ abstract class AbstractQuery /** * Executes the query. * - * @param array $params Any additional query parameters. + * @param \Doctrine\Common\Collections\ArrayCollection|array $parameters Query parameters. * @param integer $hydrationMode Processing mode to be used during the hydration process. * @return mixed */ - public function execute($params = array(), $hydrationMode = null) + public function execute($parameters = null, $hydrationMode = null) { if ($hydrationMode !== null) { $this->setHydrationMode($hydrationMode); } - if ($params) { - $this->setParameters($params); + if ( ! empty($parameters)) { + $this->setParameters($parameters); } $setCacheEntry = function() {}; @@ -730,6 +729,7 @@ abstract class AbstractQuery $setCacheEntry = function($data) use ($cache, $result, $cacheKey, $realCacheKey, $queryCacheProfile) { $result[$realCacheKey] = $data; + $cache->save($cacheKey, $result, $queryCacheProfile->getLifetime()); }; } @@ -760,19 +760,20 @@ abstract class AbstractQuery */ protected function getHydrationCacheId() { - $params = $this->getParameters(); + $parameters = array(); - foreach ($params AS $key => $value) { - $params[$key] = $this->processParameterValue($value); + foreach ($this->getParameters()->getIterator() as $parameter) { + $parameters[$parameter->getName()] = $this->processParameterValue($parameter->getValue()); } $sql = $this->getSQL(); $queryCacheProfile = $this->getHydrationCacheProfile(); $hints = $this->getHints(); $hints['hydrationMode'] = $this->getHydrationMode(); + ksort($hints); - return $queryCacheProfile->generateCacheKeys($sql, $params, $hints); + return $queryCacheProfile->generateCacheKeys($sql, $parameters, $hints); } /** @@ -817,8 +818,8 @@ abstract class AbstractQuery */ public function __clone() { - $this->_params = array(); - $this->_paramTypes = array(); + $this->parameters = new ArrayCollection(); + $this->_hints = array(); } } diff --git a/lib/Doctrine/ORM/NativeQuery.php b/lib/Doctrine/ORM/NativeQuery.php index 5e76cc520..72232f241 100644 --- a/lib/Doctrine/ORM/NativeQuery.php +++ b/lib/Doctrine/ORM/NativeQuery.php @@ -58,19 +58,30 @@ final class NativeQuery extends AbstractQuery */ protected function _doExecute() { - $params = $this->_params; - $types = $this->_paramTypes; + $parameters = array(); + $types = array(); - if ($params && is_int(key($params))) { - ksort($params); + foreach ($this->getParameters()->getIterator() as $parameter) { + $name = $parameter->getName(); + $value = $this->processParameterValue($parameter->getValue()); + $type = ($parameter->getValue() === $value) + ? $parameter->getType() + : Query\ParameterTypeInferer::inferType($value); + + $parameters[$name] = $value; + $types[$name] = $type; + } + + if ($parameters && is_int(key($parameters))) { + ksort($parameters); ksort($types); - $params = array_values($params); - $types = array_values($types); + $parameters = array_values($parameters); + $types = array_values($types); } return $this->_em->getConnection()->executeQuery( - $this->_sql, $params, $types, $this->_queryCacheProfile + $this->_sql, $parameters, $types, $this->_queryCacheProfile ); } } diff --git a/lib/Doctrine/ORM/Query.php b/lib/Doctrine/ORM/Query.php index fba4d7579..5ff7f96eb 100644 --- a/lib/Doctrine/ORM/Query.php +++ b/lib/Doctrine/ORM/Query.php @@ -19,10 +19,13 @@ namespace Doctrine\ORM; -use Doctrine\DBAL\LockMode, - Doctrine\ORM\Query\Parser, - Doctrine\ORM\Query\ParserResult, - Doctrine\ORM\Query\QueryException; +use Doctrine\Common\Collections\ArrayCollection; + +use Doctrine\DBAL\LockMode; + +use Doctrine\ORM\Query\Parser; +use Doctrine\ORM\Query\ParserResult; +use Doctrine\ORM\Query\QueryException; /** * A Query object represents a DQL query. @@ -248,7 +251,7 @@ final class Query extends AbstractQuery // Prepare parameters $paramMappings = $this->_parserResult->getParameterMappings(); - if (count($paramMappings) != count($this->_params)) { + if (count($paramMappings) != count($this->parameters)) { throw QueryException::invalidParameterNumber(); } @@ -269,17 +272,23 @@ final class Query extends AbstractQuery */ private function processParameterMappings($paramMappings) { - $sqlParams = $types = array(); + $sqlParams = array(); + $types = array(); + + foreach ($this->parameters->getIterator() as $parameter) { + $key = $parameter->getName(); - foreach ($this->_params as $key => $value) { if ( ! isset($paramMappings[$key])) { throw QueryException::unknownParameter($key); } - if (isset($this->_paramTypes[$key])) { - foreach ($paramMappings[$key] as $position) { - $types[$position] = $this->_paramTypes[$key]; - } + $value = $this->processParameterValue($parameter->getValue()); + $type = ($parameter->getValue() === $value) + ? $parameter->getType() + : Query\ParameterTypeInferer::inferType($value); + + foreach ($paramMappings[$key] as $position) { + $types[$position] = $type; } $sqlPositions = $paramMappings[$key]; @@ -517,15 +526,15 @@ final class Query extends AbstractQuery * Executes the query and returns an IterableResult that can be used to incrementally * iterated over the result. * - * @param array $params The query parameters. + * @param \Doctrine\Common\Collections\ArrayCollection|array $parameters The query parameters. * @param integer $hydrationMode The hydration mode to use. * @return \Doctrine\ORM\Internal\Hydration\IterableResult */ - public function iterate(array $params = array(), $hydrationMode = self::HYDRATE_OBJECT) + public function iterate($parameters = null, $hydrationMode = self::HYDRATE_OBJECT) { $this->setHint(self::HINT_INTERNAL_ITERATION, true); - return parent::iterate($params, $hydrationMode); + return parent::iterate($parameters, $hydrationMode); } /** diff --git a/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php b/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php index 2978d8302..575e6dfb8 100644 --- a/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php +++ b/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php @@ -19,9 +19,11 @@ namespace Doctrine\ORM\Query\Exec; -use Doctrine\DBAL\Connection, - Doctrine\DBAL\Types\Type, - Doctrine\ORM\Query\AST; +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Types\Type; + +use Doctrine\ORM\Query\ParameterTypeInferer; +use Doctrine\ORM\Query\AST; /** * Executes the SQL statements for bulk DQL UPDATE statements on classes in @@ -105,9 +107,16 @@ class MultiTableUpdateExecutor extends AbstractSqlExecutor //FIXME: parameters can be more deeply nested. traverse the tree. //FIXME (URGENT): With query cache the parameter is out of date. Move to execute() stage. if ($newValue instanceof AST\InputParameter) { - $paramKey = $newValue->name; - $this->_sqlParameters[$i]['parameters'][] = $sqlWalker->getQuery()->getParameter($paramKey); - $this->_sqlParameters[$i]['types'][] = $sqlWalker->getQuery()->getParameterType($paramKey); + $parameterName = $newValue->name; + $parameter = $sqlWalker->getQuery()->getParameter($parameterName); + + $value = $sqlWalker->getQuery()->processParameterValue($parameter->getValue()); + $type = ($parameter->getValue() === $value) + ? $parameter->getType() + : ParameterTypeInferer::inferType($value); + + $this->_sqlParameters[$i]['parameters'][] = $value; + $this->_sqlParameters[$i]['types'][] = $type; ++$this->_numParametersInUpdateClause; } diff --git a/lib/Doctrine/ORM/Query/Parameter.php b/lib/Doctrine/ORM/Query/Parameter.php new file mode 100644 index 000000000..659386665 --- /dev/null +++ b/lib/Doctrine/ORM/Query/Parameter.php @@ -0,0 +1,101 @@ +. + */ + +namespace Doctrine\ORM\Query; + +/** + * Define a Query Parameter + * + * @link www.doctrine-project.org + * @since 2.3 + * @author Guilherme Blanco + */ +class Parameter +{ + /** + * @var string Parameter name + */ + private $name; + + /** + * @var mixed Parameter value + */ + private $value; + + /** + * @var mixed Parameter type + */ + private $type; + + /** + * Constructor. + * + * @param string $name Parameter name + * @param mixed $value Parameter value + * @param mixed $type Parameter type + */ + public function __construct($name, $value, $type = null) + { + $this->name = trim($name, ':'); + + $this->setValue($value); + } + + /** + * Retrieve the Parameter name. + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Retrieve the Parameter value. + * + * @return mixed + */ + public function getValue() + { + return $this->value; + } + + /** + * Retrieve the Parameter type. + * + * @return mixed + */ + public function getType() + { + return $this->type; + } + + /** + * Define the Parameter value. + * + * @param mixed $value Parameter value + * @param mixed $type Parameter type + */ + public function setValue($value, $type = null) + { + $this->value = $value; + $this->type = $type ?: ParameterTypeInferer::inferType($value); + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php index 3b524da69..2bef079ae 100644 --- a/lib/Doctrine/ORM/Query/SqlWalker.php +++ b/lib/Doctrine/ORM/Query/SqlWalker.php @@ -1687,7 +1687,6 @@ class SqlWalker implements TreeWalker // InputParameter case ($entityExpr instanceof AST\InputParameter): $dqlParamKey = $entityExpr->name; - $entity = $this->_query->getParameter($dqlParamKey); $entitySql = '?'; break; @@ -1853,8 +1852,7 @@ class SqlWalker implements TreeWalker $dqlAlias = $instanceOfExpr->identificationVariable; $discrClass = $class = $this->_queryComponents[$dqlAlias]['metadata']; - $fieldName = null; - + if ($class->discriminatorColumn) { $discrClass = $this->_em->getClassMetadata($class->rootEntityName); } @@ -1871,7 +1869,8 @@ class SqlWalker implements TreeWalker if ($parameter instanceof AST\InputParameter) { // We need to modify the parameter value to be its correspondent mapped value $dqlParamKey = $parameter->name; - $paramValue = $this->_query->getParameter($dqlParamKey); + $dqlParam = $this->_query->getParameter($dqlParamKey); + $paramValue = $this->_query->processParameterValue($dqlParam->getValue()); if ( ! ($paramValue instanceof \Doctrine\ORM\Mapping\ClassMetadata)) { throw QueryException::invalidParameterType('ClassMetadata', get_class($paramValue)); diff --git a/lib/Doctrine/ORM/QueryBuilder.php b/lib/Doctrine/ORM/QueryBuilder.php index 436805f15..0db6e297e 100644 --- a/lib/Doctrine/ORM/QueryBuilder.php +++ b/lib/Doctrine/ORM/QueryBuilder.php @@ -19,6 +19,8 @@ namespace Doctrine\ORM; +use Doctrine\Common\Collections\ArrayCollection; + use Doctrine\ORM\Query\Expr; /** @@ -77,14 +79,9 @@ class QueryBuilder private $_dql; /** - * @var array The query parameters. + * @var \Doctrine\Common\Collections\ArrayCollection The query parameters. */ - private $_params = array(); - - /** - * @var array The parameter type map of this query. - */ - private $_paramTypes = array(); + private $parameters = array(); /** * @var integer The index of the first result to retrieve. @@ -109,6 +106,7 @@ class QueryBuilder public function __construct(EntityManager $em) { $this->_em = $em; + $this->parameters = new ArrayCollection(); } /** @@ -218,8 +216,10 @@ class QueryBuilder */ public function getQuery() { + $parameters = clone $this->parameters; + return $this->_em->createQuery($this->getDQL()) - ->setParameters($this->_params, $this->_paramTypes) + ->setParameters($parameters) ->setFirstResult($this->_firstResult) ->setMaxResults($this->_maxResults); } @@ -355,10 +355,7 @@ class QueryBuilder */ public function setParameter($key, $value, $type = null) { - $key = trim($key, ':'); - - $this->_paramTypes[$key] = $type ?: Query\ParameterTypeInferer::inferType($value); - $this->_params[$key] = $value; + $this->parameters->add(new Query\Parameter($key, $value, $type)); return $this; } @@ -371,20 +368,18 @@ class QueryBuilder * ->select('u') * ->from('User', 'u') * ->where('u.id = :user_id1 OR u.id = :user_id2') - * ->setParameters(array( - * 'user_id1' => 1, - * 'user_id2' => 2 - )); + * ->setParameters(new ArrayCollection(array( + * new Parameter('user_id1', 1), + * new Parameter('user_id2', 2) + ))); * * - * @param array $params The query parameters to set. + * @param \Doctrine\Common\Collections\ArrayCollections $params The query parameters to set. * @return QueryBuilder This QueryBuilder instance. */ - public function setParameters(array $params, array $types = array()) + public function setParameters(ArrayCollection $parameters) { - foreach ($params as $key => $value) { - $this->setParameter($key, $value, isset($types[$key]) ? $types[$key] : null); - } + $this->parameters = $parameters; return $this; } @@ -396,18 +391,25 @@ class QueryBuilder */ public function getParameters() { - return $this->_params; + return $this->parameters; } /** * Gets a (previously set) query parameter of the query being constructed. * * @param mixed $key The key (index or name) of the bound parameter. + * * @return mixed The value of the bound parameter. */ public function getParameter($key) { - return isset($this->_params[$key]) ? $this->_params[$key] : null; + foreach ($this->parameters->getIterator() as $parameter) { + if ($parameter->getName() === $key) { + return $parameter; + } + } + + return null; } /** diff --git a/tests/Doctrine/Tests/ORM/Functional/HydrationCacheTest.php b/tests/Doctrine/Tests/ORM/Functional/HydrationCacheTest.php index 897421164..821c5dff4 100644 --- a/tests/Doctrine/Tests/ORM/Functional/HydrationCacheTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/HydrationCacheTest.php @@ -14,6 +14,7 @@ class HydrationCacheTest extends OrmFunctionalTestCase public function setUp() { $this->useModelSet('cms'); + parent::setUp(); $user = new CmsUser; @@ -72,14 +73,17 @@ class HydrationCacheTest extends OrmFunctionalTestCase $user = new CmsUser(); $user->id = 1; - $dql = "SELECT u FROM Doctrine\Tests\Models\Cms\CmsUser u WHERE u.id = ?1"; + $dql = "SELECT u FROM Doctrine\Tests\Models\Cms\CmsUser u WHERE u.id = ?1"; $query = $this->_em->createQuery($dql) - ->setParameter(1, $user) - ->setHydrationCacheProfile(new QueryCacheProfile(null, null, $cache)); + ->setParameter(1, $user) + ->setHydrationCacheProfile(new QueryCacheProfile(null, null, $cache)); $query->getResult(); + $c = $this->getCurrentQueryCount(); + $query->getResult(); + $this->assertEquals($c, $this->getCurrentQueryCount(), "Should not execute query. Its cached!"); } } diff --git a/tests/Doctrine/Tests/ORM/Functional/NativeQueryTest.php b/tests/Doctrine/Tests/ORM/Functional/NativeQueryTest.php index a6a9016a4..3436a74f4 100644 --- a/tests/Doctrine/Tests/ORM/Functional/NativeQueryTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/NativeQueryTest.php @@ -2,8 +2,12 @@ namespace Doctrine\Tests\ORM\Functional; +use Doctrine\Common\Collections\ArrayCollection; + use Doctrine\ORM\Query\ResultSetMapping; use Doctrine\ORM\Query\ResultSetMappingBuilder; +use Doctrine\ORM\Query\Parameter; + use Doctrine\Tests\Models\CMS\CmsUser; use Doctrine\Tests\Models\CMS\CmsPhonenumber; use Doctrine\Tests\Models\CMS\CmsAddress; @@ -191,6 +195,10 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase public function testFluentInterface() { + $parameters = new ArrayCollection; + $parameters->add(new Parameter(1, 'foo')); + $parameters->add(new Parameter(2, 'bar')); + $rsm = new ResultSetMapping; $q = $this->_em->createNativeQuery('SELECT id, name, status, phonenumber FROM cms_users INNER JOIN cms_phonenumbers ON id = user_id WHERE username = ?', $rsm); @@ -199,7 +207,7 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase ->expireResultCache(true) ->setHint('foo', 'bar') ->setParameter(1, 'foo') - ->setParameters(array(2 => 'bar')) + ->setParameters($parameters) ->setResultCacheDriver(null) ->setResultCacheLifetime(3500); @@ -362,7 +370,7 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase $repository = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsAddress'); $query = $repository->createNativeNamedQuery('find-all'); $result = $query->getResult(); - + $this->assertCount(1, $result); $this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsAddress', $result[0]); $this->assertEquals($addr->id, $result[0]->id); @@ -396,7 +404,7 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase $result = $repository->createNativeNamedQuery('fetchIdAndUsernameWithResultClass') ->setParameter(1, 'FabioBatSilva')->getResult(); - + $this->assertEquals(1, count($result)); $this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $result[0]); $this->assertNull($result[0]->name); @@ -511,7 +519,7 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase $user2->name = 'test tester'; $user2->username = 'test'; $user2->status = 'tester'; - + $phone1 = new CmsPhonenumber; $phone2 = new CmsPhonenumber; $phone3 = new CmsPhonenumber; @@ -528,7 +536,7 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->_em->flush(); $this->_em->clear(); - + $repository = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsUser'); $result = $repository->createNativeNamedQuery('fetchUserPhonenumberCount') @@ -583,7 +591,7 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->_em->clear(); - + $result = $repository->createNativeNamedQuery('fetchAllWithResultClass') ->getResult(); diff --git a/tests/Doctrine/Tests/ORM/Functional/QueryCacheTest.php b/tests/Doctrine/Tests/ORM/Functional/QueryCacheTest.php index e4d567db4..faffdd7bc 100644 --- a/tests/Doctrine/Tests/ORM/Functional/QueryCacheTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/QueryCacheTest.php @@ -19,10 +19,13 @@ class QueryCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase */ private $cacheDataReflection; - protected function setUp() { + protected function setUp() + { $this->cacheDataReflection = new \ReflectionProperty("Doctrine\Common\Cache\ArrayCache", "data"); $this->cacheDataReflection->setAccessible(true); + $this->useModelSet('cms'); + parent::setUp(); } diff --git a/tests/Doctrine/Tests/ORM/Functional/QueryTest.php b/tests/Doctrine/Tests/ORM/Functional/QueryTest.php index 74824ff15..fd1e14703 100644 --- a/tests/Doctrine/Tests/ORM/Functional/QueryTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/QueryTest.php @@ -2,11 +2,16 @@ namespace Doctrine\Tests\ORM\Functional; +use Doctrine\Common\Collections\ArrayCollection; + use Doctrine\DBAL\Connection; -use Doctrine\Tests\Models\CMS\CmsUser, - Doctrine\Tests\Models\CMS\CmsArticle; + use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Query; +use Doctrine\ORM\Query\Parameter; + +use Doctrine\Tests\Models\CMS\CmsUser; +use Doctrine\Tests\Models\CMS\CmsArticle; require_once __DIR__ . '/../../TestInit.php'; @@ -149,9 +154,22 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase } public function testSetParameters() + { + $q = $this->_em->createQuery('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name = ?1 AND u.status = ?2'); + + $parameters = new ArrayCollection(); + $parameters->add(new Parameter(1, 'jwage')); + $parameters->add(new Parameter(2, 'active')); + + $q->setParameters($parameters); + $users = $q->getResult(); + } + + public function testSetParametersBackwardsCompatible() { $q = $this->_em->createQuery('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name = ?1 AND u.status = ?2'); $q->setParameters(array(1 => 'jwage', 2 => 'active')); + $users = $q->getResult(); } @@ -176,7 +194,7 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase $articleId = $article1->id; $query = $this->_em->createQuery("select a from Doctrine\Tests\Models\CMS\CmsArticle a WHERE a.topic = ?1"); - $articles = $query->iterate(array(1 => 'Doctrine 2'), Query::HYDRATE_ARRAY); + $articles = $query->iterate(new ArrayCollection(array(new Parameter(1, 'Doctrine 2'))), Query::HYDRATE_ARRAY); $found = array(); foreach ($articles AS $article) { @@ -520,10 +538,10 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->_em->clear(); $query = $this->_em->createQuery("SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.status = :a AND u.id IN (:b)"); - $query->setParameters(array( - 'b' => array($user1->id, $user2->id, $user3->id), - 'a' => 'developer', - )); + $query->setParameters(new ArrayCollection(array( + new Parameter('b', array($user1->id, $user2->id, $user3->id)), + new Parameter('a', 'developer') + ))); $result = $query->getResult(); $this->assertEquals(3, count($result)); @@ -639,7 +657,7 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase /** * @group DDC-1651 */ - public function testSetParameterBindingSingleIdentifierObjectConverted() + public function testSetParameterBindingSingleIdentifierObject() { $userC = new CmsUser; $userC->name = 'Jonathan'; @@ -653,7 +671,10 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase $q = $this->_em->createQuery("SELECT DISTINCT u from Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = ?1"); $q->setParameter(1, $userC); - $this->assertEquals($userC->id, $q->getParameter(1)); + $this->assertEquals($userC, $q->getParameter(1)->getValue()); + + // Parameter is not converted before, but it should be converted during execution. Test should not fail here + $q->getResult(); } diff --git a/tests/Doctrine/Tests/ORM/Query/QueryTest.php b/tests/Doctrine/Tests/ORM/Query/QueryTest.php index 24267c5c5..de160d096 100644 --- a/tests/Doctrine/Tests/ORM/Query/QueryTest.php +++ b/tests/Doctrine/Tests/ORM/Query/QueryTest.php @@ -3,6 +3,9 @@ namespace Doctrine\Tests\ORM\Query; use Doctrine\Common\Cache\ArrayCache; +use Doctrine\Common\Collections\ArrayCollection; + +use Doctrine\ORM\Query\Parameter; class QueryTest extends \Doctrine\Tests\OrmTestCase { @@ -16,21 +19,34 @@ class QueryTest extends \Doctrine\Tests\OrmTestCase public function testGetParameters() { $query = $this->_em->createQuery("select u from Doctrine\Tests\Models\CMS\CmsUser u where u.username = ?1"); - $this->assertEquals(array(), $query->getParameters()); + + $parameters = new ArrayCollection(); + + $this->assertEquals($parameters, $query->getParameters()); } public function testGetParameters_HasSomeAlready() { $query = $this->_em->createQuery("select u from Doctrine\Tests\Models\CMS\CmsUser u where u.username = ?1"); $query->setParameter(2, 84); - $this->assertEquals(array(2 => 84), $query->getParameters()); + + $parameters = new ArrayCollection(); + $parameters->add(new Parameter(2, 84)); + + $this->assertEquals($parameters, $query->getParameters()); } public function testSetParameters() { $query = $this->_em->createQuery("select u from Doctrine\Tests\Models\CMS\CmsUser u where u.username = ?1"); - $query->setParameters(array(1 => 'foo', 2 => 'bar')); - $this->assertEquals(array(1 => 'foo', 2 => 'bar'), $query->getParameters()); + + $parameters = new ArrayCollection(); + $parameters->add(new Parameter(1, 'foo')); + $parameters->add(new Parameter(2, 'bar')); + + $query->setParameters($parameters); + + $this->assertEquals($parameters, $query->getParameters()); } public function testFree() @@ -40,7 +56,7 @@ class QueryTest extends \Doctrine\Tests\OrmTestCase $query->free(); - $this->assertEquals(array(), $query->getParameters()); + $this->assertEquals(0, count($query->getParameters())); } public function testClone() @@ -54,7 +70,7 @@ class QueryTest extends \Doctrine\Tests\OrmTestCase $cloned = clone $query; $this->assertEquals($dql, $cloned->getDql()); - $this->assertEquals(array(), $cloned->getParameters()); + $this->assertEquals(0, count($cloned->getParameters())); $this->assertFalse($cloned->getHint('foo')); } @@ -68,7 +84,7 @@ class QueryTest extends \Doctrine\Tests\OrmTestCase ->setHint('foo', 'bar') ->setHint('bar', 'baz') ->setParameter(1, 'bar') - ->setParameters(array(2 => 'baz')) + ->setParameters(new ArrayCollection(array(new Parameter(2, 'baz')))) ->setResultCacheDriver(null) ->setResultCacheId('foo') ->setDql('foo') @@ -129,7 +145,7 @@ class QueryTest extends \Doctrine\Tests\OrmTestCase /** * @group DDC-1697 */ - public function testKeyValueParameters() + public function testCollectionParameters() { $cities = array( 0 => "Paris", @@ -142,8 +158,9 @@ class QueryTest extends \Doctrine\Tests\OrmTestCase ->setParameter('cities', $cities); $parameters = $query->getParameters(); + $parameter = $parameters->first(); - $this->assertArrayHasKey('cities', $parameters); - $this->assertEquals($cities, $parameters['cities']); + $this->assertEquals('cities', $parameter->getName()); + $this->assertEquals($cities, $parameter->getValue()); } } diff --git a/tests/Doctrine/Tests/ORM/QueryBuilderTest.php b/tests/Doctrine/Tests/ORM/QueryBuilderTest.php index f078b8995..60a0e3dfa 100644 --- a/tests/Doctrine/Tests/ORM/QueryBuilderTest.php +++ b/tests/Doctrine/Tests/ORM/QueryBuilderTest.php @@ -19,8 +19,12 @@ namespace Doctrine\Tests\ORM; +use Doctrine\Common\Collections\ArrayCollection; + use Doctrine\ORM\QueryBuilder, - Doctrine\ORM\Query\Expr; + Doctrine\ORM\Query\Expr, + Doctrine\ORM\Query\Parameter, + Doctrine\ORM\Query\ParameterTypeInferer; require_once __DIR__ . '/../TestInit.php'; @@ -385,7 +389,9 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase ->where('u.id = :id') ->setParameter('id', 1); - $this->assertEquals(array('id' => 1), $qb->getParameters()); + $parameter = new Parameter('id', 1, ParameterTypeInferer::inferType(1)); + + $this->assertEquals($parameter, $qb->getParameter('id')); } public function testSetParameters() @@ -395,9 +401,13 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase ->from('Doctrine\Tests\Models\CMS\CmsUser', 'u') ->where($qb->expr()->orx('u.username = :username', 'u.username = :username2')); - $qb->setParameters(array('username' => 'jwage', 'username2' => 'jonwage')); + $parameters = new ArrayCollection(); + $parameters->add(new Parameter('username', 'jwage')); + $parameters->add(new Parameter('username2', 'jonwage')); - $this->assertEquals(array('username' => 'jwage', 'username2' => 'jonwage'), $qb->getQuery()->getParameters()); + $qb->setParameters($parameters); + + $this->assertEquals($parameters, $qb->getQuery()->getParameters()); } @@ -408,8 +418,12 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase ->from('Doctrine\Tests\Models\CMS\CmsUser', 'u') ->where('u.id = :id'); - $qb->setParameters(array('id' => 1)); - $this->assertEquals(array('id' => 1), $qb->getParameters()); + $parameters = new ArrayCollection(); + $parameters->add(new Parameter('id', 1)); + + $qb->setParameters($parameters); + + $this->assertEquals($parameters, $qb->getParameters()); } public function testGetParameter() @@ -419,8 +433,12 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase ->from('Doctrine\Tests\Models\CMS\CmsUser', 'u') ->where('u.id = :id'); - $qb->setParameters(array('id' => 1)); - $this->assertEquals(1, $qb->getParameter('id')); + $parameters = new ArrayCollection(); + $parameters->add(new Parameter('id', 1)); + + $qb->setParameters($parameters); + + $this->assertEquals($parameters->first(), $qb->getParameter('id')); } public function testMultipleWhere() @@ -536,6 +554,7 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase $qb->setParameter('name', 'romanb'); $q1 = $qb->getQuery(); + $this->assertEquals('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name = :name', $q1->getDql()); $this->assertEquals(1, count($q1->getParameters()));