From ebb432bfb80f5dfa97cefa0a5378ab8ebd836011 Mon Sep 17 00:00:00 2001 From: romanb Date: Sat, 15 Aug 2009 18:11:51 +0000 Subject: [PATCH] [2.0] Preparing to address character casing issue. --- lib/Doctrine/DBAL/Driver/PDOConnection.php | 2 +- .../DBAL/Platforms/AbstractPlatform.php | 6 +++ .../DBAL/Platforms/OraclePlatform.php | 8 ++++ .../DBAL/Platforms/PostgreSqlPlatform.php | 8 ++++ .../Persisters/StandardEntityPersister.php | 2 +- lib/Doctrine/ORM/Query/ResultSetMapping.php | 8 ++-- lib/Doctrine/ORM/Query/SqlWalker.php | 8 ++++ lib/Doctrine/ORM/Tools/SchemaTool.php | 2 +- .../Tests/ORM/Functional/NativeQueryTest.php | 47 +++++++++++++++++++ .../Functional/SingleTableInheritanceTest.php | 4 +- 10 files changed, 87 insertions(+), 8 deletions(-) diff --git a/lib/Doctrine/DBAL/Driver/PDOConnection.php b/lib/Doctrine/DBAL/Driver/PDOConnection.php index be6fddfa1..319a36df7 100644 --- a/lib/Doctrine/DBAL/Driver/PDOConnection.php +++ b/lib/Doctrine/DBAL/Driver/PDOConnection.php @@ -36,6 +36,6 @@ class PDOConnection extends PDO implements Connection parent::__construct($dsn, $user, $password, $options); $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('Doctrine\DBAL\Driver\PDOStatement', array())); $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - $this->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER); + //$this->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER); } } \ No newline at end of file diff --git a/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php b/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php index a04308ac5..2a2d22d48 100644 --- a/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php @@ -1544,6 +1544,12 @@ abstract class AbstractPlatform */ abstract public function getName(); + /** + * Gets the character casing of a column in an SQL result set of this platform. + * + * @param string $column The column name for which to get the correct character casing. + * @return string The column name in the character casing used in SQL result sets. + */ public function getSqlResultCasing($column) { return $column; diff --git a/lib/Doctrine/DBAL/Platforms/OraclePlatform.php b/lib/Doctrine/DBAL/Platforms/OraclePlatform.php index 65978c3d7..31406f707 100644 --- a/lib/Doctrine/DBAL/Platforms/OraclePlatform.php +++ b/lib/Doctrine/DBAL/Platforms/OraclePlatform.php @@ -501,6 +501,14 @@ END;'; return $query; } + /** + * Gets the character casing of a column in an SQL result set of this platform. + * + * Oracle returns all column names in SQL result sets in uppercase. + * + * @param string $column The column name for which to get the correct character casing. + * @return string The column name in the character casing used in SQL result sets. + */ public function getSqlResultCasing($column) { return strtoupper($column); diff --git a/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php b/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php index 0240fcb07..bc97dc9a9 100644 --- a/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php @@ -747,6 +747,14 @@ class PostgreSqlPlatform extends AbstractPlatform return 'postgresql'; } + /** + * Gets the character casing of a column in an SQL result set. + * + * PostgreSQL returns all column names in SQL result sets in lowercase. + * + * @param string $column The column name for which to get the correct character casing. + * @return string The column name in the character casing used in SQL result sets. + */ public function getSqlResultCasing($column) { return strtolower($column); diff --git a/lib/Doctrine/ORM/Persisters/StandardEntityPersister.php b/lib/Doctrine/ORM/Persisters/StandardEntityPersister.php index 8e826f7b1..adcbca924 100644 --- a/lib/Doctrine/ORM/Persisters/StandardEntityPersister.php +++ b/lib/Doctrine/ORM/Persisters/StandardEntityPersister.php @@ -530,7 +530,7 @@ class StandardEntityPersister $coll = new PersistentCollection( $this->_em, $this->_em->getClassMetadata($assoc->targetEntityName), - new ArrayCollection); + /*$this->_class->reflFields[$field]->getValue($entity) ?:*/ new ArrayCollection); $coll->setOwner($entity, $assoc); $this->_class->reflFields[$field]->setValue($entity, $coll); if ($assoc->isLazilyFetched()) { diff --git a/lib/Doctrine/ORM/Query/ResultSetMapping.php b/lib/Doctrine/ORM/Query/ResultSetMapping.php index 99e3701ea..7309f38c6 100644 --- a/lib/Doctrine/ORM/Query/ResultSetMapping.php +++ b/lib/Doctrine/ORM/Query/ResultSetMapping.php @@ -29,7 +29,7 @@ namespace Doctrine\ORM\Query; * reduce the size of serialized instances for more effective caching due to better (un-)serialization * performance. * - * Users should use the public methods. + * Users should use the public methods. * * @author Roman Borschel * @since 2.0 @@ -40,7 +40,7 @@ class ResultSetMapping public $isMixed = false; /** Maps alias names to ClassMetadata descriptors. */ public $aliasMap = array(); - /** Maps alias names to related association mappings. */ + /** Maps alias names to related association field names. */ public $relationMap = array(); /** Maps alias names to parent alias names. */ public $parentAliasMap = array(); @@ -141,7 +141,7 @@ class ResultSetMapping * @param string $class The class name of the joined entity. * @param string $alias The unique alias to use for the joined entity. * @param string $parentAlias The alias of the entity result that is the parent of this joined result. - * @param object $relation The association that connects the parent entity result with the joined entity result. + * @param object $relation The association field that connects the parent entity result with the joined entity result. */ public function addJoinedEntityResult($class, $alias, $parentAlias, $relation) { @@ -154,7 +154,7 @@ class ResultSetMapping * Adds a scalar result mapping. * * @param string $columnName The name of the column in the SQL result set. - * @param string $alias The field alias with which the scalar result should be placed in the result structure. + * @param string $alias The result alias with which the scalar result should be placed in the result structure. */ public function addScalarResult($columnName, $alias) { diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php index 6be1ef04f..c0892481f 100644 --- a/lib/Doctrine/ORM/Query/SqlWalker.php +++ b/lib/Doctrine/ORM/Query/SqlWalker.php @@ -471,6 +471,7 @@ class SqlWalker implements TreeWalker $sql .= ", $tblAlias." . $rootClass->getQuotedDiscriminatorColumnName($this->_platform) . ' AS ' . $columnAlias; + //$columnAlias = $this->_platform->getSqlResultCasing($columnAlias); $this->_rsm->setDiscriminatorColumn($dqlAlias, $columnAlias); $this->_rsm->addMetaResult($dqlAlias, $columnAlias, $discrColumn['fieldName']); @@ -489,6 +490,7 @@ class SqlWalker implements TreeWalker $columnAlias = $this->getSqlColumnAlias($srcColumn); $sql .= ", $sqlTableAlias." . $assoc->getQuotedJoinColumnName($srcColumn, $this->_platform) . ' AS ' . $columnAlias; + //$columnAlias = $this->_platform->getSqlResultCasing($columnAlias); $this->_rsm->addMetaResult($dqlAlias, $columnAlias, $srcColumn); } } @@ -504,6 +506,7 @@ class SqlWalker implements TreeWalker foreach ($assoc->targetToSourceKeyColumns as $srcColumn) { $columnAlias = $this->getSqlColumnAlias($srcColumn); $sql .= ', ' . $sqlTableAlias . '.' . $assoc->getQuotedJoinColumnName($srcColumn, $this->_platform) . ' AS ' . $columnAlias; + //$columnAlias = $this->_platform->getSqlResultCasing($columnAlias); $this->_rsm->addMetaResult($dqlAlias, $columnAlias, $srcColumn); } } @@ -745,6 +748,7 @@ class SqlWalker implements TreeWalker $columnAlias = $this->getSqlColumnAlias($class->columnNames[$fieldName]); $sql .= $sqlTableAlias . '.' . $columnName . ' AS ' . $columnAlias; + //$columnAlias = $this->_platform->getSqlResultCasing($columnAlias); $this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName); } else { throw DoctrineException::updateMe( @@ -761,6 +765,7 @@ class SqlWalker implements TreeWalker $columnAlias = 'sclr' . $this->_aliasCounter++; $sql .= $this->walkAggregateExpression($expr) . ' AS ' . $columnAlias; + //$columnAlias = $this->_platform->getSqlResultCasing($columnAlias); $this->_rsm->addScalarResult($columnAlias, $resultAlias); } else if ($expr instanceof AST\Subselect) { $sql .= $this->walkSubselect($expr); @@ -774,6 +779,7 @@ class SqlWalker implements TreeWalker $columnAlias = 'sclr' . $this->_aliasCounter++; $sql .= $this->walkFunction($expr) . ' AS ' . $columnAlias; + //$columnAlias = $this->_platform->getSqlResultCasing($columnAlias); $this->_rsm->addScalarResult($columnAlias, $resultAlias); } else { // IdentificationVariable @@ -801,6 +807,7 @@ class SqlWalker implements TreeWalker $sql .= $sqlTableAlias . '.' . $class->getQuotedColumnName($fieldName, $this->_platform) . ' AS ' . $columnAlias; + //$columnAlias = $this->_platform->getSqlResultCasing($columnAlias); $this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName); } @@ -820,6 +827,7 @@ class SqlWalker implements TreeWalker $sql .= $sqlTableAlias . '.' . $subClass->getQuotedColumnName($fieldName, $this->_platform) . ' AS ' . $columnAlias; + //$columnAlias = $this->_platform->getSqlResultCasing($columnAlias); $this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName); } } diff --git a/lib/Doctrine/ORM/Tools/SchemaTool.php b/lib/Doctrine/ORM/Tools/SchemaTool.php index ae43a5332..189100fcd 100644 --- a/lib/Doctrine/ORM/Tools/SchemaTool.php +++ b/lib/Doctrine/ORM/Tools/SchemaTool.php @@ -205,7 +205,7 @@ class SchemaTool private function _gatherColumn($class, array $mapping, array &$options) { $column = array(); - $column['name'] = $class->getQuotedColumnName($mapping['columnName'], $this->_platform); + $column['name'] = $class->getQuotedColumnName($mapping['fieldName'], $this->_platform); $column['type'] = Type::getType($mapping['type']); $column['length'] = $mapping['length']; $column['notnull'] = ! $mapping['nullable']; diff --git a/tests/Doctrine/Tests/ORM/Functional/NativeQueryTest.php b/tests/Doctrine/Tests/ORM/Functional/NativeQueryTest.php index 182a4de92..abb929c65 100644 --- a/tests/Doctrine/Tests/ORM/Functional/NativeQueryTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/NativeQueryTest.php @@ -4,6 +4,7 @@ namespace Doctrine\Tests\ORM\Functional; use Doctrine\ORM\Query\ResultSetMapping; use Doctrine\Tests\Models\CMS\CmsUser; +use Doctrine\Tests\Models\CMS\CmsPhonenumber; require_once __DIR__ . '/../../TestInit.php'; @@ -17,6 +18,10 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase protected function setUp() { $this->useModelSet('cms'); parent::setUp(); + + if ($this->_em->getConnection()->getDatabasePlatform()->getName() == 'oracle') { + $this->markTestSkipped('The ' . $testClass .' does not work with Oracle due to character casing.'); + } } public function testBasicNativeQuery() @@ -27,6 +32,8 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase $user->status = 'dev'; $this->_em->persist($user); $this->_em->flush(); + + $this->_em->clear(); $rsm = new ResultSetMapping; $rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u'); @@ -42,5 +49,45 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertTrue($users[0] instanceof CmsUser); $this->assertEquals('Roman', $users[0]->name); } + + public function testJoinedNativeQuery() + { + $user = new CmsUser; + $user->name = 'Roman'; + $user->username = 'romanb'; + $user->status = 'dev'; + + $phone = new CmsPhonenumber; + $phone->phonenumber = 424242; + + $user->addPhonenumber($phone); + + $this->_em->persist($user); + $this->_em->flush(); + + $this->_em->clear(); + + $rsm = new ResultSetMapping; + $rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u'); + $rsm->addFieldResult('u', 'id', 'id'); + $rsm->addFieldResult('u', 'name', 'name'); + $rsm->addFieldResult('u', 'status', 'status'); + $rsm->addJoinedEntityResult('Doctrine\Tests\Models\CMS\CmsPhonenumber', 'p', 'u', 'phonenumbers'); + $rsm->addFieldResult('p', 'phonenumber', 'phonenumber'); + + $query = $this->_em->createNativeQuery('SELECT id, name, status, phonenumber FROM cms_users INNER JOIN cms_phonenumbers ON id = user_id WHERE username = ?', $rsm); + $query->setParameter(1, 'romanb'); + + $users = $query->getResult(); + $this->assertEquals(1, count($users)); + $this->assertTrue($users[0] instanceof CmsUser); + $this->assertEquals('Roman', $users[0]->name); + $this->assertTrue($users[0]->getPhonenumbers() instanceof \Doctrine\ORM\PersistentCollection); + $this->assertEquals(1, count($users[0]->getPhonenumbers())); + $phones = $users[0]->getPhonenumbers(); + $this->assertEquals(424242, $phones[0]->phonenumber); + $this->assertTrue($phones[0]->getUser() === $users[0]); + + } } diff --git a/tests/Doctrine/Tests/ORM/Functional/SingleTableInheritanceTest.php b/tests/Doctrine/Tests/ORM/Functional/SingleTableInheritanceTest.php index 5f7af14ec..e67e34fa4 100644 --- a/tests/Doctrine/Tests/ORM/Functional/SingleTableInheritanceTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/SingleTableInheritanceTest.php @@ -20,6 +20,8 @@ class SingleTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\RelatedEntity') )); } catch (\Exception $e) { + var_dump($e->getMessage()); + var_dump($e->getTraceAsString()); // Swallow all exceptions. We do not test the schema tool here. } } @@ -111,7 +113,7 @@ class ParentEntity { private $id; /** - * @Column(type="string") + * @Column(name="DATA", type="string") */ private $data;