Permalink
Browse files

Merge pull request #690 from FabioBatSilva/DDC-2494

[DDC-2494] Apply type conversion to meta columns
  • Loading branch information...
2 parents b15758b + c1e688f commit 6937061b23ec4de63081efac800415e09dcbcb4f @guilhermeblanco guilhermeblanco committed Jun 12, 2013
@@ -114,9 +114,8 @@ protected function hydrateRowData(array $sqlResult, array &$cache, array &$resul
}
// Convert field to a valid PHP value
- if (isset($cache[$column]['field'])) {
- $type = Type::getType($cache[$column]['class']->fieldMappings[$cache[$column]['name']]['type']);
- $value = $type->convertToPHPValue($value, $this->_platform);
+ if (isset($cache[$column]['type'])) {
+ $value = Type::getType($cache[$column]['type'])->convertToPHPValue($value, $this->_platform);
}
// Prevent overwrite in case of inherit classes using same property name (See AbstractHydrator)
@@ -145,44 +144,36 @@ protected function hydrateRowData(array $sqlResult, array &$cache, array &$resul
*/
protected function hydrateColumnInfo($entityName, $column)
{
- switch (true) {
- case (isset($this->_rsm->fieldMappings[$column])):
- $class = isset($this->declaringClasses[$column])
- ? $this->declaringClasses[$column]
- : $this->class;
-
- // If class is not part of the inheritance, ignore
- if ( ! ($class->name === $entityName || is_subclass_of($entityName, $class->name))) {
- return null;
- }
-
- return array(
- 'class' => $class,
- 'name' => $this->_rsm->fieldMappings[$column],
- 'field' => true,
- );
- case (isset($this->_rsm->relationMap[$column])):
- $class = isset($this->_rsm->relationMap[$column])
- ? $this->_rsm->relationMap[$column]
- : $this->class;
+ if (isset($this->_rsm->fieldMappings[$column])) {
+ $name = $this->_rsm->fieldMappings[$column];
+ $class = isset($this->declaringClasses[$column])
+ ? $this->declaringClasses[$column]
+ : $this->class;
- // If class is not self referencing, ignore
- if ( ! ($class === $entityName || is_subclass_of($entityName, $class))) {
- return null;
- }
+ // If class is not part of the inheritance, ignore
+ if ( ! ($class->name === $entityName || is_subclass_of($entityName, $class->name))) {
+ return null;
+ }
- // TODO: Decide what to do with associations. It seems original code is incomplete.
- // One solution is to load the association, but it might require extra efforts.
- return array('name' => $column);
+ return array(
+ 'name' => $name,
+ 'type' => $class->fieldMappings[$name]['type']
+ );
+ }
- case (isset($this->_rsm->metaMappings[$column])):
- return array(
- 'name' => $this->_rsm->metaMappings[$column]
- );
+ if (isset($this->_rsm->metaMappings[$column])) {
+ return array(
+ 'name' => $this->_rsm->metaMappings[$column],
+ 'type' => (isset($this->_rsm->typeMappings[$column]) ? $this->_rsm->typeMappings[$column] : null)
+ );
+ }
- default:
- return null;
+ // An ObjectHydrator should be used instead of SimpleObjectHydrator
+ if (isset($this->_rsm->relationMap[$column])) {
+ throw new \Exception(sprintf('Unable to retrieve association information for column "%s"', $column));
}
+
+ return null;
}
}
@@ -1334,16 +1334,22 @@ protected function getSelectColumnAssociationSQL($field, $assoc, ClassMetadata $
return '';
}
- $columnList = array();
+ $columnList = array();
+ $targetClass = $this->em->getClassMetadata($assoc['targetEntity']);
foreach ($assoc['joinColumns'] as $joinColumn) {
-
+ $type = null;
+ $isIdentifier = isset($assoc['id']) && $assoc['id'] === true;
$quotedColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform);
$resultColumnName = $this->getSQLColumnAlias($joinColumn['name']);
$columnList[] = $this->getSQLTableAlias($class->name, ($alias == 'r' ? '' : $alias) )
. '.' . $quotedColumn . ' AS ' . $resultColumnName;
- $this->rsm->addMetaResult($alias, $resultColumnName, $quotedColumn, isset($assoc['id']) && $assoc['id'] === true);
+ if (isset($targetClass->fieldNames[$joinColumn['referencedColumnName']])) {
+ $type = $targetClass->fieldMappings[$targetClass->fieldNames[$joinColumn['referencedColumnName']]]['type'];
+ }
+
+ $this->rsm->addMetaResult($alias, $resultColumnName, $quotedColumn, $isIdentifier, $type);
}
return implode(', ', $columnList);
@@ -543,14 +543,15 @@ public function isMixedResult()
/**
* Adds a meta column (foreign key or discriminator column) to the result set.
*
- * @param string $alias
- * @param string $columnName
- * @param string $fieldName
+ * @param string $alias The result alias with which the meta result should be placed in the result structure.
+ * @param string $columnName The name of the column in the SQL result set.
+ * @param string $fieldName The name of the field on the declaring class.
* @param bool $isIdentifierColumn
+ * @param string $type The column type
*
* @return ResultSetMapping This ResultSetMapping instance.
*/
- public function addMetaResult($alias, $columnName, $fieldName, $isIdentifierColumn = false)
+ public function addMetaResult($alias, $columnName, $fieldName, $isIdentifierColumn = false, $type = null)
{
$this->metaMappings[$columnName] = $fieldName;
$this->columnOwnerMap[$columnName] = $alias;
@@ -559,6 +560,10 @@ public function addMetaResult($alias, $columnName, $fieldName, $isIdentifierColu
$this->isIdentifierColumn[$alias][$columnName] = true;
}
+ if ($type) {
+ $this->typeMappings[$columnName] = $type;
+ }
+
return $this;
}
}
@@ -0,0 +1,211 @@
+<?php
+
+namespace Doctrine\Tests\ORM\Functional\Ticket;
+
+use Doctrine\DBAL\Types\Type;
+use Doctrine\DBAL\Platforms\AbstractPlatform;
+
+/**
+ * @group DDC-2494
+ */
+class DDC2494Test extends \Doctrine\Tests\OrmFunctionalTestCase
+{
+ protected function setUp()
+ {
+ parent::setUp();
+
+ DDC2494TinyIntType::$calls = array();
+
+ Type::addType('ddc2494_tinyint', __NAMESPACE__ . '\DDC2494TinyIntType');
+
+ $this->_schemaTool->createSchema(array(
+ $this->_em->getClassMetadata(DDC2494Currency::CLASSNAME),
+ $this->_em->getClassMetadata(DDC2494Campaign::CLASSNAME),
+ ));
+ }
+
+ public function testIssue()
+ {
+ $currency = new DDC2494Currency(1, 2);
+
+ $this->_em->persist($currency);
+ $this->_em->flush();
+
+ $campaign = new DDC2494Campaign($currency);
+
+ $this->_em->persist($campaign);
+ $this->_em->flush();
+ $this->_em->close();
+
+ $this->assertArrayHasKey('convertToDatabaseValue', DDC2494TinyIntType::$calls);
+ $this->assertCount(3, DDC2494TinyIntType::$calls['convertToDatabaseValue']);
+
+ $item = $this->_em->find(DDC2494Campaign::CLASSNAME, $campaign->getId());
+
+ $this->assertInstanceOf(DDC2494Campaign::CLASSNAME, $item);
+ $this->assertInstanceOf(DDC2494Currency::CLASSNAME, $item->getCurrency());
+
+ $queryCount = $this->getCurrentQueryCount();
+
+ $this->assertInstanceOf('\Doctrine\Common\Proxy\Proxy', $item->getCurrency());
+ $this->assertFalse($item->getCurrency()->__isInitialized());
+
+ $this->assertArrayHasKey('convertToPHPValue', DDC2494TinyIntType::$calls);
+ $this->assertCount(1, DDC2494TinyIntType::$calls['convertToPHPValue']);
+
+ $this->assertInternalType('integer', $item->getCurrency()->getId());
+ $this->assertCount(1, DDC2494TinyIntType::$calls['convertToPHPValue']);
+ $this->assertFalse($item->getCurrency()->__isInitialized());
+
+ $this->assertEquals($queryCount, $this->getCurrentQueryCount());
+
+ $this->assertInternalType('integer', $item->getCurrency()->getTemp());
+ $this->assertCount(3, DDC2494TinyIntType::$calls['convertToPHPValue']);
+ $this->assertTrue($item->getCurrency()->__isInitialized());
+
+ $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
+ }
+}
+
+/**
+ * @Table(name="ddc2494_currency")
+ * @Entity
+ */
+class DDC2494Currency
+{
+ const CLASSNAME = __CLASS__;
+
+ /**
+ * @Id
+ * @Column(type="integer", type="ddc2494_tinyint")
+ */
+ protected $id;
+
+ /**
+ * @Column(name="temp", type="ddc2494_tinyint", nullable=false)
+ */
+ protected $temp;
+
+ /**
+ * @var \Doctrine\Common\Collections\Collection
+ *
+ * @OneToMany(targetEntity="DDC2494Campaign", mappedBy="currency")
+ */
+ protected $campaigns;
+
+ public function __construct($id, $temp)
+ {
+ $this->id = $id;
+ $this->temp = $temp;
+ }
+
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ public function getTemp()
+ {
+ return $this->temp;
+ }
+
+ public function getCampaigns()
+ {
+ return $this->campaigns;
+ }
+}
+
+/**
+ * @Table(name="ddc2494_campaign")
+ * @Entity
+ */
+class DDC2494Campaign
+{
+ const CLASSNAME = __CLASS__;
+
+ /**
+ * @Id
+ * @GeneratedValue
+ * @Column(type="integer")
+ */
+ protected $id;
+
+ /**
+ * @var \Doctrine\Tests\ORM\Functional\Ticket\DDC2494Currency
+ *
+ * @ManyToOne(targetEntity="DDC2494Currency", inversedBy="campaigns")
+ * @JoinColumn(name="currency_id", referencedColumnName="id", nullable=false)
+ */
+ protected $currency;
+
+ public function __construct(DDC2494Currency $currency)
+ {
+ $this->currency = $currency;
+ }
+
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * @return \Doctrine\Tests\ORM\Functional\Ticket\DDC2494Currency
+ */
+ public function getCurrency()
+ {
+ return $this->currency;
+ }
+}
+
+class DDC2494TinyIntType extends Type
+{
+ public static $calls = array();
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
+ {
+ return $platform->getSmallIntTypeDeclarationSQL($fieldDeclaration);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function convertToDatabaseValue($value, AbstractPlatform $platform)
+ {
+ $return = (string) $value;
+
+ self::$calls[__FUNCTION__][] = array(
+ 'value' => $value,
+ 'return' => $return,
+ 'platform' => $platform,
+ );
+
+ return $return;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function convertToPHPValue($value, AbstractPlatform $platform)
+ {
+ $return = (integer) $value;
+
+ self::$calls[__FUNCTION__][] = array(
+ 'value' => $value,
+ 'return' => $return,
+ 'platform' => $platform,
+ );
+
+ return $return;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'ddc2494_tinyint';
+ }
+}

0 comments on commit 6937061

Please sign in to comment.