Skip to content
Browse files

Merge branch 'DDC-1651'

  • Loading branch information...
2 parents 93f79d0 + bd1bc07 commit 6cd82d77f5e581b3d21c60c5cb5e6c5042a3ff9b @beberlei beberlei committed Feb 18, 2012
View
48 lib/Doctrine/ORM/AbstractQuery.php
@@ -208,6 +208,7 @@ public function setParameter($key, $value, $type = null)
{
$key = trim($key, ':');
+ $value = $this->processParameterValue($value);
if ($type === null) {
$type = Query\ParameterTypeInferer::inferType($value);
}
@@ -219,6 +220,53 @@ public function setParameter($key, $value, $type = null)
}
/**
+ * Process an individual parameter value
+ *
+ * @param mixed $value
+ * @return array
+ */
+ private function processParameterValue($value)
+ {
+ switch (true) {
+ case is_array($value):
+ for ($i = 0, $l = count($value); $i < $l; $i++) {
+ $paramValue = $this->processParameterValue($value[$i]);
+ $value[$i] = is_array($paramValue) ? $paramValue[key($paramValue)] : $paramValue;
+ }
+
+ return $value;
+
+ case is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(get_class($value)):
+ return $this->convertObjectParameterToScalarValue($value);
+
+ default:
+ return $value;
+ }
+ }
+
+ protected function convertObjectParameterToScalarValue($value)
+ {
+ $class = $this->_em->getClassMetadata(get_class($value));
+
+ if ($class->isIdentifierComposite) {
+ throw new \InvalidArgumentException("Binding an entity with a composite primary key to a query is not supported. You should split the parameter into the explicit fields and bind them seperately.");
+ }
+
+ if ($this->_em->getUnitOfWork()->getEntityState($value) === UnitOfWork::STATE_MANAGED) {
+ $values = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
+ } else {
+ $values = $class->getIdentifierValues($value);
+ }
+
+ $value = $values[$class->getSingleIdentifierFieldName()];
+ if (!$value) {
+ throw new \InvalidArgumentException("Binding entities to query parameters only allowed for entities that have an identifier.");
+ }
+
+ return $value;
+ }
+
+ /**
* Sets a collection of query parameters.
*
* @param array $params
View
36 lib/Doctrine/ORM/Query.php
@@ -282,7 +282,8 @@ private function processParameterMappings($paramMappings)
}
$sqlPositions = $paramMappings[$key];
- $value = array_values($this->processParameterValue($value));
+ // optimized multi value sql positions away for now, they are not allowed in DQL anyways.
+ $value = array($value);
$countValue = count($value);
for ($i = 0, $l = count($sqlPositions); $i < $l; $i++) {
@@ -306,39 +307,6 @@ private function processParameterMappings($paramMappings)
}
/**
- * Process an individual parameter value
- *
- * @param mixed $value
- * @return array
- */
- private function processParameterValue($value)
- {
- switch (true) {
- case is_array($value):
- for ($i = 0, $l = count($value); $i < $l; $i++) {
- $paramValue = $this->processParameterValue($value[$i]);
-
- // TODO: What about Entities that have composite primary key?
- $value[$i] = is_array($paramValue) ? $paramValue[key($paramValue)] : $paramValue;
- }
-
- return array($value);
-
- case is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(get_class($value)):
- if ($this->_em->getUnitOfWork()->getEntityState($value) === UnitOfWork::STATE_MANAGED) {
- return array_values($this->_em->getUnitOfWork()->getEntityIdentifier($value));
- }
-
- $class = $this->_em->getClassMetadata(get_class($value));
-
- return array_values($class->getIdentifierValues($value));
-
- default:
- return array($value);
- }
- }
-
- /**
* Defines a cache driver to be used for caching queries.
*
* @param Doctrine_Cache_Interface|null $driver Cache driver
View
22 tests/Doctrine/Tests/ORM/Functional/CompositePrimaryKeyTest.php
@@ -4,6 +4,7 @@
use Doctrine\Tests\Models\Navigation\NavCountry;
use Doctrine\Tests\Models\Navigation\NavPointOfInterest;
use Doctrine\Tests\Models\Navigation\NavTour;
+use Doctrine\Tests\Models\Navigation\NavPhotos;
require_once __DIR__ . '/../../TestInit.php';
@@ -51,6 +52,25 @@ public function testPersistCompositePkEntity()
$this->assertEquals('Brandenburger Tor', $poi->getName());
}
+ /**
+ * @group DDC-1651
+ */
+ public function testSetParameterCompositeKeyObject()
+ {
+ $this->putGermanysBrandenburderTor();
+
+ $poi = $this->_em->find('Doctrine\Tests\Models\Navigation\NavPointOfInterest', array('lat' => 100, 'long' => 200));
+ $photo = new NavPhotos($poi, "asdf");
+ $this->_em->persist($photo);
+ $this->_em->flush();
+ $this->_em->clear();
+
+ $dql = 'SELECT t FROM Doctrine\Tests\Models\Navigation\NavPhotos t WHERE t.poi = ?1';
+
+ $this->setExpectedException('Doctrine\ORM\Query\QueryException', 'A single-valued association path expression to an entity with a composite primary key is not supported.');
+ $sql = $this->_em->createQuery($dql)->getSQL();
+ }
+
public function testManyToManyCompositeRelation()
{
$this->putGermanysBrandenburderTor();
@@ -98,4 +118,4 @@ public function testSpecifiyUnknownIdentifierPrimaryKeyFails()
$this->setExpectedException('Doctrine\ORM\ORMException', 'The identifier long is missing for a query of Doctrine\Tests\Models\Navigation\NavPointOfInterest');
$poi = $this->_em->find('Doctrine\Tests\Models\Navigation\NavPointOfInterest', array('key1' => 100));
}
-}
+}
View
22 tests/Doctrine/Tests/ORM/Functional/QueryTest.php
@@ -599,4 +599,24 @@ public function testQueryWithHiddenAsSelectExpression()
$this->assertEquals(3, count($users));
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $users[0]);
}
-}
+
+ /**
+ * @group DDC-1651
+ */
+ public function testSetParameterBindingSingleIdentifierObjectConverted()
+ {
+ $userC = new CmsUser;
+ $userC->name = 'Jonathan';
+ $userC->username = 'jwage';
+ $userC->status = 'developer';
+ $this->_em->persist($userC);
+
+ $this->_em->flush();
+ $this->_em->clear();
+
+ $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));
+ }
+}

0 comments on commit 6cd82d7

Please sign in to comment.
Something went wrong with that request. Please try again.