diff --git a/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php b/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php index 49caf5f42..4115ca9e1 100644 --- a/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php @@ -19,7 +19,7 @@ * . */ -#namespace Doctrine::DBAL::Platforms; +#namespace Doctrine\DBAL\Platforms; /** * The MySqlPlatform provides the behavior, features and SQL dialect of the diff --git a/lib/Doctrine/ORM/Collection.php b/lib/Doctrine/ORM/Collection.php index ae0632c8f..0033168cb 100644 --- a/lib/Doctrine/ORM/Collection.php +++ b/lib/Doctrine/ORM/Collection.php @@ -104,6 +104,8 @@ final class Doctrine_ORM_Collection extends Doctrine_Common_Collections_Collecti */ private $_hydrationFlag; + private $_ownerClass; + /** * Creates a new persistent collection. */ @@ -111,8 +113,9 @@ final class Doctrine_ORM_Collection extends Doctrine_Common_Collections_Collecti { $this->_entityBaseType = $entityBaseType; $this->_em = $em; + $this->_ownerClass = $em->getClassMetadata($entityBaseType); if ($keyField !== null) { - if ( ! $this->_em->getClassMetadata($entityBaseType)->hasField($keyField)) { + if ( ! $this->_ownerClass->hasField($keyField)) { throw new Doctrine_Exception("Invalid field '$keyField' can't be uses as key."); } $this->_keyField = $keyField; @@ -227,7 +230,7 @@ final class Doctrine_ORM_Collection extends Doctrine_Common_Collections_Collecti if ($this->_hydrationFlag) { if ($this->_backRefFieldName) { // set back reference to owner - $this->_em->getClassMetadata($this->_entityBaseType)->getReflectionProperty( + $this->_ownerClass->getReflectionProperty( $this->_backRefFieldName)->setValue($value, $this->_owner); } } else { diff --git a/lib/Doctrine/ORM/Entity.php b/lib/Doctrine/ORM/Entity.php index 44de89fb3..ced9de006 100644 --- a/lib/Doctrine/ORM/Entity.php +++ b/lib/Doctrine/ORM/Entity.php @@ -29,6 +29,7 @@ * @link www.doctrine-project.org * @since 2.0 * @version $Revision: 4342 $ + * @DEPRECATED */ interface Doctrine_ORM_Entity {} diff --git a/lib/Doctrine/ORM/EntityManager.php b/lib/Doctrine/ORM/EntityManager.php index 80f615779..f34871a49 100644 --- a/lib/Doctrine/ORM/EntityManager.php +++ b/lib/Doctrine/ORM/EntityManager.php @@ -594,9 +594,11 @@ class Doctrine_ORM_EntityManager $this->_hydrators[$hydrationMode] = new Doctrine_ORM_Internal_Hydration_ArrayHydrator($this); break; case Doctrine_ORM_Query::HYDRATE_SCALAR: - case Doctrine_ORM_Query::HYDRATE_SINGLE_SCALAR: $this->_hydrators[$hydrationMode] = new Doctrine_ORM_Internal_Hydration_ScalarHydrator($this); break; + case Doctrine_ORM_Query::HYDRATE_SINGLE_SCALAR: + $this->_hydrators[$hydrationMode] = new Doctrine_ORM_Internal_Hydration_SingleScalarHydrator($this); + break; case Doctrine_ORM_Query::HYDRATE_NONE: $this->_hydrators[$hydrationMode] = new Doctrine_ORM_Internal_Hydration_NoneHydrator($this); break; diff --git a/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php b/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php index cfd8070ab..e14ac06ad 100644 --- a/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php +++ b/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php @@ -38,11 +38,11 @@ abstract class Doctrine_ORM_Internal_Hydration_AbstractHydrator * * Two dimensional array containing the map for query aliases. Main keys are component aliases. * - * table Table object associated with given alias. + * metadata ClassMetadata object associated with given alias. * relation Relation object owned by the parent. * parent Alias of the parent. * agg Aggregates of this component. - * map Name of the column / aggregate value this component is mapped to a collection. + * map Name of the column / aggregate value this component is mapped to in a collection. */ protected $_queryComponents = array(); @@ -100,7 +100,7 @@ abstract class Doctrine_ORM_Internal_Hydration_AbstractHydrator { $this->_stmt = $stmt; $this->_prepare($parserResult); - $result = $this->_hydrateAll($parserResult); + $result = $this->_hydrateAll(); $this->_cleanup(); return $result; } @@ -164,7 +164,7 @@ abstract class Doctrine_ORM_Internal_Hydration_AbstractHydrator * * @param object $parserResult */ - abstract protected function _hydrateAll($parserResult); + abstract protected function _hydrateAll(); /** * Gets the row container used during row-by-row hydration through {@link iterate()}. diff --git a/lib/Doctrine/ORM/Internal/Hydration/ArrayDriver.php b/lib/Doctrine/ORM/Internal/Hydration/ArrayDriver.php index 662aac349..36575ad2f 100644 --- a/lib/Doctrine/ORM/Internal/Hydration/ArrayDriver.php +++ b/lib/Doctrine/ORM/Internal/Hydration/ArrayDriver.php @@ -30,6 +30,7 @@ * @version $Revision$ * @author Konsta Vesterinen * @author Roman Borschel + * @DEPRECATED */ class Doctrine_ORM_Internal_Hydration_ArrayDriver { diff --git a/lib/Doctrine/ORM/Internal/Hydration/ArrayHydrator.php b/lib/Doctrine/ORM/Internal/Hydration/ArrayHydrator.php index 18d3ede80..b387d2f63 100644 --- a/lib/Doctrine/ORM/Internal/Hydration/ArrayHydrator.php +++ b/lib/Doctrine/ORM/Internal/Hydration/ArrayHydrator.php @@ -39,7 +39,7 @@ class Doctrine_ORM_Internal_Hydration_ArrayHydrator extends Doctrine_ORM_Interna } /** @override */ - protected function _hydrateAll($parserResult) + protected function _hydrateAll() { $s = microtime(true); @@ -61,7 +61,7 @@ class Doctrine_ORM_Internal_Hydration_ArrayHydrator extends Doctrine_ORM_Interna // 1) Initialize $id = $this->_idTemplate; // initialize the id-memory $nonemptyComponents = array(); - $rowData = parent::_gatherRowData($data, $cache, $id, $nonemptyComponents); + $rowData = $this->_gatherRowData($data, $cache, $id, $nonemptyComponents); $rootAlias = $this->_rootAlias; // 2) Hydrate the data of the root entity from the current row diff --git a/lib/Doctrine/ORM/Internal/Hydration/ObjectDriver.php b/lib/Doctrine/ORM/Internal/Hydration/ObjectDriver.php index 4b871abe6..c17dc687c 100644 --- a/lib/Doctrine/ORM/Internal/Hydration/ObjectDriver.php +++ b/lib/Doctrine/ORM/Internal/Hydration/ObjectDriver.php @@ -31,6 +31,7 @@ * @author Konsta Vesterinen * @author Roman Borschel * @internal All the methods in this class are performance-sentitive. + * @DEPRECATED */ class Doctrine_ORM_Internal_Hydration_ObjectDriver { diff --git a/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php b/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php index a3e2c4f19..9116cee0a 100644 --- a/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php +++ b/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php @@ -1,8 +1,5 @@ _stmt->fetch(PDO::FETCH_ASSOC)) { $this->_hydrateRow($data, $cache, $result); } @@ -111,7 +111,7 @@ class Doctrine_ORM_Internal_Hydration_ObjectHydrator extends Doctrine_ORM_Intern } } - private function getElementCollection($component) + private function getCollection($component) { $coll = new Doctrine_ORM_Collection($this->_em, $component); $this->_collections[] = $coll; @@ -125,7 +125,7 @@ class Doctrine_ORM_Internal_Hydration_ObjectHydrator extends Doctrine_ORM_Intern if ( ! isset($this->_initializedRelations[$oid][$name])) { $relation = $classMetadata->getAssociationMapping($name); $relatedClass = $this->_em->getClassMetadata($relation->getTargetEntityName()); - $coll = $this->getElementCollection($relatedClass->getClassName()); + $coll = $this->getCollection($relatedClass->getClassName()); $coll->_setOwner($entity, $relation); $coll->_setHydrationFlag(true); $classMetadata->getReflectionProperty($name)->setValue($entity, $coll); @@ -142,7 +142,7 @@ class Doctrine_ORM_Internal_Hydration_ObjectHydrator extends Doctrine_ORM_Intern private function getLastKey($coll) { - // check needed because of mixed results. + // Check needed because of mixed results. // is_object instead of is_array because is_array is slow on large arrays. if (is_object($coll)) { $coll->last(); @@ -153,9 +153,9 @@ class Doctrine_ORM_Internal_Hydration_ObjectHydrator extends Doctrine_ORM_Intern } } - private function getElement(array $data, $className) + private function getEntity(array $data, $className) { - $entity = $this->_em->getUnitOfWork()->createEntity($className, $data); + $entity = $this->_uow->createEntity($className, $data); $oid = spl_object_hash($entity); $this->_metadataMap[$oid] = $this->_em->getClassMetadata($className); return $entity; @@ -169,7 +169,7 @@ class Doctrine_ORM_Internal_Hydration_ObjectHydrator extends Doctrine_ORM_Intern * @param $entity2 * @param $indexField */ - private function addRelatedIndexedElement($entity1, $property, $entity2, $indexField) + private function addRelatedIndexedEntity($entity1, $property, $entity2, $indexField) { $classMetadata1 = $this->_metadataMap[spl_object_hash($entity1)]; $classMetadata2 = $this->_metadataMap[spl_object_hash($entity2)]; @@ -184,15 +184,23 @@ class Doctrine_ORM_Internal_Hydration_ObjectHydrator extends Doctrine_ORM_Intern * @param $property * @param $entity2 */ - private function addRelatedElement($entity1, $property, $entity2) + private function addRelatedEntity($entity1, $property, $entity2) { $classMetadata1 = $this->_metadataMap[spl_object_hash($entity1)]; $classMetadata1->getReflectionProperty($property)->getValue($entity1)->add($entity2); } + /** + * Checks whether a field on an entity has a non-null value. + * + * @param object $entity + * @param string $field + * @return boolean + */ private function isFieldSet($entity, $field) { - return $this->_metadataMap[spl_object_hash($entity)]->getReflectionProperty($field) + return $this->_metadataMap[spl_object_hash($entity)] + ->getReflectionProperty($field) ->getValue($entity) !== null; } @@ -220,7 +228,7 @@ class Doctrine_ORM_Internal_Hydration_ObjectHydrator extends Doctrine_ORM_Intern $targetClass->getReflectionProperty($sourceProp)->setValue($entity2, $entity1); } } else { - // for sure bidirectional, as there is no inverse side in unidirectional + // For sure bidirectional, as there is no inverse side in unidirectional $mappedByProp = $relation->getMappedByFieldName(); $targetClass->getReflectionProperty($mappedByProp)->setValue($entity2, $entity1); } @@ -228,11 +236,8 @@ class Doctrine_ORM_Internal_Hydration_ObjectHydrator extends Doctrine_ORM_Intern } /** - * Hydrates a single row. - * - * @param $data The row data. - * @param $cache The cache to use. - * @param $result The result to append to. + * {@inheritdoc} + * * @override */ protected function _hydrateRow(array &$data, array &$cache, &$result) @@ -240,7 +245,7 @@ class Doctrine_ORM_Internal_Hydration_ObjectHydrator extends Doctrine_ORM_Intern // 1) Initialize $id = $this->_idTemplate; // initialize the id-memory $nonemptyComponents = array(); - $rowData = parent::_gatherRowData($data, $cache, $id, $nonemptyComponents); + $rowData = $this->_gatherRowData($data, $cache, $id, $nonemptyComponents); $rootAlias = $this->_rootAlias; // 2) Hydrate the data of the root entity from the current row @@ -318,11 +323,11 @@ class Doctrine_ORM_Internal_Hydration_ObjectHydrator extends Doctrine_ORM_Intern $index = $indexExists ? $this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]] : false; $indexIsValid = $index !== false ? $this->isIndexKeyInUse($baseElement, $relationAlias, $index) : false; if ( ! $indexExists || ! $indexIsValid) { - $element = $this->getElement($data, $entityName); + $element = $this->getEntity($data, $entityName); if ($field = $this->_getCustomIndexField($dqlAlias)) { - $this->addRelatedIndexedElement($baseElement, $relationAlias, $element, $field); + $this->addRelatedIndexedEntity($baseElement, $relationAlias, $element, $field); } else { - $this->addRelatedElement($baseElement, $relationAlias, $element); + $this->addRelatedEntity($baseElement, $relationAlias, $element); } $this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]] = $this->getLastKey( $this->_metadataMap[$oid] @@ -341,7 +346,7 @@ class Doctrine_ORM_Internal_Hydration_ObjectHydrator extends Doctrine_ORM_Intern $this->setRelatedElement($baseElement, $relationAlias, null); } else if ( ! $this->isFieldSet($baseElement, $relationAlias)) { $this->setRelatedElement($baseElement, $relationAlias, - $this->getElement($data, $entityName)); + $this->getEntity($data, $entityName)); } } diff --git a/lib/Doctrine/ORM/Internal/Hydration/ScalarHydrator.php b/lib/Doctrine/ORM/Internal/Hydration/ScalarHydrator.php index 6966604f2..088311ef5 100644 --- a/lib/Doctrine/ORM/Internal/Hydration/ScalarHydrator.php +++ b/lib/Doctrine/ORM/Internal/Hydration/ScalarHydrator.php @@ -11,7 +11,7 @@ class Doctrine_ORM_Internal_Hydration_ScalarHydrator extends Doctrine_ORM_Internal_Hydration_AbstractHydrator { /** @override */ - protected function _hydrateAll($parserResult) + protected function _hydrateAll() { $result = array(); $cache = array(); diff --git a/lib/Doctrine/ORM/Internal/Hydration/SingleScalarHydrator.php b/lib/Doctrine/ORM/Internal/Hydration/SingleScalarHydrator.php index 72870fb1e..27f468ce1 100644 --- a/lib/Doctrine/ORM/Internal/Hydration/SingleScalarHydrator.php +++ b/lib/Doctrine/ORM/Internal/Hydration/SingleScalarHydrator.php @@ -12,7 +12,7 @@ class Doctrine_ORM_Internal_Hydration_SingleScalarHydrator extends Doctrine_ORM_Internal_Hydration_AbstractHydrator { /** @override */ - protected function _hydrateAll($parserResult) + protected function _hydrateAll() { $cache = array(); $result = $this->_stmt->fetchAll(PDO::FETCH_ASSOC); diff --git a/lib/Doctrine/ORM/Internal/Hydration/StandardHydrator.php b/lib/Doctrine/ORM/Internal/Hydration/StandardHydrator.php index 4192fce72..88fd3554a 100644 --- a/lib/Doctrine/ORM/Internal/Hydration/StandardHydrator.php +++ b/lib/Doctrine/ORM/Internal/Hydration/StandardHydrator.php @@ -55,6 +55,7 @@ * @version $Revision: 3192 $ * @author Konsta Vesterinen * @author Roman Borschel + * @DEPRECATED */ class Doctrine_ORM_Internal_Hydration_StandardHydrator extends Doctrine_ORM_Internal_Hydration_AbstractHydrator { diff --git a/lib/Doctrine/ORM/Internal/Null.php b/lib/Doctrine/ORM/Internal/Null.php index c9799d2ee..0747f2161 100644 --- a/lib/Doctrine/ORM/Internal/Null.php +++ b/lib/Doctrine/ORM/Internal/Null.php @@ -40,6 +40,7 @@ * @version $Revision: 4723 $ * @author Konsta Vesterinen * @todo No longer needed? + * @DEPRECATED */ // static initializer Doctrine_ORM_Internal_Null::$INSTANCE = new Doctrine_ORM_Internal_Null(); diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadata.php b/lib/Doctrine/ORM/Mapping/ClassMetadata.php index 760d58e60..b87a92ef9 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadata.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadata.php @@ -1499,6 +1499,32 @@ class Doctrine_ORM_Mapping_ClassMetadata return isset($this->_associationMappings[$fieldName]); } + /** + * Checks whether the class has a mapped association for the specified field + * and if yes, checks whether it is a single-valued association (to-one). + * + * @param string $fieldName + * @return boolean TRUE if the association exists and is single-valued, FALSE otherwise. + */ + public function isSingleValuedAssociation($fieldName) + { + return isset($this->_associationMappings[$fieldName]) && + $this->_associationMappings[$fieldName]->isOneToOne(); + } + + /** + * Checks whether the class has a mapped association for the specified field + * and if yes, checks whether it is a collection-valued association (to-many). + * + * @param string $fieldName + * @return boolean TRUE if the association exists and is collection-valued, FALSE otherwise. + */ + public function isCollectionValuedAssociation($fieldName) + { + return isset($this->_associationMappings[$fieldName]) && + ! $this->_associationMappings[$fieldName]->isOneToOne(); + } + /** Creates a string representation of the instance. */ public function __toString() { diff --git a/lib/Doctrine/ORM/Query.php b/lib/Doctrine/ORM/Query.php index 28de235e2..976e470b4 100644 --- a/lib/Doctrine/ORM/Query.php +++ b/lib/Doctrine/ORM/Query.php @@ -304,10 +304,10 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract // Double the params if we are using limit-subquery algorithm // We always have an instance of Doctrine_ORM_Query_ParserResult on hands... - if ($this->_parserResult->isLimitSubqueryUsed() && + /*if ($this->_parserResult->isLimitSubqueryUsed() && $this->_entityManager->getConnection()->getAttribute(Doctrine::ATTR_DRIVER_NAME) !== 'mysql') { $params = array_merge($params, $params); - } + }*/ // Executing the query and returning statement return $executor->execute($this->_conn, $params); diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index e6e84653f..f58c33bbb 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -1113,7 +1113,6 @@ class Doctrine_ORM_UnitOfWork * @param Doctrine\ORM\Entity $entity * @param array $data * @param boolean $overrideLocalChanges - * @return void */ private function _mergeData($entity, array $data, $class, $overrideLocalChanges = false) { if ($overrideLocalChanges) { diff --git a/tests/Orm/Functional/BasicCRUDTest.php b/tests/Orm/Functional/BasicCRUDTest.php index 4e68dbc40..73351f350 100644 --- a/tests/Orm/Functional/BasicCRUDTest.php +++ b/tests/Orm/Functional/BasicCRUDTest.php @@ -50,7 +50,7 @@ class Orm_Functional_BasicCRUDTest extends Doctrine_OrmFunctionalTestCase { } public function testMore() { - echo PHP_EOL . "SECOND" . PHP_EOL; + #echo PHP_EOL . "SECOND" . PHP_EOL; /*$user = new CmsUser; $user->name = 'jon'; $user->*/ diff --git a/tests/Orm/Hydration/AllTests.php b/tests/Orm/Hydration/AllTests.php index 9cfc88116..431b57ba2 100644 --- a/tests/Orm/Hydration/AllTests.php +++ b/tests/Orm/Hydration/AllTests.php @@ -23,7 +23,6 @@ class Orm_Hydration_AllTests { $suite = new Doctrine_TestSuite('Doctrine Orm Hydration'); - //$suite->addTestSuite('Orm_Hydration_BasicHydrationTest'); $suite->addTestSuite('Orm_Hydration_ObjectHydratorTest'); $suite->addTestSuite('Orm_Hydration_ArrayHydratorTest'); $suite->addTestSuite('Orm_Hydration_ScalarHydratorTest'); diff --git a/tests/Orm/Hydration/ArrayHydratorTest.php b/tests/Orm/Hydration/ArrayHydratorTest.php index 5bdf952b2..6fc35a82b 100644 --- a/tests/Orm/Hydration/ArrayHydratorTest.php +++ b/tests/Orm/Hydration/ArrayHydratorTest.php @@ -46,7 +46,7 @@ class Orm_Hydration_ArrayHydratorTest extends Orm_Hydration_HydrationTest $hydrator = new Doctrine_ORM_Internal_Hydration_ArrayHydrator($this->_em); $result = $hydrator->hydrateAll($stmt, $this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, Doctrine_ORM_Query::HYDRATE_ARRAY)); + $queryComponents, $tableAliasMap)); $this->assertEquals(2, count($result)); $this->assertTrue(is_array($result)); @@ -115,7 +115,7 @@ class Orm_Hydration_ArrayHydratorTest extends Orm_Hydration_HydrationTest $hydrator = new Doctrine_ORM_Internal_Hydration_ArrayHydrator($this->_em); $result = $hydrator->hydrateAll($stmt, $this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, Doctrine_ORM_Query::HYDRATE_ARRAY, true)); + $queryComponents, $tableAliasMap, true)); $this->assertEquals(2, count($result)); $this->assertTrue(is_array($result)); @@ -185,7 +185,7 @@ class Orm_Hydration_ArrayHydratorTest extends Orm_Hydration_HydrationTest $hydrator = new Doctrine_ORM_Internal_Hydration_ArrayHydrator($this->_em); $result = $hydrator->hydrateAll($stmt, $this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, Doctrine_ORM_Query::HYDRATE_ARRAY, true)); + $queryComponents, $tableAliasMap, true)); $this->assertEquals(2, count($result)); $this->assertTrue(is_array($result)); @@ -257,7 +257,7 @@ class Orm_Hydration_ArrayHydratorTest extends Orm_Hydration_HydrationTest $hydrator = new Doctrine_ORM_Internal_Hydration_ArrayHydrator($this->_em); $result = $hydrator->hydrateAll($stmt, $this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, Doctrine_ORM_Query::HYDRATE_ARRAY, true)); + $queryComponents, $tableAliasMap, true)); $this->assertEquals(2, count($result)); $this->assertTrue(is_array($result)); @@ -377,7 +377,7 @@ class Orm_Hydration_ArrayHydratorTest extends Orm_Hydration_HydrationTest $hydrator = new Doctrine_ORM_Internal_Hydration_ArrayHydrator($this->_em); $result = $hydrator->hydrateAll($stmt, $this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, Doctrine_ORM_Query::HYDRATE_ARRAY, true)); + $queryComponents, $tableAliasMap, true)); $this->assertEquals(2, count($result)); $this->assertTrue(is_array($result)); @@ -525,7 +525,7 @@ class Orm_Hydration_ArrayHydratorTest extends Orm_Hydration_HydrationTest $hydrator = new Doctrine_ORM_Internal_Hydration_ArrayHydrator($this->_em); $result = $hydrator->hydrateAll($stmt, $this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, Doctrine_ORM_Query::HYDRATE_ARRAY, true)); + $queryComponents, $tableAliasMap, true)); $this->assertEquals(2, count($result)); $this->assertTrue(is_array($result)); @@ -647,7 +647,7 @@ class Orm_Hydration_ArrayHydratorTest extends Orm_Hydration_HydrationTest $hydrator = new Doctrine_ORM_Internal_Hydration_ArrayHydrator($this->_em); $result = $hydrator->hydrateAll($stmt, $this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, Doctrine_ORM_Query::HYDRATE_ARRAY)); + $queryComponents, $tableAliasMap)); $this->assertEquals(2, count($result)); $this->assertTrue(is_array($result)); @@ -692,7 +692,7 @@ class Orm_Hydration_ArrayHydratorTest extends Orm_Hydration_HydrationTest $hydrator = new Doctrine_ORM_Internal_Hydration_ArrayHydrator($this->_em); $iterableResult = $hydrator->iterate($stmt, $this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, Doctrine_ORM_Query::HYDRATE_ARRAY)); + $queryComponents, $tableAliasMap)); $rowNum = 0; while (($row = $iterableResult->next()) !== false) { diff --git a/tests/Orm/Hydration/BasicHydrationTest.php b/tests/Orm/Hydration/BasicHydrationTest.php deleted file mode 100644 index 472ce14e2..000000000 --- a/tests/Orm/Hydration/BasicHydrationTest.php +++ /dev/null @@ -1,1038 +0,0 @@ -_em = $this->_getTestEntityManager(); - } - - /** Getter for the hydration mode dataProvider */ - public static function hydrationModeProvider() - { - return array( - array('hydrationMode' => Doctrine_ORM_Query::HYDRATE_OBJECT), - array('hydrationMode' => Doctrine_ORM_Query::HYDRATE_ARRAY), - array('hydrationMode' => Doctrine_ORM_Query::HYDRATE_SCALAR) - ); - } - - /** Helper method */ - private function _createParserResult($stmt, $queryComponents, $tableToClassAliasMap, - $hydrationMode, $isMixedQuery = false) - { - $parserResult = new Doctrine_ORM_Query_ParserResultDummy(); - $parserResult->setDatabaseStatement($stmt); - $parserResult->setHydrationMode($hydrationMode); - $parserResult->setQueryComponents($queryComponents); - $parserResult->setTableToClassAliasMap($tableToClassAliasMap); - $parserResult->setMixedQuery($isMixedQuery); - return $parserResult; - } - - /** - * Select u.id, u.name from CmsUser u - * - * @dataProvider hydrationModeProvider - */ - public function testNewHydrationSimpleEntityQuery($hydrationMode) - { - // Faked query components - $queryComponents = array( - 'u' => array( - 'metadata' => $this->_em->getClassMetadata('CmsUser'), - 'parent' => null, - 'relation' => null, - 'map' => null - ) - ); - - // Faked table alias map - $tableAliasMap = array( - 'u' => 'u' - ); - - // Faked result set - $resultSet = array( - array( - 'u__id' => '1', - 'u__name' => 'romanb' - ), - array( - 'u__id' => '2', - 'u__name' => 'jwage' - ) - ); - - - $stmt = new Doctrine_HydratorMockStatement($resultSet); - $hydrator = new Doctrine_ORM_Internal_Hydration_StandardHydrator($this->_em); - - $result = $hydrator->hydrateResultSet($this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, $hydrationMode)); - - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY || $hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) { - $this->assertEquals(2, count($result)); - } - - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) { - $this->assertTrue($result instanceof Doctrine_ORM_Collection); - $this->assertTrue($result[0] instanceof CmsUser); - $this->assertTrue($result[1] instanceof CmsUser); - $this->assertEquals(1, $result[0]->id); - $this->assertEquals('romanb', $result[0]->name); - $this->assertEquals(2, $result[1]->id); - $this->assertEquals('jwage', $result[1]->name); - } else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) { - $this->assertTrue(is_array($result)); - $this->assertEquals(1, $result[0]['id']); - $this->assertEquals('romanb', $result[0]['name']); - $this->assertEquals(2, $result[1]['id']); - $this->assertEquals('jwage', $result[1]['name']); - } else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_SCALAR) { - $this->assertTrue(is_array($result)); - $this->assertEquals(2, count($result)); - $this->assertEquals('romanb', $result[0]['u_name']); - $this->assertEquals(1, $result[0]['u_id']); - $this->assertEquals('jwage', $result[1]['u_name']); - $this->assertEquals(2, $result[1]['u_id']); - } - } - - /** - * select u.id, u.status, p.phonenumber, upper(u.name) nameUpper from User u - * join u.phonenumbers p - * = - * select u.id, u.status, p.phonenumber, upper(u.name) as u__0 from USERS u - * INNER JOIN PHONENUMBERS p ON u.id = p.user_id - * - * @dataProvider hydrationModeProvider - */ - public function testNewHydrationMixedQueryFetchJoin($hydrationMode) - { - // Faked query components - $queryComponents = array( - 'u' => array( - 'metadata' => $this->_em->getClassMetadata('CmsUser'), - 'parent' => null, - 'relation' => null, - 'map' => null, - 'agg' => array('0' => 'nameUpper') - ), - 'p' => array( - 'metadata' => $this->_em->getClassMetadata('CmsPhonenumber'), - 'parent' => 'u', - 'relation' => $this->_em->getClassMetadata('CmsUser')->getAssociationMapping('phonenumbers'), - 'map' => null - ) - ); - - // Faked table alias map - $tableAliasMap = array( - 'u' => 'u', - 'p' => 'p' - ); - - // Faked result set - $resultSet = array( - //row1 - array( - 'u__id' => '1', - 'u__status' => 'developer', - 'u__0' => 'ROMANB', - 'p__phonenumber' => '42', - ), - array( - 'u__id' => '1', - 'u__status' => 'developer', - 'u__0' => 'ROMANB', - 'p__phonenumber' => '43', - ), - array( - 'u__id' => '2', - 'u__status' => 'developer', - 'u__0' => 'JWAGE', - 'p__phonenumber' => '91' - ) - ); - - $stmt = new Doctrine_HydratorMockStatement($resultSet); - $hydrator = new Doctrine_ORM_Internal_Hydration_StandardHydrator($this->_em); - - $result = $hydrator->hydrateResultSet($this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, $hydrationMode, true)); - - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) { - //var_dump($result); - } - - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY || $hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) { - $this->assertEquals(2, count($result)); - $this->assertTrue(is_array($result)); - $this->assertTrue(is_array($result[0])); - $this->assertTrue(is_array($result[1])); - } - - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) { - $this->assertTrue($result[0][0] instanceof CmsUser); - $this->assertTrue($result[0][0]->phonenumbers instanceof Doctrine_ORM_Collection); - $this->assertTrue($result[0][0]->phonenumbers[0] instanceof CmsPhonenumber); - $this->assertTrue($result[0][0]->phonenumbers[1] instanceof CmsPhonenumber); - $this->assertTrue($result[1][0] instanceof CmsUser); - $this->assertTrue($result[1][0]->phonenumbers instanceof Doctrine_ORM_Collection); - - // first user => 2 phonenumbers - $this->assertEquals(2, count($result[0][0]->phonenumbers)); - $this->assertEquals('ROMANB', $result[0]['nameUpper']); - // second user => 1 phonenumber - $this->assertEquals(1, count($result[1][0]->phonenumbers)); - $this->assertEquals('JWAGE', $result[1]['nameUpper']); - - $this->assertEquals(42, $result[0][0]->phonenumbers[0]->phonenumber); - $this->assertEquals(43, $result[0][0]->phonenumbers[1]->phonenumber); - $this->assertEquals(91, $result[1][0]->phonenumbers[0]->phonenumber); - } else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) { - // first user => 2 phonenumbers - $this->assertEquals(2, count($result[0][0]['phonenumbers'])); - $this->assertEquals('ROMANB', $result[0]['nameUpper']); - // second user => 1 phonenumber - $this->assertEquals(1, count($result[1][0]['phonenumbers'])); - $this->assertEquals('JWAGE', $result[1]['nameUpper']); - - $this->assertEquals(42, $result[0][0]['phonenumbers'][0]['phonenumber']); - $this->assertEquals(43, $result[0][0]['phonenumbers'][1]['phonenumber']); - $this->assertEquals(91, $result[1][0]['phonenumbers'][0]['phonenumber']); - } else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_SCALAR) { - $this->assertTrue(is_array($result)); - $this->assertEquals(3, count($result)); - $this->assertEquals(1, $result[0]['u_id']); - $this->assertEquals('developer', $result[0]['u_status']); - $this->assertEquals('ROMANB', $result[0]['u_nameUpper']); - $this->assertEquals(42, $result[0]['p_phonenumber']); - - // ... more checks to come - } - } - - /** - * select u.id, u.status, count(p.phonenumber) numPhones from User u - * join u.phonenumbers p group by u.status, u.id - * = - * select u.id, u.status, count(p.phonenumber) as p__0 from USERS u - * INNER JOIN PHONENUMBERS p ON u.id = p.user_id group by u.id, u.status - * - * @dataProvider hydrationModeProvider - */ - public function testNewHydrationMixedQueryNormalJoin($hydrationMode) - { - // Faked query components - $queryComponents = array( - 'u' => array( - 'metadata' => $this->_em->getClassMetadata('CmsUser'), - 'parent' => null, - 'relation' => null, - 'map' => null - ), - 'p' => array( - 'metadata' => $this->_em->getClassMetadata('CmsPhonenumber'), - 'parent' => 'u', - 'relation' => $this->_em->getClassMetadata('CmsUser')->getAssociationMapping('phonenumbers'), - 'map' => null, - 'agg' => array('0' => 'numPhones') - ) - ); - - // Faked table alias map - $tableAliasMap = array( - 'u' => 'u', - 'p' => 'p' - ); - - // Faked result set - $resultSet = array( - //row1 - array( - 'u__id' => '1', - 'u__status' => 'developer', - 'p__0' => '2', - ), - array( - 'u__id' => '2', - 'u__status' => 'developer', - 'p__0' => '1', - ) - ); - - $stmt = new Doctrine_HydratorMockStatement($resultSet); - $hydrator = new Doctrine_ORM_Internal_Hydration_StandardHydrator($this->_em); - - $result = $hydrator->hydrateResultSet($this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, $hydrationMode, true)); - //var_dump($result); - - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY || $hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) { - $this->assertEquals(2, count($result)); - $this->assertTrue(is_array($result)); - $this->assertTrue(is_array($result[0])); - $this->assertTrue(is_array($result[1])); - // first user => 2 phonenumbers - $this->assertEquals(2, $result[0]['numPhones']); - // second user => 1 phonenumber - $this->assertEquals(1, $result[1]['numPhones']); - } - - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) { - $this->assertTrue($result[0][0] instanceof CmsUser); - $this->assertTrue($result[1][0] instanceof CmsUser); - } else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_SCALAR) { - $this->assertEquals(2, count($result)); - - $this->assertEquals(1, $result[0]['u_id']); - $this->assertEquals('developer', $result[0]['u_status']); - $this->assertEquals(2, $result[0]['p_numPhones']); - - $this->assertEquals(2, $result[1]['u_id']); - $this->assertEquals('developer', $result[1]['u_status']); - $this->assertEquals(1, $result[1]['p_numPhones']); - } - } - - /** - * select u.id, u.status, upper(u.name) nameUpper from User u index by u.id - * join u.phonenumbers p indexby p.phonenumber - * = - * select u.id, u.status, upper(u.name) as p__0 from USERS u - * INNER JOIN PHONENUMBERS p ON u.id = p.user_id - * - * @dataProvider hydrationModeProvider - */ - public function testNewHydrationMixedQueryFetchJoinCustomIndex($hydrationMode) - { - // Faked query components - $queryComponents = array( - 'u' => array( - 'metadata' => $this->_em->getClassMetadata('CmsUser'), - 'parent' => null, - 'relation' => null, - 'agg' => array('0' => 'nameUpper'), - 'map' => 'id' - ), - 'p' => array( - 'metadata' => $this->_em->getClassMetadata('CmsPhonenumber'), - 'parent' => 'u', - 'relation' => $this->_em->getClassMetadata('CmsUser')->getAssociationMapping('phonenumbers'), - 'map' => 'phonenumber' - ) - ); - - // Faked table alias map - $tableAliasMap = array( - 'u' => 'u', - 'p' => 'p' - ); - - // Faked result set - $resultSet = array( - //row1 - array( - 'u__id' => '1', - 'u__status' => 'developer', - 'u__0' => 'ROMANB', - 'p__phonenumber' => '42', - ), - array( - 'u__id' => '1', - 'u__status' => 'developer', - 'u__0' => 'ROMANB', - 'p__phonenumber' => '43', - ), - array( - 'u__id' => '2', - 'u__status' => 'developer', - 'u__0' => 'JWAGE', - 'p__phonenumber' => '91' - ) - ); - - - $stmt = new Doctrine_HydratorMockStatement($resultSet); - $hydrator = new Doctrine_ORM_Internal_Hydration_StandardHydrator($this->_em); - - $result = $hydrator->hydrateResultSet($this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, $hydrationMode, true)); - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) { - //var_dump($result); - } - - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY || $hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) { - $this->assertEquals(2, count($result)); - $this->assertTrue(is_array($result)); - $this->assertTrue(is_array($result[0])); - $this->assertTrue(is_array($result[1])); - - // test the scalar values - $this->assertEquals('ROMANB', $result[0]['nameUpper']); - $this->assertEquals('JWAGE', $result[1]['nameUpper']); - } - - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) { - $this->assertTrue($result[0]['1'] instanceof CmsUser); - $this->assertTrue($result[1]['2'] instanceof CmsUser); - $this->assertTrue($result[0]['1']->phonenumbers instanceof Doctrine_ORM_Collection); - // first user => 2 phonenumbers. notice the custom indexing by user id - $this->assertEquals(2, count($result[0]['1']->phonenumbers)); - // second user => 1 phonenumber. notice the custom indexing by user id - $this->assertEquals(1, count($result[1]['2']->phonenumbers)); - // test the custom indexing of the phonenumbers - $this->assertTrue(isset($result[0]['1']->phonenumbers['42'])); - $this->assertTrue(isset($result[0]['1']->phonenumbers['43'])); - $this->assertTrue(isset($result[1]['2']->phonenumbers['91'])); - } else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) { - // first user => 2 phonenumbers. notice the custom indexing by user id - $this->assertEquals(2, count($result[0]['1']['phonenumbers'])); - // second user => 1 phonenumber. notice the custom indexing by user id - $this->assertEquals(1, count($result[1]['2']['phonenumbers'])); - // test the custom indexing of the phonenumbers - $this->assertTrue(isset($result[0]['1']['phonenumbers']['42'])); - $this->assertTrue(isset($result[0]['1']['phonenumbers']['43'])); - $this->assertTrue(isset($result[1]['2']['phonenumbers']['91'])); - } else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_SCALAR) { - // NOTE: Indexing has no effect with HYDRATE_SCALAR - //... asserts to come - } - } - - - /** - * select u.id, u.status, p.phonenumber, upper(u.name) nameUpper, a.id, a.topic - * from User u - * join u.phonenumbers p - * join u.articles a - * = - * select u.id, u.status, p.phonenumber, upper(u.name) as u__0, a.id, a.topic - * from USERS u - * inner join PHONENUMBERS p ON u.id = p.user_id - * inner join ARTICLES a ON u.id = a.user_id - * - * @dataProvider hydrationModeProvider - */ - public function testNewHydrationMixedQueryMultipleFetchJoin($hydrationMode) - { - // Faked query components - $queryComponents = array( - 'u' => array( - 'metadata' => $this->_em->getClassMetadata('CmsUser'), - 'parent' => null, - 'relation' => null, - 'map' => null, - 'agg' => array('0' => 'nameUpper') - ), - 'p' => array( - 'metadata' => $this->_em->getClassMetadata('CmsPhonenumber'), - 'parent' => 'u', - 'relation' => $this->_em->getClassMetadata('CmsUser')->getAssociationMapping('phonenumbers'), - 'map' => null - ), - 'a' => array( - 'metadata' => $this->_em->getClassMetadata('CmsArticle'), - 'parent' => 'u', - 'relation' => $this->_em->getClassMetadata('CmsUser')->getAssociationMapping('articles'), - 'map' => null - ), - ); - - // Faked table alias map - $tableAliasMap = array( - 'u' => 'u', - 'p' => 'p', - 'a' => 'a' - ); - - // Faked result set - $resultSet = array( - //row1 - array( - 'u__id' => '1', - 'u__status' => 'developer', - 'u__0' => 'ROMANB', - 'p__phonenumber' => '42', - 'a__id' => '1', - 'a__topic' => 'Getting things done!' - ), - array( - 'u__id' => '1', - 'u__status' => 'developer', - 'u__0' => 'ROMANB', - 'p__phonenumber' => '43', - 'a__id' => '1', - 'a__topic' => 'Getting things done!' - ), - array( - 'u__id' => '1', - 'u__status' => 'developer', - 'u__0' => 'ROMANB', - 'p__phonenumber' => '42', - 'a__id' => '2', - 'a__topic' => 'ZendCon' - ), - array( - 'u__id' => '1', - 'u__status' => 'developer', - 'u__0' => 'ROMANB', - 'p__phonenumber' => '43', - 'a__id' => '2', - 'a__topic' => 'ZendCon' - ), - array( - 'u__id' => '2', - 'u__status' => 'developer', - 'u__0' => 'JWAGE', - 'p__phonenumber' => '91', - 'a__id' => '3', - 'a__topic' => 'LINQ' - ), - array( - 'u__id' => '2', - 'u__status' => 'developer', - 'u__0' => 'JWAGE', - 'p__phonenumber' => '91', - 'a__id' => '4', - 'a__topic' => 'PHP6' - ), - ); - - $stmt = new Doctrine_HydratorMockStatement($resultSet); - $hydrator = new Doctrine_ORM_Internal_Hydration_StandardHydrator($this->_em); - - $result = $hydrator->hydrateResultSet($this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, $hydrationMode, true)); - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) { - //var_dump($result); - } - - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY || $hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) { - $this->assertEquals(2, count($result)); - $this->assertTrue(is_array($result)); - $this->assertTrue(is_array($result[0])); - $this->assertTrue(is_array($result[1])); - } - - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) { - $this->assertTrue($result[0][0] instanceof CmsUser); - $this->assertTrue($result[0][0]->phonenumbers instanceof Doctrine_ORM_Collection); - $this->assertTrue($result[0][0]->phonenumbers[0] instanceof CmsPhonenumber); - $this->assertTrue($result[0][0]->phonenumbers[1] instanceof CmsPhonenumber); - $this->assertTrue($result[0][0]->articles instanceof Doctrine_ORM_Collection); - $this->assertTrue($result[0][0]->articles[0] instanceof CmsArticle); - $this->assertTrue($result[0][0]->articles[1] instanceof CmsArticle); - $this->assertTrue($result[1][0] instanceof CmsUser); - $this->assertTrue($result[1][0]->phonenumbers instanceof Doctrine_ORM_Collection); - $this->assertTrue($result[1][0]->phonenumbers[0] instanceof CmsPhonenumber); - $this->assertTrue($result[1][0]->articles[0] instanceof CmsArticle); - $this->assertTrue($result[1][0]->articles[1] instanceof CmsArticle); - } else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) { - // first user => 2 phonenumbers, 2 articles - $this->assertEquals(2, count($result[0][0]['phonenumbers'])); - $this->assertEquals(2, count($result[0][0]['articles'])); - $this->assertEquals('ROMANB', $result[0]['nameUpper']); - // second user => 1 phonenumber, 2 articles - $this->assertEquals(1, count($result[1][0]['phonenumbers'])); - $this->assertEquals(2, count($result[1][0]['articles'])); - $this->assertEquals('JWAGE', $result[1]['nameUpper']); - - $this->assertEquals(42, $result[0][0]['phonenumbers'][0]['phonenumber']); - $this->assertEquals(43, $result[0][0]['phonenumbers'][1]['phonenumber']); - $this->assertEquals(91, $result[1][0]['phonenumbers'][0]['phonenumber']); - - $this->assertEquals('Getting things done!', $result[0][0]['articles'][0]['topic']); - $this->assertEquals('ZendCon', $result[0][0]['articles'][1]['topic']); - $this->assertEquals('LINQ', $result[1][0]['articles'][0]['topic']); - $this->assertEquals('PHP6', $result[1][0]['articles'][1]['topic']); - } else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_SCALAR) { - //... - $this->assertEquals(6, count($result)); - //var_dump($result); - } - } - - /** - * select u.id, u.status, p.phonenumber, upper(u.name) nameUpper, a.id, a.topic, - * c.id, c.topic - * from User u - * join u.phonenumbers p - * join u.articles a - * left join a.comments c - * = - * select u.id, u.status, p.phonenumber, upper(u.name) as u__0, a.id, a.topic, - * c.id, c.topic - * from USERS u - * inner join PHONENUMBERS p ON u.id = p.user_id - * inner join ARTICLES a ON u.id = a.user_id - * left outer join COMMENTS c ON a.id = c.article_id - * - * @dataProvider hydrationModeProvider - */ - public function testNewHydrationMixedQueryMultipleDeepMixedFetchJoin($hydrationMode) - { - // Faked query components - $queryComponents = array( - 'u' => array( - 'metadata' => $this->_em->getClassMetadata('CmsUser'), - 'parent' => null, - 'relation' => null, - 'map' => null, - 'agg' => array('0' => 'nameUpper') - ), - 'p' => array( - 'metadata' => $this->_em->getClassMetadata('CmsPhonenumber'), - 'parent' => 'u', - 'relation' => $this->_em->getClassMetadata('CmsUser')->getAssociationMapping('phonenumbers'), - 'map' => null - ), - 'a' => array( - 'metadata' => $this->_em->getClassMetadata('CmsArticle'), - 'parent' => 'u', - 'relation' => $this->_em->getClassMetadata('CmsUser')->getAssociationMapping('articles'), - 'map' => null - ), - 'c' => array( - 'metadata' => $this->_em->getClassMetadata('CmsComment'), - 'parent' => 'a', - 'relation' => $this->_em->getClassMetadata('CmsArticle')->getAssociationMapping('comments'), - 'map' => null - ), - ); - - // Faked table alias map - $tableAliasMap = array( - 'u' => 'u', - 'p' => 'p', - 'a' => 'a', - 'c' => 'c' - ); - - // Faked result set - $resultSet = array( - //row1 - array( - 'u__id' => '1', - 'u__status' => 'developer', - 'u__0' => 'ROMANB', - 'p__phonenumber' => '42', - 'a__id' => '1', - 'a__topic' => 'Getting things done!', - 'c__id' => '1', - 'c__topic' => 'First!' - ), - array( - 'u__id' => '1', - 'u__status' => 'developer', - 'u__0' => 'ROMANB', - 'p__phonenumber' => '43', - 'a__id' => '1', - 'a__topic' => 'Getting things done!', - 'c__id' => '1', - 'c__topic' => 'First!' - ), - array( - 'u__id' => '1', - 'u__status' => 'developer', - 'u__0' => 'ROMANB', - 'p__phonenumber' => '42', - 'a__id' => '2', - 'a__topic' => 'ZendCon', - 'c__id' => null, - 'c__topic' => null - ), - array( - 'u__id' => '1', - 'u__status' => 'developer', - 'u__0' => 'ROMANB', - 'p__phonenumber' => '43', - 'a__id' => '2', - 'a__topic' => 'ZendCon', - 'c__id' => null, - 'c__topic' => null - ), - array( - 'u__id' => '2', - 'u__status' => 'developer', - 'u__0' => 'JWAGE', - 'p__phonenumber' => '91', - 'a__id' => '3', - 'a__topic' => 'LINQ', - 'c__id' => null, - 'c__topic' => null - ), - array( - 'u__id' => '2', - 'u__status' => 'developer', - 'u__0' => 'JWAGE', - 'p__phonenumber' => '91', - 'a__id' => '4', - 'a__topic' => 'PHP6', - 'c__id' => null, - 'c__topic' => null - ), - ); - - $stmt = new Doctrine_HydratorMockStatement($resultSet); - $hydrator = new Doctrine_ORM_Internal_Hydration_StandardHydrator($this->_em); - - $result = $hydrator->hydrateResultSet($this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, $hydrationMode, true)); - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) { - //var_dump($result); - } - - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY || $hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) { - $this->assertEquals(2, count($result)); - $this->assertTrue(is_array($result)); - $this->assertTrue(is_array($result[0])); - $this->assertTrue(is_array($result[1])); - } - - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) { - $this->assertTrue($result[0][0] instanceof CmsUser); - $this->assertTrue($result[1][0] instanceof CmsUser); - // phonenumbers - $this->assertTrue($result[0][0]->phonenumbers instanceof Doctrine_ORM_Collection); - $this->assertTrue($result[0][0]->phonenumbers[0] instanceof CmsPhonenumber); - $this->assertTrue($result[0][0]->phonenumbers[1] instanceof CmsPhonenumber); - $this->assertTrue($result[1][0]->phonenumbers instanceof Doctrine_ORM_Collection); - $this->assertTrue($result[1][0]->phonenumbers[0] instanceof CmsPhonenumber); - // articles - $this->assertTrue($result[0][0]->articles instanceof Doctrine_ORM_Collection); - $this->assertTrue($result[0][0]->articles[0] instanceof CmsArticle); - $this->assertTrue($result[0][0]->articles[1] instanceof CmsArticle); - $this->assertTrue($result[1][0]->articles[0] instanceof CmsArticle); - $this->assertTrue($result[1][0]->articles[1] instanceof CmsArticle); - // article comments - $this->assertTrue($result[0][0]->articles[0]->comments instanceof Doctrine_ORM_Collection); - $this->assertTrue($result[0][0]->articles[0]->comments[0] instanceof CmsComment); - // empty comment collections - $this->assertTrue($result[0][0]->articles[1]->comments instanceof Doctrine_ORM_Collection); - $this->assertEquals(0, count($result[0][0]->articles[1]->comments)); - $this->assertTrue($result[1][0]->articles[0]->comments instanceof Doctrine_ORM_Collection); - $this->assertEquals(0, count($result[1][0]->articles[0]->comments)); - $this->assertTrue($result[1][0]->articles[1]->comments instanceof Doctrine_ORM_Collection); - $this->assertEquals(0, count($result[1][0]->articles[1]->comments)); - } else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_SCALAR) { - //... - } else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) { - // first user => 2 phonenumbers, 2 articles, 1 comment on first article - $this->assertEquals(2, count($result[0][0]['phonenumbers'])); - $this->assertEquals(2, count($result[0][0]['articles'])); - $this->assertEquals(1, count($result[0][0]['articles'][0]['comments'])); - $this->assertEquals('ROMANB', $result[0]['nameUpper']); - // second user => 1 phonenumber, 2 articles, no comments - $this->assertEquals(1, count($result[1][0]['phonenumbers'])); - $this->assertEquals(2, count($result[1][0]['articles'])); - $this->assertEquals('JWAGE', $result[1]['nameUpper']); - - $this->assertEquals(42, $result[0][0]['phonenumbers'][0]['phonenumber']); - $this->assertEquals(43, $result[0][0]['phonenumbers'][1]['phonenumber']); - $this->assertEquals(91, $result[1][0]['phonenumbers'][0]['phonenumber']); - - $this->assertEquals('Getting things done!', $result[0][0]['articles'][0]['topic']); - $this->assertEquals('ZendCon', $result[0][0]['articles'][1]['topic']); - $this->assertEquals('LINQ', $result[1][0]['articles'][0]['topic']); - $this->assertEquals('PHP6', $result[1][0]['articles'][1]['topic']); - - $this->assertEquals('First!', $result[0][0]['articles'][0]['comments'][0]['topic']); - - $this->assertTrue(isset($result[0][0]['articles'][0]['comments'])); - - // empty comment collections - $this->assertTrue(is_array($result[0][0]['articles'][1]['comments'])); - $this->assertEquals(0, count($result[0][0]['articles'][1]['comments'])); - $this->assertTrue(is_array($result[1][0]['articles'][0]['comments'])); - $this->assertEquals(0, count($result[1][0]['articles'][0]['comments'])); - $this->assertTrue(is_array($result[1][0]['articles'][1]['comments'])); - $this->assertEquals(0, count($result[1][0]['articles'][1]['comments'])); - } - } - - - /** - * Tests that the hydrator does not rely on a particular order of the rows - * in the result set. - * - * DQL: - * select c.id, c.position, c.name, b.id, b.position - * from ForumCategory c inner join c.boards b - * order by c.position asc, b.position asc - * - * Checks whether the boards are correctly assigned to the categories. - * - * The 'evil' result set that confuses the object population is displayed below. - * - * c.id | c.position | c.name | boardPos | b.id | b.category_id (just for clarity) - * 1 | 0 | First | 0 | 1 | 1 - * 2 | 0 | Second | 0 | 2 | 2 <-- - * 1 | 0 | First | 1 | 3 | 1 - * 1 | 0 | First | 2 | 4 | 1 - * - * @dataProvider hydrationModeProvider - */ - public function testNewHydrationEntityQueryCustomResultSetOrder($hydrationMode) - { - // Faked query components - $queryComponents = array( - 'c' => array( - 'metadata' => $this->_em->getClassMetadata('ForumCategory'), - 'parent' => null, - 'relation' => null, - 'map' => null - ), - 'b' => array( - 'metadata' => $this->_em->getClassMetadata('ForumBoard'), - 'parent' => 'c', - 'relation' => $this->_em->getClassMetadata('ForumCategory')->getAssociationMapping('boards'), - 'map' => null - ), - ); - - // Faked table alias map - $tableAliasMap = array( - 'c' => 'c', - 'b' => 'b' - ); - - // Faked result set - $resultSet = array( - array( - 'c__id' => '1', - 'c__position' => '0', - 'c__name' => 'First', - 'b__id' => '1', - 'b__position' => '0', - //'b__category_id' => '1' - ), - array( - 'c__id' => '2', - 'c__position' => '0', - 'c__name' => 'Second', - 'b__id' => '2', - 'b__position' => '0', - //'b__category_id' => '2' - ), - array( - 'c__id' => '1', - 'c__position' => '0', - 'c__name' => 'First', - 'b__id' => '3', - 'b__position' => '1', - //'b__category_id' => '1' - ), - array( - 'c__id' => '1', - 'c__position' => '0', - 'c__name' => 'First', - 'b__id' => '4', - 'b__position' => '2', - //'b__category_id' => '1' - ) - ); - - $stmt = new Doctrine_HydratorMockStatement($resultSet); - $hydrator = new Doctrine_ORM_Internal_Hydration_StandardHydrator($this->_em); - - $result = $hydrator->hydrateResultSet($this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, $hydrationMode)); - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) { - //var_dump($result); - } - - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY || $hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) { - $this->assertEquals(2, count($result)); - } - - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) { - $this->assertTrue(is_array($result)); - $this->assertTrue(is_array($result[0])); - $this->assertTrue(is_array($result[1])); - $this->assertTrue(isset($result[0]['boards'])); - $this->assertEquals(3, count($result[0]['boards'])); - $this->assertTrue(isset($result[1]['boards'])); - $this->assertEquals(1, count($result[1]['boards'])); - } else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) { - $this->assertTrue($result instanceof Doctrine_ORM_Collection); - $this->assertTrue($result[0] instanceof ForumCategory); - $this->assertTrue($result[1] instanceof ForumCategory); - $this->assertEquals(1, $result[0]->getId()); - $this->assertEquals(2, $result[1]->getId()); - $this->assertTrue(isset($result[0]->boards)); - $this->assertEquals(3, count($result[0]->boards)); - $this->assertTrue(isset($result[1]->boards)); - $this->assertEquals(1, count($result[1]->boards)); - - } else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_SCALAR) { - //... - } - - } - - /** Result set provider for the HYDRATE_SINGLE_SCALAR tests */ - public static function singleScalarResultSetProvider() { - return array( - // valid - array('name' => 'result1', - 'resultSet' => array( - array( - 'u__name' => 'romanb' - ) - )), - // valid - array('name' => 'result2', - 'resultSet' => array( - array( - 'u__id' => '1' - ) - )), - // invalid - array('name' => 'result3', - 'resultSet' => array( - array( - 'u__id' => '1', - 'u__name' => 'romanb' - ) - )), - // invalid - array('name' => 'result4', - 'resultSet' => array( - array( - 'u__id' => '1' - ), - array( - 'u__id' => '2' - ) - )), - ); - } - - /** - * select u.name from CmsUser u where u.id = 1 - * - * @dataProvider singleScalarResultSetProvider - */ - public function testHydrateSingleScalar($name, $resultSet) - { - // Faked query components - $queryComponents = array( - 'u' => array( - 'metadata' => $this->_em->getClassMetadata('CmsUser'), - 'parent' => null, - 'relation' => null, - 'map' => null - ) - ); - - // Faked table alias map - $tableAliasMap = array( - 'u' => 'u' - ); - - $stmt = new Doctrine_HydratorMockStatement($resultSet); - $hydrator = new Doctrine_ORM_Internal_Hydration_StandardHydrator($this->_em); - - if ($name == 'result1') { - $result = $hydrator->hydrateResultSet($this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, Doctrine_ORM_Query::HYDRATE_SINGLE_SCALAR)); - $this->assertEquals('romanb', $result); - } else if ($name == 'result2') { - $result = $hydrator->hydrateResultSet($this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, Doctrine_ORM_Query::HYDRATE_SINGLE_SCALAR)); - $this->assertEquals(1, $result); - } else if ($name == 'result3' || $name == 'result4') { - try { - $result = $hydrator->hydrateResultSet($this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, Doctrine_ORM_Query::HYDRATE_SINGLE_SCALAR)); - $this->fail(); - } catch (Doctrine_ORM_Exceptions_HydrationException $ex) {} - } - - } - - - /** - * select u.id, u.status, p.phonenumber, upper(u.name) nameUpper from User u - * join u.phonenumbers p - * = - * select u.id, u.status, p.phonenumber, upper(u.name) as u__0 from USERS u - * INNER JOIN PHONENUMBERS p ON u.id = p.user_id - * - * @dataProvider hydrationModeProvider - */ - /*public function testNewHydrationMixedQueryFetchJoinPerformance($hydrationMode) - { - // Faked query components - $queryComponents = array( - 'u' => array( - 'metadata' => $this->_em->getClassMetadata('CmsUser'), - 'parent' => null, - 'relation' => null, - 'map' => null, - 'agg' => array('0' => 'nameUpper') - ), - 'p' => array( - 'metadata' => $this->_em->getClassMetadata('CmsPhonenumber'), - 'parent' => 'u', - 'relation' => $this->_em->getClassMetadata('CmsUser')->getAssociationMapping('phonenumbers'), - 'map' => null - ) - ); - - // Faked table alias map - $tableAliasMap = array( - 'u' => 'u', - 'p' => 'p' - ); - - // Faked result set - $resultSet = array( - //row1 - array( - 'u__id' => '1', - 'u__status' => 'developer', - 'u__0' => 'ROMANB', - 'p__phonenumber' => '42', - ), - array( - 'u__id' => '1', - 'u__status' => 'developer', - 'u__0' => 'ROMANB', - 'p__phonenumber' => '43', - ), - array( - 'u__id' => '2', - 'u__status' => 'developer', - 'u__0' => 'JWAGE', - 'p__phonenumber' => '91' - ) - ); - for ($i=4; $i<5000; $i++) { - $resultSet[] = array( - 'u__id' => $i, - 'u__status' => 'developer', - 'u__0' => 'JWAGE' . $i, - 'p__phonenumber' => '91' - ); - } - - $stmt = new Doctrine_HydratorMockStatement($resultSet); - $hydrator = new Doctrine_ORM_Internal_Hydration_StandardHydrator($this->_em); - - $result = $hydrator->hydrateResultSet($this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, $hydrationMode, true)); - }*/ - -} diff --git a/tests/Orm/Hydration/HydrationTest.php b/tests/Orm/Hydration/HydrationTest.php index 5f95bd31f..b770df679 100644 --- a/tests/Orm/Hydration/HydrationTest.php +++ b/tests/Orm/Hydration/HydrationTest.php @@ -19,12 +19,9 @@ class Orm_Hydration_HydrationTest extends Doctrine_OrmTestCase } /** Helper method */ - protected function _createParserResult($stmt, $queryComponents, $tableToClassAliasMap, - $hydrationMode, $isMixedQuery = false) + protected function _createParserResult($queryComponents, $tableToClassAliasMap, $isMixedQuery = false) { $parserResult = new Doctrine_ORM_Query_ParserResultDummy(); - $parserResult->setDatabaseStatement($stmt); - $parserResult->setHydrationMode($hydrationMode); $parserResult->setQueryComponents($queryComponents); $parserResult->setTableToClassAliasMap($tableToClassAliasMap); $parserResult->setMixedQuery($isMixedQuery); diff --git a/tests/Orm/Hydration/ObjectHydratorTest.php b/tests/Orm/Hydration/ObjectHydratorTest.php index 84d7cce64..899dbfcc2 100644 --- a/tests/Orm/Hydration/ObjectHydratorTest.php +++ b/tests/Orm/Hydration/ObjectHydratorTest.php @@ -46,7 +46,7 @@ class Orm_Hydration_ObjectHydratorTest extends Orm_Hydration_HydrationTest $hydrator = new Doctrine_ORM_Internal_Hydration_ObjectHydrator($this->_em); $result = $hydrator->hydrateAll($stmt, $this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, Doctrine_ORM_Query::HYDRATE_OBJECT)); + $queryComponents, $tableAliasMap)); $this->assertEquals(2, count($result)); $this->assertTrue($result instanceof Doctrine_ORM_Collection); @@ -117,7 +117,7 @@ class Orm_Hydration_ObjectHydratorTest extends Orm_Hydration_HydrationTest $hydrator = new Doctrine_ORM_Internal_Hydration_ObjectHydrator($this->_em); $result = $hydrator->hydrateAll($stmt, $this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, Doctrine_ORM_Query::HYDRATE_OBJECT, true)); + $queryComponents, $tableAliasMap, true)); $this->assertEquals(2, count($result)); $this->assertTrue(is_array($result)); @@ -194,7 +194,7 @@ class Orm_Hydration_ObjectHydratorTest extends Orm_Hydration_HydrationTest $hydrator = new Doctrine_ORM_Internal_Hydration_ObjectHydrator($this->_em); $result = $hydrator->hydrateAll($stmt, $this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, Doctrine_ORM_Query::HYDRATE_OBJECT, true)); + $queryComponents, $tableAliasMap, true)); $this->assertEquals(2, count($result)); $this->assertTrue(is_array($result)); @@ -268,7 +268,7 @@ class Orm_Hydration_ObjectHydratorTest extends Orm_Hydration_HydrationTest $hydrator = new Doctrine_ORM_Internal_Hydration_ObjectHydrator($this->_em); $result = $hydrator->hydrateAll($stmt, $this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, Doctrine_ORM_Query::HYDRATE_OBJECT, true)); + $queryComponents, $tableAliasMap, true)); $this->assertEquals(2, count($result)); $this->assertTrue(is_array($result)); @@ -392,7 +392,7 @@ class Orm_Hydration_ObjectHydratorTest extends Orm_Hydration_HydrationTest $hydrator = new Doctrine_ORM_Internal_Hydration_ObjectHydrator($this->_em); $result = $hydrator->hydrateAll($stmt, $this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, Doctrine_ORM_Query::HYDRATE_OBJECT, true)); + $queryComponents, $tableAliasMap, true)); $this->assertEquals(2, count($result)); $this->assertTrue(is_array($result)); @@ -536,7 +536,7 @@ class Orm_Hydration_ObjectHydratorTest extends Orm_Hydration_HydrationTest $hydrator = new Doctrine_ORM_Internal_Hydration_ObjectHydrator($this->_em); $result = $hydrator->hydrateAll($stmt, $this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, Doctrine_ORM_Query::HYDRATE_OBJECT, true)); + $queryComponents, $tableAliasMap, true)); $this->assertEquals(2, count($result)); $this->assertTrue(is_array($result)); @@ -652,7 +652,7 @@ class Orm_Hydration_ObjectHydratorTest extends Orm_Hydration_HydrationTest $hydrator = new Doctrine_ORM_Internal_Hydration_ObjectHydrator($this->_em); $result = $hydrator->hydrateAll($stmt, $this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, Doctrine_ORM_Query::HYDRATE_OBJECT)); + $queryComponents, $tableAliasMap)); $this->assertEquals(2, count($result)); $this->assertTrue($result instanceof Doctrine_ORM_Collection); @@ -700,7 +700,7 @@ class Orm_Hydration_ObjectHydratorTest extends Orm_Hydration_HydrationTest $hydrator = new Doctrine_ORM_Internal_Hydration_ObjectHydrator($this->_em); $iterableResult = $hydrator->iterate($stmt, $this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, Doctrine_ORM_Query::HYDRATE_OBJECT)); + $queryComponents, $tableAliasMap)); $rowNum = 0; while (($row = $iterableResult->next()) !== false) { @@ -716,5 +716,78 @@ class Orm_Hydration_ObjectHydratorTest extends Orm_Hydration_HydrationTest ++$rowNum; } } + + /** + * select u.id, u.status, p.phonenumber, upper(u.name) nameUpper from User u + * join u.phonenumbers p + * = + * select u.id, u.status, p.phonenumber, upper(u.name) as u__0 from USERS u + * INNER JOIN PHONENUMBERS p ON u.id = p.user_id + * + * @dataProvider hydrationModeProvider + */ + /*public function testNewHydrationMixedQueryFetchJoinPerformance() + { + // Faked query components + $queryComponents = array( + 'u' => array( + 'metadata' => $this->_em->getClassMetadata('CmsUser'), + 'parent' => null, + 'relation' => null, + 'map' => null, + 'agg' => array('0' => 'nameUpper') + ), + 'p' => array( + 'metadata' => $this->_em->getClassMetadata('CmsPhonenumber'), + 'parent' => 'u', + 'relation' => $this->_em->getClassMetadata('CmsUser')->getAssociationMapping('phonenumbers'), + 'map' => null + ) + ); + + // Faked table alias map + $tableAliasMap = array( + 'u' => 'u', + 'p' => 'p' + ); + + // Faked result set + $resultSet = array( + //row1 + array( + 'u__id' => '1', + 'u__status' => 'developer', + 'u__0' => 'ROMANB', + 'p__phonenumber' => '42', + ), + array( + 'u__id' => '1', + 'u__status' => 'developer', + 'u__0' => 'ROMANB', + 'p__phonenumber' => '43', + ), + array( + 'u__id' => '2', + 'u__status' => 'developer', + 'u__0' => 'JWAGE', + 'p__phonenumber' => '91' + ) + ); + for ($i=4; $i<300; $i++) { + $resultSet[] = array( + 'u__id' => $i, + 'u__status' => 'developer', + 'u__0' => 'JWAGE' . $i, + 'p__phonenumber' => '91' + ); + } + + $stmt = new Doctrine_HydratorMockStatement($resultSet); + $hydrator = new Doctrine_ORM_Internal_Hydration_ObjectHydrator($this->_em); + + $result = $hydrator->hydrateAll($stmt, $this->_createParserResult( + $queryComponents, $tableAliasMap, true)); + + }*/ } diff --git a/tests/Orm/Hydration/ScalarHydratorTest.php b/tests/Orm/Hydration/ScalarHydratorTest.php index a91c0cfca..e41bc4abe 100644 --- a/tests/Orm/Hydration/ScalarHydratorTest.php +++ b/tests/Orm/Hydration/ScalarHydratorTest.php @@ -46,7 +46,7 @@ class Orm_Hydration_ScalarHydratorTest extends Orm_Hydration_HydrationTest $hydrator = new Doctrine_ORM_Internal_Hydration_ScalarHydrator($this->_em); $result = $hydrator->hydrateAll($stmt, $this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, Doctrine_ORM_Query::HYDRATE_SCALAR)); + $queryComponents, $tableAliasMap)); $this->assertTrue(is_array($result)); $this->assertEquals(2, count($result)); diff --git a/tests/Orm/Hydration/SingleScalarHydratorTest.php b/tests/Orm/Hydration/SingleScalarHydratorTest.php index c4e0b9852..9d51d92bf 100644 --- a/tests/Orm/Hydration/SingleScalarHydratorTest.php +++ b/tests/Orm/Hydration/SingleScalarHydratorTest.php @@ -74,16 +74,16 @@ class Orm_Hydration_SingleScalarHydratorTest extends Orm_Hydration_HydrationTest if ($name == 'result1') { $result = $hydrator->hydrateAll($stmt, $this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, Doctrine_ORM_Query::HYDRATE_SINGLE_SCALAR)); + $queryComponents, $tableAliasMap)); $this->assertEquals('romanb', $result); } else if ($name == 'result2') { $result = $hydrator->hydrateAll($stmt, $this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, Doctrine_ORM_Query::HYDRATE_SINGLE_SCALAR)); + $queryComponents, $tableAliasMap)); $this->assertEquals(1, $result); } else if ($name == 'result3' || $name == 'result4') { try { $result = $hydrator->hydrateall($stmt, $this->_createParserResult( - $stmt, $queryComponents, $tableAliasMap, Doctrine_ORM_Query::HYDRATE_SINGLE_SCALAR)); + $queryComponents, $tableAliasMap)); $this->fail(); } catch (Doctrine_ORM_Exceptions_HydrationException $ex) {} }