From d1a695b42b54ed7deb2f9461fee7d02d32514c3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20K=C5=99=C3=AD=C5=BE?= Date: Mon, 23 Mar 2015 15:57:41 +0100 Subject: [PATCH 1/4] Typo in phpdoc --- .../Persister/Entity/ReadWriteCachedEntityPersister.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Doctrine/ORM/Cache/Persister/Entity/ReadWriteCachedEntityPersister.php b/lib/Doctrine/ORM/Cache/Persister/Entity/ReadWriteCachedEntityPersister.php index 0d0a1af9d9e..8413082deac 100644 --- a/lib/Doctrine/ORM/Cache/Persister/Entity/ReadWriteCachedEntityPersister.php +++ b/lib/Doctrine/ORM/Cache/Persister/Entity/ReadWriteCachedEntityPersister.php @@ -35,10 +35,10 @@ class ReadWriteCachedEntityPersister extends AbstractEntityPersister { /** - * @param \Doctrine\ORM\Persister\Entity\EntityPersister $persister The entity persister to cache. - * @param \Doctrine\ORM\Cache\ConcurrentRegion $region The entity cache region. - * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager. - * @param \Doctrine\ORM\Mapping\ClassMetadata $class The entity metadata. + * @param \Doctrine\ORM\Persisters\Entity\EntityPersister $persister The entity persister to cache. + * @param \Doctrine\ORM\Cache\ConcurrentRegion $region The entity cache region. + * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager. + * @param \Doctrine\ORM\Mapping\ClassMetadata $class The entity metadata. */ public function __construct(EntityPersister $persister, ConcurrentRegion $region, EntityManagerInterface $em, ClassMetadata $class) { From e57be9da5e0c6bb31ac286d213e204784a34aa43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20K=C5=99=C3=AD=C5=BE?= Date: Mon, 23 Mar 2015 17:51:04 +0100 Subject: [PATCH 2/4] Fix: generated IDs are converted to integer --- lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php | 5 ++++- .../ORM/Persisters/Entity/JoinedSubclassPersister.php | 5 ++++- lib/Doctrine/ORM/UnitOfWork.php | 4 +++- tests/Doctrine/Tests/Mocks/EntityPersisterMock.php | 5 ++++- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php b/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php index a86f8bc2104..7ab1d3b1c2c 100644 --- a/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php +++ b/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php @@ -285,7 +285,10 @@ public function executeInserts() $id = array( $this->class->identifier[0] => $generatedId ); - $postInsertIds[$generatedId] = $entity; + $postInsertIds[] = array( + 'generatedId' => $generatedId, + 'entity' => $entity, + ); } else { $id = $this->class->getIdentifierValues($entity); } diff --git a/lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php b/lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php index 2886413fd73..b807fbae9ca 100644 --- a/lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php +++ b/lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php @@ -180,7 +180,10 @@ public function executeInserts() $id = array( $this->class->identifier[0] => $generatedId ); - $postInsertIds[$generatedId] = $entity; + $postInsertIds[] = array( + 'generatedId' => $generatedId, + 'entity' => $entity, + ); } else { $id = $this->em->getUnitOfWork()->getEntityIdentifier($entity); } diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index 2a458a3ceda..fe12e55df8c 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -1019,7 +1019,9 @@ private function executeInserts($class) if ($postInsertIds) { // Persister returned post-insert IDs - foreach ($postInsertIds as $id => $entity) { + foreach ($postInsertIds as $postInsertId) { + $id = $postInsertId['generatedId']; + $entity = $postInsertId['entity']; $oid = spl_object_hash($entity); $idField = $class->identifier[0]; diff --git a/tests/Doctrine/Tests/Mocks/EntityPersisterMock.php b/tests/Doctrine/Tests/Mocks/EntityPersisterMock.php index ac2157b5224..761ec4bc183 100644 --- a/tests/Doctrine/Tests/Mocks/EntityPersisterMock.php +++ b/tests/Doctrine/Tests/Mocks/EntityPersisterMock.php @@ -55,7 +55,10 @@ public function addInsert($entity) if ( ! is_null($this->mockIdGeneratorType) && $this->mockIdGeneratorType == \Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_IDENTITY || $this->class->isIdGeneratorIdentity()) { $id = $this->identityColumnValueCounter++; - $this->postInsertIds[$id] = $entity; + $this->postInsertIds[] = array( + 'generatedId' => $id, + 'entity' => $entity, + ); return $id; } return null; From cbdf23ca65e3a8c4948e090048934d6f0f68caf8 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Mon, 23 Mar 2015 23:29:22 +0000 Subject: [PATCH 3/4] Verifies that identifiers are kept as strings when dealing with large numbers --- .../ORM/Functional/Ticket/DDC3634Test.php | 388 ++++++++++++++++++ 1 file changed, 388 insertions(+) create mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/DDC3634Test.php diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC3634Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC3634Test.php new file mode 100644 index 00000000000..6139ce540a7 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC3634Test.php @@ -0,0 +1,388 @@ +_schemaTool->createSchema([ + $this->_em->getClassMetadata(DDC3634Entity::CLASSNAME), + ]); + } catch (ToolsException $e) { + // schema already in place + } + } + + public function testSavesVeryLargeIntegerAutoGeneratedValue() + { + $veryLargeId = PHP_INT_MAX . PHP_INT_MAX; + + $entityManager = EntityManager::create( + new DDC3634LastInsertIdMockingConnection($veryLargeId, $this->_em->getConnection()), + $this->_em->getConfiguration() + ); + + $entity = new DDC3634Entity(); + + $entityManager->persist($entity); + $entityManager->flush(); + + $this->assertSame($veryLargeId, $entity->id); + } + + public function testSavesIntegerAutoGeneratedValueAsString() + { + $entity = new DDC3634Entity(); + + $this->_em->persist($entity); + $this->_em->flush(); + + $this->assertInternalType('string', $entity->id); + } +} + +/** @Entity */ +class DDC3634Entity +{ + const CLASSNAME = __CLASS__; + + /** @Id @Column(type="bigint") @GeneratedValue(strategy="AUTO") */ + public $id; +} + +class DDC3634LastInsertIdMockingConnection extends Connection +{ + /** + * @var Connection + */ + private $realConnection; + + /** + * @var int + */ + private $identifier; + + /** + * @param int $identifier + * @param Connection $realConnection + */ + public function __construct($identifier, Connection $realConnection) + { + $this->realConnection = $realConnection; + $this->identifier = $identifier; + } + + private function forwardCall() + { + $trace = debug_backtrace(0, 2)[1]; + + return call_user_func_array([$this->realConnection, $trace['function']], $trace['args']); + } + + public function getParams() + { + return $this->forwardCall(); + } + + public function getDatabase() + { + return $this->forwardCall(); + } + + public function getHost() + { + return $this->forwardCall(); + } + + public function getPort() + { + return $this->forwardCall(); + } + + public function getUsername() + { + return $this->forwardCall(); + } + + public function getPassword() + { + return $this->forwardCall(); + } + + public function getDriver() + { + return $this->forwardCall(); + } + + public function getConfiguration() + { + return $this->forwardCall(); + } + + public function getEventManager() + { + return $this->forwardCall(); + } + + public function getDatabasePlatform() + { + return $this->forwardCall(); + } + + public function getExpressionBuilder() + { + return $this->forwardCall(); + } + + public function connect() + { + return $this->forwardCall(); + } + + public function isAutoCommit() + { + return $this->forwardCall(); + } + + public function setAutoCommit($autoCommit) + { + return $this->forwardCall(); + } + + public function setFetchMode($fetchMode) + { + return $this->forwardCall(); + } + + public function fetchAssoc($statement, array $params = [], array $types = []) + { + return $this->forwardCall(); + } + + public function fetchArray($statement, array $params = [], array $types = []) + { + return $this->forwardCall(); + } + + public function fetchColumn($statement, array $params = [], $column = 0, array $types = []) + { + return $this->forwardCall(); + } + + public function isConnected() + { + return $this->forwardCall(); + } + + public function isTransactionActive() + { + return $this->forwardCall(); + } + + public function delete($tableExpression, array $identifier, array $types = []) + { + return $this->forwardCall(); + } + + public function close() + { + return $this->forwardCall(); + } + + public function setTransactionIsolation($level) + { + return $this->forwardCall(); + } + + public function getTransactionIsolation() + { + return $this->forwardCall(); + } + + public function update($tableExpression, array $data, array $identifier, array $types = []) + { + return $this->forwardCall(); + } + + public function insert($tableExpression, array $data, array $types = []) + { + return $this->forwardCall(); + } + + public function quoteIdentifier($str) + { + return $this->forwardCall(); + } + + public function quote($input, $type = null) + { + return $this->forwardCall(); + } + + public function fetchAll($sql, array $params = [], $types = []) + { + return $this->forwardCall(); + } + + public function prepare($statement) + { + return $this->forwardCall(); + } + + public function executeQuery($query, array $params = [], $types = [], QueryCacheProfile $qcp = null) + { + return $this->forwardCall(); + } + + public function executeCacheQuery($query, $params, $types, QueryCacheProfile $qcp) + { + return $this->forwardCall(); + } + + public function project($query, array $params, \Closure $function) + { + return $this->forwardCall(); + } + + public function query() + { + return $this->forwardCall(); + } + + public function executeUpdate($query, array $params = [], array $types = []) + { + return $this->forwardCall(); + } + + public function exec($statement) + { + return $this->forwardCall(); + } + + public function getTransactionNestingLevel() + { + return $this->forwardCall(); + } + + public function errorCode() + { + return $this->forwardCall(); + } + + public function errorInfo() + { + return $this->forwardCall(); + } + + public function lastInsertId($seqName = null) + { + return $this->identifier; + } + + public function transactional(\Closure $func) + { + return $this->forwardCall(); + } + + public function setNestTransactionsWithSavepoints($nestTransactionsWithSavepoints) + { + return $this->forwardCall(); + } + + public function getNestTransactionsWithSavepoints() + { + return $this->forwardCall(); + } + + protected function _getNestedTransactionSavePointName() + { + return $this->forwardCall(); + } + + public function beginTransaction() + { + return $this->forwardCall(); + } + + public function commit() + { + return $this->forwardCall(); + } + + public function rollBack() + { + return $this->forwardCall(); + } + + public function createSavepoint($savepoint) + { + return $this->forwardCall(); + } + + public function releaseSavepoint($savepoint) + { + return $this->forwardCall(); + } + + public function rollbackSavepoint($savepoint) + { + return $this->forwardCall(); + } + + public function getWrappedConnection() + { + return $this->forwardCall(); + } + + public function getSchemaManager() + { + return $this->forwardCall(); + } + + public function setRollbackOnly() + { + return $this->forwardCall(); + } + + public function isRollbackOnly() + { + return $this->forwardCall(); + } + + public function convertToDatabaseValue($value, $type) + { + return $this->forwardCall(); + } + + public function convertToPHPValue($value, $type) + { + return $this->forwardCall(); + } + + public function resolveParams(array $params, array $types) + { + return $this->forwardCall(); + } + + public function createQueryBuilder() + { + return $this->forwardCall(); + } + + public function ping() + { + return $this->forwardCall(); + } +} \ No newline at end of file From 4c119c44a116ad1b4d216ff960f3fba88c2529cf Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Mon, 23 Mar 2015 23:37:36 +0000 Subject: [PATCH 4/4] Completed test coverage for DDC-3634 --- .../ORM/Functional/Ticket/DDC3634Test.php | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC3634Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC3634Test.php index 6139ce540a7..6cbc0158fff 100644 --- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC3634Test.php +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC3634Test.php @@ -19,6 +19,8 @@ protected function setUp() { try { $this->_schemaTool->createSchema([ $this->_em->getClassMetadata(DDC3634Entity::CLASSNAME), + $this->_em->getClassMetadata(DDC3634JTIBaseEntity::CLASSNAME), + $this->_em->getClassMetadata(DDC3634JTIChildEntity::CLASSNAME), ]); } catch (ToolsException $e) { // schema already in place @@ -51,6 +53,16 @@ public function testSavesIntegerAutoGeneratedValueAsString() $this->assertInternalType('string', $entity->id); } + + public function testSavesIntegerAutoGeneratedValueAsStringWithJoinedInheritance() + { + $entity = new DDC3634JTIChildEntity(); + + $this->_em->persist($entity); + $this->_em->flush(); + + $this->assertInternalType('string', $entity->id); + } } /** @Entity */ @@ -62,6 +74,28 @@ class DDC3634Entity public $id; } +/** + * @Entity + * @InheritanceType("JOINED") + * @DiscriminatorMap({ + * DDC3634JTIBaseEntity::class = DDC3634JTIBaseEntity::class, + * DDC3634JTIChildEntity::class = DDC3634JTIChildEntity::class, + * }) + */ +class DDC3634JTIBaseEntity +{ + const CLASSNAME = __CLASS__; + + /** @Id @Column(type="bigint") @GeneratedValue(strategy="AUTO") */ + public $id; +} + +/** @Entity */ +class DDC3634JTIChildEntity extends DDC3634JTIBaseEntity +{ + const CLASSNAME = __CLASS__; +} + class DDC3634LastInsertIdMockingConnection extends Connection { /**