Compare commits

...

61 Commits
2.3.2 ... 2.3.4

Author SHA1 Message Date
Benjamin Eberlei
a41b02c080 Release 2.3.4 2013-05-11 09:51:12 +02:00
Benjamin Eberlei
8b3c206bc1 Bump dependency to 2.3.4 2013-05-11 09:47:19 +02:00
Benjamin Eberlei
e0feccc2e4 Merge branch 'DDC-2280' into 2.3 2013-05-09 18:17:03 +02:00
Benjamin Eberlei
818d3d27fe [DDC-2280] length attribute in <id> was not converted. 2013-05-09 18:16:55 +02:00
Benjamin Eberlei
98d3847a11 Merge branch 'DDC-2387' into 2.3 2013-05-09 12:11:23 +02:00
Benjamin Eberlei
63918f214b [DDC-2387] Fix DatabaseDriver not working with combinations of composite/association keys. 2013-05-09 12:11:04 +02:00
Benjamin Eberlei
acf21246c7 Merge branch 'DDC-2437' into 2.3 2013-05-09 11:04:14 +02:00
Vladislav Vlastovskiy
795e4a4b6b Added test complex inner join with indexBy 2013-05-09 11:03:36 +02:00
Vladislav Vlastovskiy
946a22f2c7 Swapped places indexBy and condition in accordance with EBNF 2013-05-09 11:03:36 +02:00
Benjamin Eberlei
bdd7482b3f Merge branch 'DDC-2423' into 2.3 2013-05-09 10:56:00 +02:00
Benjamin Eberlei
8e31107f86 [DDC-2423] Fixed bug with EntityGenerator not generating fetch="" attribute in association annotations. 2013-05-09 10:55:42 +02:00
Benjamin Eberlei
209090d338 Merge branch 'DDC-2267' into 2.3 2013-05-04 13:39:37 +02:00
Benjamin Eberlei
27117bbc98 [DDC-2267] Allow EntityManager#flush($entity) to be called on entities scheduled for removal. 2013-05-04 13:39:23 +02:00
Benjamin Eberlei
0f2be50d8f [DDC-2426] Missing length attribute in doctrine-mapping.xsd for <id> tag. 2013-05-04 12:59:02 +02:00
Benjamin Eberlei
193e74af05 Merge branch 'DDC-1984' into 2.3 2013-05-01 19:40:06 +02:00
Benjamin Eberlei
bb6e4f2074 [DDC-1984] Throw exception if passing null into UnitOfWork#lock() - which can happen when EntityManager#find() tries to lock entity that was just deleted by another process. 2013-05-01 19:39:48 +02:00
Benjamin Eberlei
6063fe4adf Merge branch 'DDC-2409' into 2.3 2013-05-01 11:01:17 +02:00
Benjamin Eberlei
846c6d2c5e Simplify condition of previous commit (5cdc73e) 2013-05-01 11:00:55 +02:00
Fabio B. Silva
1f257622a1 Fix DDC-2409 2013-05-01 11:00:55 +02:00
Benjamin Eberlei
84257c9454 Merge branch 'DBAL-483' into 2.3 2013-05-01 10:45:19 +02:00
Benjamin Eberlei
eedacc9822 [DBAL-483] Add sqlite check again as ALTER TABLE is only supported as of 2.4 2013-05-01 10:44:31 +02:00
Benjamin Eberlei
3d9099e33b [DBAL-483] Pass default values to DBAL mapping layer correctly to fix default comparision bug. 2013-05-01 10:42:53 +02:00
EuKov
ad7b5871bf Fixed typo in SQLFilter (use statement ClassMetadata) 2013-04-23 22:26:59 +02:00
Benjamin Eberlei
803f2740c9 [DDC-2346] Reapply changes lost in rebase onto 2.3 2013-04-14 09:52:39 +02:00
Stefan Kleff
ed3f375ef3 Added constant 2013-04-14 09:49:26 +02:00
Stefan Kleff
a188c88ef2 Added test based on e468ced00b 2013-04-14 09:48:09 +02:00
Benjamin Eberlei
86e40a692b Merge branch 'DDC-2252' into 2.3 2013-04-06 19:56:15 +02:00
Fabio B. Silva
36b79309bd Fix DDC-2252 2013-04-06 19:55:50 +02:00
Benjamin Eberlei
66b6b7169e Merge branch 'DDC-2224-2' into 2.3 2013-04-04 20:35:01 +02:00
Benjamin Eberlei
7c7a8abe40 [DDC-2224] Adjust ClassMetadata processing 2013-04-04 20:34:49 +02:00
Benjamin Eberlei
e5c68ab45c [DDC-2224] Rewrite instanceof feature with parameter needle ClassMetadata breaks caching of queries. 2013-04-04 20:32:04 +02:00
Benjamin Eberlei
868bb68cc8 Bump dev version to 2.3.4 2013-03-24 21:43:58 +01:00
Benjamin Eberlei
b3788c14ee Release 2.3.3 2013-03-24 21:43:58 +01:00
Benjamin Eberlei
3148d8aeac Bump Dbal Dependency to 2.3.3 2013-03-24 20:21:32 +01:00
Benjamin Eberlei
ae1f903080 Merge branch 'DDC-2090' into 2.3 2013-03-17 21:49:24 +01:00
Fabio B. Silva
07482bd624 Fix DDC-2090 2013-03-17 21:48:55 +01:00
Benjamin Eberlei
8d78b90bca Merge branch 'DDC-1666' into 2.3 2013-03-14 23:42:28 +01:00
Benjamin Eberlei
ca93400493 [DDC-1666] Fix bug where orphan removal on one-to-one associations lead to unique constraint errors when replacing an entity with a new one. 2013-03-14 23:42:04 +01:00
Benjamin Eberlei
7152e5f72f Merge branch 'DDC-2300' into 2.3 2013-03-14 23:22:01 +01:00
Benjamin Eberlei
279fcb6c81 [DDC-2300] Fix version xml mapping and serialization of ClassMetadata. 2013-03-14 23:20:46 +01:00
Benjamin Eberlei
7705105c5d Merge branch 'GH-593' into 2.3 2013-03-14 22:59:42 +01:00
Norbert Orzechowicz
cb70a8a8c4 Fix SimpleObjectHydrator behavior when column not exists in fieldMappings, relationMappings and metaMappings 2013-03-14 22:59:20 +01:00
Benjamin Eberlei
8a2d7374b1 Fix bugs in tests 2013-03-14 20:08:37 +01:00
Benjamin Eberlei
563fdb953b Merge branch 'DDC-2340' into 2.3 2013-03-12 22:53:10 +01:00
Benjamin Eberlei
3daf824c9e [DDC-2340] Fix bug with dirty collection matching + ordering. 2013-03-12 22:52:52 +01:00
Jean-Guilhem Rouel
aa4664687f Don't add empty expression to another one 2013-03-12 19:18:07 +01:00
Benjamin Eberlei
550c1cf98c Merge branch 'GH-572' into 2.3 2013-03-12 19:06:02 +01:00
Norbert Orzechowicz
33799d094c [DDC-2282] Fix pagination problem with SQL Server.
ORDER BY removed from all count queries when on SQL Server
Fixed SQLServer ORDER BY problem in paginator CountOutputWalker
Added test to check query with ORDER BY and SQLServerPlatform
2013-03-12 19:05:28 +01:00
Benjamin Eberlei
304acf0a1a Merge branch 'DDC-2310' into 2.3 2013-02-21 19:03:42 +01:00
Benjamin Eberlei
84996e0601 [DDC-2310] Fix regression introduced in SQL Server lock handling. 2013-02-21 19:03:12 +01:00
Benjamin Eberlei
fdd0af34e6 Merge branch 'DDC-2243' into 2.3 2013-01-20 20:35:21 +01:00
Benjamin Eberlei
f0312edb94 [DDC-2243] Fix bug where a bigint identifier would be casted to an integer, causing inconsistency with the string handling. 2013-01-20 20:34:09 +01:00
Benjamin Eberlei
6d25c4e08a Merge remote-tracking branch 'origin/2.3' into 2.3 2013-01-20 20:12:44 +01:00
Benjamin Eberlei
d9f51eb2fa Merge branch 'DDC-2246' into 2.3 2013-01-20 20:12:35 +01:00
Benjamin Eberlei
88cebe1263 [DDC-2246] Fix bug with UnitOfWork#getEntityState() and entities with foreign identifier. 2013-01-20 20:11:40 +01:00
Benjamin Eberlei
6829c464e8 Merge branch 'DDC-2231' into 2.3 2013-01-12 10:32:44 +01:00
Benjamin Eberlei
fc2eebdf75 DDC-2231 - Simplify test 2013-01-12 10:32:24 +01:00
Stefan Kleff
54193e7f82 Added test 2013-01-12 10:32:24 +01:00
Stefan Kleff
8001cad573 fixed indentation
Restored old way of injection to just inject it during a refresh
Added injection for initialized proxies
2013-01-12 10:32:24 +01:00
Stefan Kleff
c4c70d667a The EntityManager was not injected in uninitialized proxys which are ObjectManagerAware.
I ran into that problem while I had two objects in the identitymap while hydrating a collection: one was new a "real" entity and the other one was an uninitialized proxy. For "real" entities the em is injected in line 2427, for new entities it is injected in 2436->2364, but for proxies this is missing. According to the comment "inject ObjectManager into just loaded proxies." the code in line 2427 should do this, but in fact it is just used if it is a "real" entity or an already initialized proxy. Moving the injection to outside of the condition in line 2411 (if the entity is an unitialized proxy) solves this.
2013-01-12 10:32:24 +01:00
Benjamin Eberlei
f5bb8be884 Bump dev version to 2.3.3 2013-01-07 21:05:04 +01:00
52 changed files with 1201 additions and 203 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "doctrine/orm",
"type": "library","version":"2.3.2",
"type": "library","version":"2.3.4",
"description": "Object-Relational-Mapper for PHP",
"keywords": ["orm", "database"],
"homepage": "http://www.doctrine-project.org",

View File

@@ -329,6 +329,7 @@
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
<xs:attribute name="type" type="xs:NMTOKEN" />
<xs:attribute name="column" type="xs:NMTOKEN" />
<xs:attribute name="length" type="xs:NMTOKEN" />
<xs:attribute name="association-key" type="xs:boolean" default="false" />
<xs:attribute name="column-definition" type="xs:string" />
<xs:anyAttribute namespace="##other"/>

View File

@@ -26,6 +26,7 @@ use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Cache\QueryCacheProfile;
use Doctrine\ORM\Query\QueryException;
use Doctrine\ORM\Mapping;
/**
* Base contract for ORM queries. Base class for Query and NativeQuery.
@@ -259,6 +260,9 @@ abstract class AbstractQuery
case is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(ClassUtils::getClass($value)):
return $this->convertObjectParameterToScalarValue($value);
case ($value instanceof Mapping\ClassMetadata):
return $value->name;
default:
return $value;
}

View File

@@ -0,0 +1,66 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Id;
use Doctrine\ORM\EntityManager;
/**
* Id generator that obtains IDs from special "identity" columns. These are columns
* that automatically get a database-generated, auto-incremented identifier on INSERT.
* This generator obtains the last insert id after such an insert.
*/
class BigIntegerIdentityGenerator extends AbstractIdGenerator
{
/**
* The name of the sequence to pass to lastInsertId(), if any.
*
* @var string
*/
private $sequenceName;
/**
* Constructor.
*
* @param string|null $seqName The name of the sequence to pass to lastInsertId()
* to obtain the last generated identifier within the current
* database session/connection, if any.
*/
public function __construct($sequenceName = null)
{
$this->sequenceName = $sequenceName;
}
/**
* {@inheritdoc}
*/
public function generate(EntityManager $em, $entity)
{
return (string)$em->getConnection()->lastInsertId($this->sequenceName);
}
/**
* {@inheritdoc}
*/
public function isPostInsertGenerator()
{
return true;
}
}

View File

@@ -28,17 +28,21 @@ use Doctrine\ORM\EntityManager;
*/
class IdentityGenerator extends AbstractIdGenerator
{
/** @var string The name of the sequence to pass to lastInsertId(), if any. */
private $_seqName;
/**
* The name of the sequence to pass to lastInsertId(), if any.
*
* @var string
*/
private $sequenceName;
/**
* @param string $seqName The name of the sequence to pass to lastInsertId()
* to obtain the last generated identifier within the current
* database session/connection, if any.
*/
public function __construct($seqName = null)
public function __construct($sequenceName = null)
{
$this->_seqName = $seqName;
$this->sequenceName = $sequenceName;
}
/**
@@ -46,7 +50,7 @@ class IdentityGenerator extends AbstractIdGenerator
*/
public function generate(EntityManager $em, $entity)
{
return (int)$em->getConnection()->lastInsertId($this->_seqName);
return (int)$em->getConnection()->lastInsertId($this->sequenceName);
}
/**

View File

@@ -27,6 +27,7 @@ use PDO,
Doctrine\ORM\Events,
Doctrine\Common\Collections\ArrayCollection,
Doctrine\Common\Collections\Collection,
Doctrine\ORM\UnitOfWork,
Doctrine\ORM\Proxy\Proxy;
/**
@@ -65,8 +66,8 @@ class ObjectHydrator extends AbstractHydrator
$this->_resultCounter = 0;
if ( ! isset($this->_hints['deferEagerLoad'])) {
$this->_hints['deferEagerLoad'] = true;
if ( ! isset($this->_hints[UnitOfWork::HINT_DEFEREAGERLOAD])) {
$this->_hints[UnitOfWork::HINT_DEFEREAGERLOAD] = true;
}
foreach ($this->_rsm->aliasMap as $dqlAlias => $className) {
@@ -123,7 +124,7 @@ class ObjectHydrator extends AbstractHydrator
*/
protected function cleanup()
{
$eagerLoad = (isset($this->_hints['deferEagerLoad'])) && $this->_hints['deferEagerLoad'] == true;
$eagerLoad = (isset($this->_hints[UnitOfWork::HINT_DEFEREAGERLOAD])) && $this->_hints[UnitOfWork::HINT_DEFEREAGERLOAD] == true;
parent::cleanup();

View File

@@ -178,10 +178,13 @@ class SimpleObjectHydrator extends AbstractHydrator
// One solution is to load the association, but it might require extra efforts.
return array('name' => $column);
default:
case (isset($this->_rsm->metaMappings[$column])):
return array(
'name' => $this->_rsm->metaMappings[$column]
);
default:
return null;
}
}
}

View File

@@ -19,16 +19,17 @@
namespace Doctrine\ORM\Mapping;
use ReflectionException,
Doctrine\ORM\ORMException,
Doctrine\ORM\EntityManager,
Doctrine\DBAL\Platforms,
Doctrine\ORM\Events,
Doctrine\Common\Persistence\Mapping\ReflectionService,
Doctrine\Common\Persistence\Mapping\ClassMetadata as ClassMetadataInterface,
Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory,
Doctrine\ORM\Id\IdentityGenerator,
Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use ReflectionException;
use Doctrine\ORM\ORMException;
use Doctrine\ORM\EntityManager;
use Doctrine\DBAL\Platforms;
use Doctrine\ORM\Events;
use Doctrine\Common\Persistence\Mapping\ReflectionService;
use Doctrine\Common\Persistence\Mapping\ClassMetadata as ClassMetadataInterface;
use Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory;
use Doctrine\ORM\Id\IdentityGenerator;
use Doctrine\ORM\Id\BigIntegerIdentityGenerator;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
/**
* The ClassMetadataFactory is used to create ClassMetadata objects that contain all the
@@ -418,9 +419,9 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
// <table>_<column>_seq in PostgreSQL for SERIAL columns.
// Not pretty but necessary and the simplest solution that currently works.
$sequenceName = null;
$fieldName = $class->identifier ? $class->getSingleIdentifierFieldName() : null;
if ($this->targetPlatform instanceof Platforms\PostgreSQLPlatform) {
$fieldName = $class->getSingleIdentifierFieldName();
$columnName = $class->getSingleIdentifierColumnName();
$quoted = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']);
$sequenceName = $class->getTableName() . '_' . $columnName . '_seq';
@@ -435,7 +436,12 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
$sequenceName = $this->em->getConfiguration()->getQuoteStrategy()->getSequenceName($definition, $class, $this->targetPlatform);
}
$class->setIdGenerator(new \Doctrine\ORM\Id\IdentityGenerator($sequenceName));
$generator = ($fieldName && $class->fieldMappings[$fieldName]['type'] === "bigint")
? new BigIntegerIdentityGenerator($sequenceName)
: new IdentityGenerator($sequenceName);
$class->setIdGenerator($generator);
break;
case ClassMetadata::GENERATOR_TYPE_SEQUENCE:

View File

@@ -1421,6 +1421,10 @@ class ClassMetadataInfo implements ClassMetadata
$mapping['orphanRemoval'] = isset($mapping['orphanRemoval']) ? (bool) $mapping['orphanRemoval'] : false;
$mapping['isCascadeRemove'] = $mapping['orphanRemoval'] ? true : $mapping['isCascadeRemove'];
if ($mapping['orphanRemoval']) {
unset($mapping['unique']);
}
if (isset($mapping['id']) && $mapping['id'] === true && !$mapping['isOwningSide']) {
throw MappingException::illegalInverseIdentifierAssocation($this->name, $mapping['fieldName']);
}

View File

@@ -217,7 +217,8 @@ class DatabaseDriver implements MappingDriver
}
if ($ids) {
if (count($ids) == 1) {
// We need to check for the columns here, because we might have associations as id as well.
if (count($primaryKeyColumns) == 1) {
$metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO);
}

View File

@@ -233,6 +233,7 @@ class XmlDriver extends FileDriver
if (isset($mapping['version'])) {
$metadata->setVersionMapping($mapping);
unset($mapping['version']);
}
$metadata->mapField($mapping);
@@ -662,7 +663,7 @@ class XmlDriver extends FileDriver
}
if (isset($fieldMapping['version']) && $fieldMapping['version']) {
$mapping['version'] = $fieldMapping['version'];
$mapping['version'] = $this->evaluateBoolean($fieldMapping['version']);
}
if (isset($fieldMapping['column-definition'])) {

View File

@@ -299,6 +299,7 @@ class YamlDriver extends FileDriver
if (isset($mapping['version'])) {
$metadata->setVersionMapping($mapping);
unset($mapping['version']);
}
$metadata->mapField($mapping);

View File

@@ -805,6 +805,10 @@ final class PersistentCollection implements Collection, Selectable
*/
public function matching(Criteria $criteria)
{
if ($this->isDirty) {
$this->initialize();
}
if ($this->initialized) {
return $this->coll->matching($criteria);
}
@@ -813,16 +817,10 @@ final class PersistentCollection implements Collection, Selectable
throw new \RuntimeException("Matching Criteria on PersistentCollection only works on OneToMany assocations at the moment.");
}
// If there are NEW objects we have to check if any of them matches the criteria
$newObjects = array();
if ($this->isDirty) {
$newObjects = $this->coll->matching($criteria)->toArray();
}
$targetClass = $this->em->getClassMetadata(get_class($this->owner));
$id = $targetClass->getSingleIdReflectionProperty()->getValue($this->owner);
$id = $this->em
->getClassMetadata(get_class($this->owner))
->getSingleIdReflectionProperty()
->getValue($this->owner);
$builder = Criteria::expr();
$ownerExpression = $builder->eq($this->backRefFieldName, $id);
$expression = $criteria->getWhereExpression();
@@ -832,7 +830,7 @@ final class PersistentCollection implements Collection, Selectable
$persister = $this->em->getUnitOfWork()->getEntityPersister($this->association['targetEntity']);
return new ArrayCollection(array_merge($persister->loadCriteria($criteria), $newObjects));
return new ArrayCollection($persister->loadCriteria($criteria));
}
}

View File

@@ -790,7 +790,7 @@ class BasicEntityPersister
$hydrator = $this->_em->newHydrator(($this->_selectJoinSql) ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT);
return $hydrator->hydrateAll($stmt, $this->_rsm, array('deferEagerLoads' => true));
return $hydrator->hydrateAll($stmt, $this->_rsm, array(UnitOfWork::HINT_DEFEREAGERLOAD => true));
}
/**
@@ -845,7 +845,7 @@ class BasicEntityPersister
$hydrator = $this->_em->newHydrator(($this->_selectJoinSql) ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT);
return $hydrator->hydrateAll($stmt, $this->_rsm, array('deferEagerLoads' => true));
return $hydrator->hydrateAll($stmt, $this->_rsm, array(UnitOfWork::HINT_DEFEREAGERLOAD => true));
}
/**
@@ -874,7 +874,7 @@ class BasicEntityPersister
*/
private function loadArrayFromStatement($assoc, $stmt)
{
$hints = array('deferEagerLoads' => true);
$hints = array(UnitOfWork::HINT_DEFEREAGERLOAD => true);
if (isset($assoc['indexBy'])) {
$rsm = clone ($this->_rsm); // this is necessary because the "default rsm" should be changed.
@@ -899,7 +899,7 @@ class BasicEntityPersister
*/
private function loadCollectionFromStatement($assoc, $stmt, $coll)
{
$hints = array('deferEagerLoads' => true, 'collection' => $coll);
$hints = array(UnitOfWork::HINT_DEFEREAGERLOAD => true, 'collection' => $coll);
if (isset($assoc['indexBy'])) {
$rsm = clone ($this->_rsm); // this is necessary because the "default rsm" should be changed.

View File

@@ -186,22 +186,22 @@ class ManyToManyPersister extends AbstractCollectionPersister
*/
protected function _getDeleteSQLParameters(PersistentCollection $coll)
{
$identifier = $this->_uow->getEntityIdentifier($coll->getOwner());
$mapping = $coll->getMapping();
$params = array();
$identifier = $this->_uow->getEntityIdentifier($coll->getOwner());
// Optimization for single column identifier
if (count($mapping['relationToSourceKeyColumns']) === 1) {
$params[] = array_pop($identifier);
return $params;
return array(reset($identifier));
}
// Composite identifier
$sourceClass = $this->_em->getClassMetadata(get_class($coll->getOwner()));
$params = array();
foreach ($mapping['relationToSourceKeyColumns'] as $srcColumn) {
$params[] = $identifier[$sourceClass->fieldNames[$srcColumn]];
foreach ($mapping['relationToSourceKeyColumns'] as $columnName => $refColumnName) {
$params[] = isset($sourceClass->fieldNames[$refColumnName])
? $identifier[$sourceClass->fieldNames[$refColumnName]]
: $identifier[$sourceClass->getFieldForColumn($columnName)];
}
return $params;

View File

@@ -104,19 +104,8 @@ class MultiTableUpdateExecutor extends AbstractSqlExecutor
$updateSql .= $sqlWalker->walkUpdateItem($updateItem);
//FIXME: parameters can be more deeply nested. traverse the tree.
//FIXME (URGENT): With query cache the parameter is out of date. Move to execute() stage.
if ($newValue instanceof AST\InputParameter) {
$parameterName = $newValue->name;
$parameter = $sqlWalker->getQuery()->getParameter($parameterName);
$value = $sqlWalker->getQuery()->processParameterValue($parameter->getValue());
$type = ($parameter->getValue() === $value)
? $parameter->getType()
: ParameterTypeInferer::inferType($value);
$this->_sqlParameters[$i]['parameters'][] = $value;
$this->_sqlParameters[$i]['types'][] = $type;
$this->_sqlParameters[$i][] = $newValue->name;
++$this->_numParametersInUpdateClause;
}
@@ -168,16 +157,18 @@ class MultiTableUpdateExecutor extends AbstractSqlExecutor
);
// Execute UPDATE statements
for ($i=0, $count=count($this->_sqlStatements); $i<$count; ++$i) {
$parameters = array();
$types = array();
foreach ($this->_sqlStatements as $key => $statement) {
$paramValues = array();
$paramTypes = array();
if (isset($this->_sqlParameters[$i])) {
$parameters = isset($this->_sqlParameters[$i]['parameters']) ? $this->_sqlParameters[$i]['parameters'] : array();
$types = isset($this->_sqlParameters[$i]['types']) ? $this->_sqlParameters[$i]['types'] : array();
if (isset($this->_sqlParameters[$key])) {
foreach ($this->_sqlParameters[$key] as $parameterKey => $parameterName) {
$paramValues[] = $params[$parameterKey];
$paramTypes[] = isset($types[$parameterKey]) ? $types[$parameterKey] : ParameterTypeInferer::inferType($params[$parameterKey]);
}
}
$conn->executeUpdate($this->_sqlStatements[$i], $parameters, $types);
$conn->executeUpdate($statement, $paramValues, $paramTypes);
}
} catch (\Exception $exception) {
// FAILURE! Drop temporary table to avoid possible collisions

View File

@@ -83,7 +83,7 @@ abstract class Base
*/
public function add($arg)
{
if ( $arg !== null || ($arg instanceof self && $arg->count() > 0) ) {
if ( $arg !== null && (!$arg instanceof self || $arg->count() > 0) ) {
// If we decide to keep Expr\Base instances, we can use this check
if ( ! is_string($arg)) {
$class = get_class($arg);

View File

@@ -141,7 +141,7 @@ class Join
{
return strtoupper($this->joinType) . ' JOIN ' . $this->join
. ($this->alias ? ' ' . $this->alias : '')
. ($this->condition ? ' ' . strtoupper($this->conditionType) . ' ' . $this->condition : '')
. ($this->indexBy ? ' INDEX BY ' . $this->indexBy : '');
. ($this->indexBy ? ' INDEX BY ' . $this->indexBy : '')
. ($this->condition ? ' ' . strtoupper($this->conditionType) . ' ' . $this->condition : '');
}
}

View File

@@ -19,9 +19,9 @@
namespace Doctrine\ORM\Query\Filter;
use Doctrine\ORM\EntityManager,
Doctrine\ORM\Mapping\ClassMetaData,
Doctrine\ORM\Query\ParameterTypeInferer;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Query\ParameterTypeInferer;
/**
* The base class that user defined filters should extend.

View File

@@ -750,7 +750,10 @@ class SqlWalker implements TreeWalker
$sqlParts = array();
foreach ($identificationVarDecls as $identificationVariableDecl) {
$sql = $this->walkRangeVariableDeclaration($identificationVariableDecl->rangeVariableDeclaration);
$sql = $this->platform->appendLockHint(
$this->walkRangeVariableDeclaration($identificationVariableDecl->rangeVariableDeclaration),
$this->query->getHint(Query::HINT_LOCK_MODE)
);
foreach ($identificationVariableDecl->joins as $join) {
$sql .= $this->walkJoin($join);
@@ -770,7 +773,7 @@ class SqlWalker implements TreeWalker
}
}
$sqlParts[] = $this->platform->appendLockHint($sql, $this->query->getHint(Query::HINT_LOCK_MODE));
$sqlParts[] = $sql;
}
return ' FROM ' . implode(', ', $sqlParts);
@@ -1367,13 +1370,16 @@ class SqlWalker implements TreeWalker
$sqlParts = array ();
foreach ($identificationVarDecls as $subselectIdVarDecl) {
$sql = $this->walkRangeVariableDeclaration($subselectIdVarDecl->rangeVariableDeclaration);
$sql = $this->platform->appendLockHint(
$this->walkRangeVariableDeclaration($subselectIdVarDecl->rangeVariableDeclaration),
$this->query->getHint(Query::HINT_LOCK_MODE)
);
foreach ($subselectIdVarDecl->joins as $join) {
$sql .= $this->walkJoin($join);
}
$sqlParts[] = $this->platform->appendLockHint($sql, $this->query->getHint(Query::HINT_LOCK_MODE));
$sqlParts[] = $sql;
}
return ' FROM ' . implode(', ', $sqlParts);
@@ -1910,31 +1916,22 @@ class SqlWalker implements TreeWalker
foreach ($instanceOfExpr->value as $parameter) {
if ($parameter instanceof AST\InputParameter) {
// We need to modify the parameter value to be its correspondent mapped value
$dqlParamKey = $parameter->name;
$dqlParam = $this->query->getParameter($dqlParamKey);
$paramValue = $this->query->processParameterValue($dqlParam->getValue());
if ( ! ($paramValue instanceof \Doctrine\ORM\Mapping\ClassMetadata)) {
throw QueryException::invalidParameterType('ClassMetadata', get_class($paramValue));
}
$entityClassName = $paramValue->name;
$sqlParameterList[] = $this->walkInputParameter($parameter);
} else {
// Get name from ClassMetadata to resolve aliases.
$entityClassName = $this->em->getClassMetadata($parameter)->name;
}
if ($entityClassName == $class->name) {
$sqlParameterList[] = $this->conn->quote($class->discriminatorValue);
} else {
$discrMap = array_flip($class->discriminatorMap);
if ($entityClassName == $class->name) {
$sqlParameterList[] = $this->conn->quote($class->discriminatorValue);
} else {
$discrMap = array_flip($class->discriminatorMap);
if (!isset($discrMap[$entityClassName])) {
throw QueryException::instanceOfUnrelatedClass($entityClassName, $class->rootEntityName);
if (!isset($discrMap[$entityClassName])) {
throw QueryException::instanceOfUnrelatedClass($entityClassName, $class->rootEntityName);
}
$sqlParameterList[] = $this->conn->quote($discrMap[$entityClassName]);
}
$sqlParameterList[] = $this->conn->quote($discrMap[$entityClassName]);
}
}

View File

@@ -1089,6 +1089,15 @@ public function __construct()
$typeOptions[] = 'orphanRemoval=' . ($associationMapping['orphanRemoval'] ? 'true' : 'false');
}
if (isset($associationMapping['fetch']) && $associationMapping['fetch'] !== ClassMetadataInfo::FETCH_LAZY) {
$fetchMap = array(
ClassMetadataInfo::FETCH_EXTRA_LAZY => 'EXTRA_LAZY',
ClassMetadataInfo::FETCH_EAGER => 'EAGER',
);
$typeOptions[] = 'fetch="' . $fetchMap[$associationMapping['fetch']] . '"';
}
$lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . '' . $type . '(' . implode(', ', $typeOptions) . ')';
if (isset($associationMapping['joinColumns']) && $associationMapping['joinColumns']) {

View File

@@ -140,9 +140,15 @@ class XmlExporter extends AbstractExporter
if (isset($field['columnName'])) {
$idXml->addAttribute('column', $field['columnName']);
}
if (isset($field['length'])) {
$idXml->addAttribute('length', $field['length']);
}
if (isset($field['associationKey']) && $field['associationKey']) {
$idXml->addAttribute('association-key', 'true');
}
if ($idGeneratorType = $this->_getIdGeneratorTypeString($metadata->generatorType)) {
$generatorXml = $idXml->addChild('generator');
$generatorXml->addAttribute('strategy', $idGeneratorType);

View File

@@ -74,6 +74,10 @@ class CountOutputWalker extends SqlWalker
*/
public function walkSelectStatement(SelectStatement $AST)
{
if ($this->platform->getName() === "mssql") {
$AST->orderByClause = null;
}
$sql = parent::walkSelectStatement($AST);
// Find out the SQL alias of the identifier column of the root entity

View File

@@ -385,22 +385,14 @@ class SchemaTool
}
if (isset($mapping['options'])) {
if (isset($mapping['options']['comment'])) {
$options['comment'] = $mapping['options']['comment'];
$knownOptions = array('comment', 'unsigned', 'fixed', 'default');
unset($mapping['options']['comment']);
}
foreach ($knownOptions as $knownOption) {
if ( isset($mapping['options'][$knownOption])) {
$options[$knownOption] = $mapping['options'][$knownOption];
if (isset($mapping['options']['unsigned'])) {
$options['unsigned'] = $mapping['options']['unsigned'];
unset($mapping['options']['unsigned']);
}
if (isset($mapping['options']['fixed'])) {
$options['fixed'] = $mapping['options']['fixed'];
unset($mapping['options']['fixed']);
unset($mapping['options'][$knownOption]);
}
}
$options['customSchemaOptions'] = $mapping['options'];

View File

@@ -67,6 +67,13 @@ class UnitOfWork implements PropertyChangedListener
*/
const STATE_REMOVED = 4;
/**
* Hint used to collect all primary keys of associated entities during hydration
* and execute it in a dedicated query afterwards
* @see https://doctrine-orm.readthedocs.org/en/latest/reference/dql-doctrine-query-language.html?highlight=eager#temporarily-change-fetch-mode-in-dql
*/
const HINT_DEFEREAGERLOAD = 'deferEagerLoad';
/**
* The identity map that holds references to all managed entities that have
* an identity. The entities are grouped by their class name.
@@ -400,13 +407,15 @@ class UnitOfWork implements PropertyChangedListener
*/
private function computeSingleEntityChangeSet($entity)
{
if ( $this->getEntityState($entity) !== self::STATE_MANAGED) {
throw new \InvalidArgumentException("Entity has to be managed for single computation " . self::objToStr($entity));
$state = $this->getEntityState($entity);
if ($state !== self::STATE_MANAGED && $state !== self::STATE_REMOVED) {
throw new \InvalidArgumentException("Entity has to be managed or scheduled for removal for single computation " . self::objToStr($entity));
}
$class = $this->em->getClassMetadata(get_class($entity));
if ($class->isChangeTrackingDeferredImplicit()) {
if ($state === self::STATE_MANAGED && $class->isChangeTrackingDeferredImplicit()) {
$this->persist($entity);
}
@@ -1376,6 +1385,10 @@ class UnitOfWork implements PropertyChangedListener
return self::STATE_NEW;
}
if ($class->containsForeignIdentifier) {
$id = $this->flattenIdentifier($class, $id);
}
switch (true) {
case ($class->isIdentifierNatural());
// Check for a version field, if available, to avoid a db lookup.
@@ -1688,6 +1701,29 @@ class UnitOfWork implements PropertyChangedListener
return $this->doMerge($entity, $visited);
}
/**
* convert foreign identifiers into scalar foreign key values to avoid object to string conversion failures.
*
* @param ClassMetadata $class
* @param array $id
* @return array
*/
private function flattenIdentifier($class, $id)
{
$flatId = array();
foreach ($id as $idField => $idValue) {
if (isset($class->associationMappings[$idField])) {
$targetClassMetadata = $this->em->getClassMetadata($class->associationMappings[$idField]['targetEntity']);
$associatedId = $this->getEntityIdentifier($idValue);
$flatId[$idField] = $associatedId[$targetClassMetadata->identifier[0]];
}
}
return $flatId;
}
/**
* Executes a merge operation on an entity.
*
@@ -1735,19 +1771,9 @@ class UnitOfWork implements PropertyChangedListener
$this->persistNew($class, $managedCopy);
} else {
$flatId = $id;
if ($class->containsForeignIdentifier) {
// convert foreign identifiers into scalar foreign key
// values to avoid object to string conversion failures.
foreach ($id as $idField => $idValue) {
if (isset($class->associationMappings[$idField])) {
$targetClassMetadata = $this->em->getClassMetadata($class->associationMappings[$idField]['targetEntity']);
$associatedId = $this->getEntityIdentifier($idValue);
$flatId[$idField] = $associatedId[$targetClassMetadata->identifier[0]];
}
}
}
$flatId = ($class->containsForeignIdentifier)
? $this->flattenIdentifier($class, $id)
: $id;
$managedCopy = $this->tryGetById($flatId, $class->rootEntityName);
@@ -1807,7 +1833,7 @@ class UnitOfWork implements PropertyChangedListener
// do not merge fields marked lazy that have not been fetched.
continue;
} else if ( ! $assoc2['isCascadeMerge']) {
if ($this->getEntityState($other, self::STATE_DETACHED) !== self::STATE_MANAGED) {
if ($this->getEntityState($other) === self::STATE_DETACHED) {
$targetClass = $this->em->getClassMetadata($assoc2['targetEntity']);
$relatedId = $targetClass->getIdentifierValues($other);
@@ -1818,6 +1844,7 @@ class UnitOfWork implements PropertyChangedListener
$this->registerManaged($other, $relatedId, array());
}
}
$prop->setValue($managedCopy, $other);
}
} else {
@@ -2209,6 +2236,10 @@ class UnitOfWork implements PropertyChangedListener
*/
public function lock($entity, $lockMode, $lockVersion = null)
{
if ($entity === null) {
throw new \InvalidArgumentException("No entity passed to UnitOfWork#lock().");
}
if ($this->getEntityState($entity, self::STATE_DETACHED) != self::STATE_MANAGED) {
throw ORMInvalidArgumentException::entityNotManaged($entity);
}
@@ -2415,17 +2446,23 @@ class UnitOfWork implements PropertyChangedListener
if ($entity instanceof NotifyPropertyChanged) {
$entity->addPropertyChangedListener($this);
}
// inject ObjectManager into just loaded proxies.
if ($overrideLocalValues && $entity instanceof ObjectManagerAware) {
$entity->injectObjectManager($this->em, $class);
}
} else {
$overrideLocalValues = isset($hints[Query::HINT_REFRESH]);
// If only a specific entity is set to refresh, check that it's the one
if(isset($hints[Query::HINT_REFRESH_ENTITY])) {
$overrideLocalValues = $hints[Query::HINT_REFRESH_ENTITY] === $entity;
}
// inject ObjectManager into just loaded proxies.
if ($overrideLocalValues && $entity instanceof ObjectManagerAware) {
$entity->injectObjectManager($this->em, $class);
}
// inject ObjectManager upon refresh.
if ($overrideLocalValues && $entity instanceof ObjectManagerAware) {
$entity->injectObjectManager($this->em, $class);
}
}
@@ -2529,7 +2566,7 @@ class UnitOfWork implements PropertyChangedListener
// this association is marked as eager fetch, and its an uninitialized proxy (wtf!)
// then we can append this entity for eager loading!
if ($hints['fetchMode'][$class->name][$field] == ClassMetadata::FETCH_EAGER &&
isset($hints['deferEagerLoad']) &&
isset($hints[self::HINT_DEFEREAGERLOAD]) &&
!$targetClass->isIdentifierComposite &&
$newValue instanceof Proxy &&
$newValue->__isInitialized__ === false) {
@@ -2554,7 +2591,7 @@ class UnitOfWork implements PropertyChangedListener
break;
// Deferred eager load only works for single identifier classes
case (isset($hints['deferEagerLoad']) && ! $targetClass->isIdentifierComposite):
case (isset($hints[self::HINT_DEFEREAGERLOAD]) && ! $targetClass->isIdentifierComposite):
// TODO: Is there a faster approach?
$this->eagerLoadingEntities[$targetClass->rootEntityName][$relatedIdHash] = current($associatedId);

View File

@@ -36,7 +36,7 @@ class Version
/**
* Current Doctrine Version
*/
const VERSION = '2.3.2';
const VERSION = '2.3.4';
/**
* Compares a Doctrine version with the current one.

View File

@@ -1118,7 +1118,7 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
$user->username = 'domnikl';
$user->status = 'developer';
$this->setExpectedException('InvalidArgumentException', 'Entity has to be managed for single computation');
$this->setExpectedException('InvalidArgumentException', 'Entity has to be managed or scheduled for removal for single computation');
$this->_em->flush($user);
}
@@ -1202,8 +1202,9 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
/**
* @group DDC-720
* @group DDC-1612
* @group DDC-2267
*/
public function testFlushSingleNewEntity()
public function testFlushSingleNewEntityThenRemove()
{
$user = new CmsUser;
$user->name = 'Dominik';
@@ -1212,6 +1213,14 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->persist($user);
$this->_em->flush($user);
$userId = $user->id;
$this->_em->remove($user);
$this->_em->flush($user);
$this->_em->clear();
$this->assertNull($this->_em->find(get_class($user), $userId));
}
/**

View File

@@ -2,12 +2,9 @@
namespace Doctrine\Tests\ORM\Functional;
require_once __DIR__ . '/../../TestInit.php';
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\ORM\Mapping\ClassMetadataInfo,
Doctrine\Common\Util\Inflector;
class DatabaseDriverTest extends \Doctrine\Tests\OrmFunctionalTestCase
class DatabaseDriverTest extends DatabaseDriverTestCase
{
/**
* @var \Doctrine\DBAL\Schema\AbstractSchemaManager
@@ -148,44 +145,4 @@ class DatabaseDriverTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals(0, count($metadatas['DbdriverBaz']->associationMappings), "no association mappings should be detected.");
}
protected function convertToClassMetadata(array $entityTables, array $manyTables = array())
{
$driver = new \Doctrine\ORM\Mapping\Driver\DatabaseDriver($this->_sm);
$driver->setTables($entityTables, $manyTables);
$metadatas = array();
foreach ($driver->getAllClassNames() AS $className) {
$class = new ClassMetadataInfo($className);
$driver->loadMetadataForClass($className, $class);
$metadatas[$className] = $class;
}
return $metadatas;
}
/**
* @param string $className
* @return ClassMetadata
*/
protected function extractClassMetadata(array $classNames)
{
$classNames = array_map('strtolower', $classNames);
$metadatas = array();
$driver = new \Doctrine\ORM\Mapping\Driver\DatabaseDriver($this->_sm);
foreach ($driver->getAllClassNames() as $className) {
if (!in_array(strtolower($className), $classNames)) {
continue;
}
$class = new ClassMetadataInfo($className);
$driver->loadMetadataForClass($className, $class);
$metadatas[$className] = $class;
}
if (count($metadatas) != count($classNames)) {
$this->fail("Have not found all classes matching the names '" . implode(", ", $classNames) . "' only tables " . implode(", ", array_keys($metadatas)));
}
return $metadatas;
}
}

View File

@@ -0,0 +1,55 @@
<?php
namespace Doctrine\Tests\ORM\Functional;
use Doctrine\Tests\OrmFunctionalTestCase;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
/**
* Common BaseClass for DatabaseDriver Tests
*/
abstract class DatabaseDriverTestCase extends OrmFunctionalTestCase
{
protected function convertToClassMetadata(array $entityTables, array $manyTables = array())
{
$sm = $this->_em->getConnection()->getSchemaManager();
$driver = new \Doctrine\ORM\Mapping\Driver\DatabaseDriver($sm);
$driver->setTables($entityTables, $manyTables);
$metadatas = array();
foreach ($driver->getAllClassNames() AS $className) {
$class = new ClassMetadataInfo($className);
$driver->loadMetadataForClass($className, $class);
$metadatas[$className] = $class;
}
return $metadatas;
}
/**
* @param string $className
* @return ClassMetadata
*/
protected function extractClassMetadata(array $classNames)
{
$classNames = array_map('strtolower', $classNames);
$metadatas = array();
$sm = $this->_em->getConnection()->getSchemaManager();
$driver = new \Doctrine\ORM\Mapping\Driver\DatabaseDriver($sm);
foreach ($driver->getAllClassNames() as $className) {
if (!in_array(strtolower($className), $classNames)) {
continue;
}
$class = new ClassMetadataInfo($className);
$driver->loadMetadataForClass($className, $class);
$metadatas[$className] = $class;
}
if (count($metadatas) != count($classNames)) {
$this->fail("Have not found all classes matching the names '" . implode(", ", $classNames) . "' only tables " . implode(", ", array_keys($metadatas)));
}
return $metadatas;
}
}

View File

@@ -173,14 +173,36 @@ class OneToManyBidirectionalAssociationTest extends \Doctrine\Tests\OrmFunctiona
$this->assertInstanceOf('Doctrine\Common\Collections\Collection', $results);
$this->assertEquals(2, count($results));
}
/**
* @group DDC-2340
*/
public function testMatchingOnDirtyCollection()
{
$this->_createFixture();
$product = $this->_em->find('Doctrine\Tests\Models\ECommerce\ECommerceProduct', $this->product->getId());
$thirdFeature = new ECommerceFeature();
$thirdFeature->setDescription('Model writing tutorial');
$features = $product->getFeatures();
$features->add($thirdFeature);
$results = $features->matching(new Criteria(
Criteria::expr()->eq('description', 'Model writing tutorial')
));
$this->assertEquals(2, count($results));
}
public function testMatchingBis()
{
$this->_createFixture();
$product = $this->_em->find('Doctrine\Tests\Models\ECommerce\ECommerceProduct', $this->product->getId());
$features = $product->getFeatures();
$thirdFeature = new ECommerceFeature();
$thirdFeature->setDescription('Third feature');
$product->addFeature($thirdFeature);

View File

@@ -0,0 +1,60 @@
<?php
namespace Doctrine\Tests\ORM\Functional\SchemaTool;
use Doctrine\ORM\Tools;
class DBAL483Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public function setUp()
{
parent::setUp();
$conn = $this->_em->getConnection();
if ($conn->getDatabasePlatform()->getName() === 'sqlite') {
$this->markTestSkipped('Sqlite does not support ALTER TABLE');
}
$this->schemaTool = new Tools\SchemaTool($this->_em);
}
/**
* @group DBAL-483
*/
public function testDefaultValueIsComparedCorrectly()
{
$class = $this->_em->getClassMetadata(__NAMESPACE__ . '\\DBAL483Default');
$this->schemaTool->createSchema(array($class));
$updateSql = $this->schemaTool->getUpdateSchemaSql(array($class));
$updateSql = array_filter($updateSql, function ($sql) {
return strpos($sql, 'DBAL483') !== false;
});
$this->assertEquals(0, count($updateSql));
}
}
/**
* @Entity
*/
class DBAL483Default
{
/**
* @Id @Column(type="integer") @GeneratedValue
*/
public $id;
/**
* @Column(type="integer", options={"default": 0})
*/
public $num;
/**
* @Column(type="string", options={"default": "foo"})
*/
public $str = "foo";
}

View File

@@ -4,9 +4,6 @@ namespace Doctrine\Tests\ORM\Functional\SchemaTool;
use Doctrine\ORM\Tools;
require_once __DIR__ . '/../../../TestInit.php';
/**
* WARNING: This test should be run as last test! It can affect others very easily!
*/
@@ -15,7 +12,8 @@ class DDC214Test extends \Doctrine\Tests\OrmFunctionalTestCase
private $classes = array();
private $schemaTool = null;
public function setUp() {
public function setUp()
{
parent::setUp();
$conn = $this->_em->getConnection();
@@ -88,4 +86,4 @@ class DDC214Test extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals(0, count($sql), "SQL: " . implode(PHP_EOL, $sql));
}
}
}

View File

@@ -461,4 +461,22 @@ class DDC117Test extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals($before + 3, count($data));
}
/**
* @group DDC-2246
*/
public function testGetEntityState()
{
$this->article1 = $this->_em->find("Doctrine\Tests\Models\DDC117\DDC117Article", $this->article1->id());
$this->article2 = $this->_em->find("Doctrine\Tests\Models\DDC117\DDC117Article", $this->article2->id());
$this->reference = new DDC117Reference($this->article2, $this->article1, "Test-Description");
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_NEW, $this->_em->getUnitOfWork()->getEntityState($this->reference));
$idCriteria = array('source' => $this->article1->id(), 'target' => $this->article2->id());
$reference = $this->_em->find("Doctrine\Tests\Models\DDC117\DDC117Reference", $idCriteria);
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_MANAGED, $this->_em->getUnitOfWork()->getEntityState($reference));
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Tests\Models\CMS\CmsUser;
use Doctrine\Tests\Models\CMS\CmsEmail;
/**
* @group DDC-1666
*/
class DDC1666Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public function setUp()
{
$this->useModelSet('cms');
parent::setUp();
}
public function testGivenOrphanRemovalOneToOne_WhenReplacing_ThenNoUniqueConstraintError()
{
$user = new CmsUser();
$user->name = "Benjamin";
$user->username = "beberlei";
$user->status = "something";
$user->setEmail($email = new CmsEmail());
$email->setEmail("kontakt@beberlei.de");
$this->_em->persist($user);
$this->_em->flush();
$this->assertTrue($this->_em->contains($email));
$user->setEmail($newEmail = new CmsEmail());
$newEmail->setEmail("benjamin.eberlei@googlemail.com");
$this->_em->flush();
$this->assertFalse($this->_em->contains($email));
}
}

View File

@@ -0,0 +1,110 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Tests\Models\Company\CompanyEmployee;
/**
* @group DDC-2090
*/
class DDC2090Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public function setUp()
{
$this->useModelSet('company');
parent::setUp();
}
public function testIssue()
{
$className = 'Doctrine\Tests\Models\Company\CompanyEmployee';
$date1 = new \DateTime('2011-11-11 11:11:11');
$date2 = new \DateTime('2012-12-12 12:12:12');
$employee1 = new CompanyEmployee;
$employee2 = new CompanyEmployee;
$employee1->setName("Fabio B. Silva");
$employee1->setStartDate(new \DateTime('yesterday'));
$employee1->setDepartment("R&D");
$employee1->setSalary(100);
$employee2->setName("Doctrine Bot");
$employee1->setStartDate(new \DateTime('yesterday'));
$employee2->setDepartment("QA");
$employee2->setSalary(100);
$this->_em->persist($employee1);
$this->_em->persist($employee2);
$this->_em->flush();
$this->_em->clear();
$this->_em->createQueryBuilder()
->update($className, 'e')
->set('e.startDate', ':date')
->set('e.salary', ':salary')
->where('e = :e')
->setParameters(array(
'e' => $employee1,
'date' => $date1,
'salary' => 101,
))
->getQuery()
->useQueryCache(true)
->execute();
$this->_em->createQueryBuilder()
->update($className, 'e')
->set('e.startDate', ':date')
->set('e.salary', ':salary')
->where('e = :e')
->setParameters(array(
'e' => $employee2,
'date' => $date2,
'salary' => 102,
))
->getQuery()
->useQueryCache(true)
->execute();
$this->_em->clear();
$e1 = $this->_em->find($className, $employee1->getId());
$e2 = $this->_em->find($className, $employee2->getId());
$this->assertEquals(101, $e1->getSalary());
$this->assertEquals(102, $e2->getSalary());
$this->assertEquals($date1, $e1->getStartDate());
$this->assertEquals($date2, $e2->getStartDate());
$this->_em->createQueryBuilder()
->update($className, 'e')
->set('e.startDate', '?1')
->set('e.salary', '?2')
->where('e = ?0')
->setParameters(array($employee1, $date1, 101))
->getQuery()
->useQueryCache(true)
->execute();
$this->_em->createQueryBuilder()
->update($className, 'e')
->set('e.startDate', '?1')
->set('e.salary', '?2')
->where('e = ?0')
->setParameters(array($employee2, $date2, 102))
->getQuery()
->useQueryCache(true)
->execute();
$this->_em->clear();
$e1 = $this->_em->find($className, $employee1->getId());
$e2 = $this->_em->find($className, $employee2->getId());
$this->assertEquals(101, $e1->getSalary());
$this->assertEquals(102, $e2->getSalary());
$this->assertEquals($date1, $e1->getStartDate());
$this->assertEquals($date2, $e2->getStartDate());
}
}

View File

@@ -0,0 +1,71 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Common\Persistence\ObjectManagerAware;
require_once __DIR__ . '/../../../TestInit.php';
/**
* @group DDC-2231
*/
class DDC2231Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
parent::setUp();
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2231EntityY'),
));
}
public function testInjectObjectManagerInProxyIfInitializedInUow()
{
$y1 = new DDC2231EntityY;
$this->_em->persist($y1);
$this->_em->flush();
$this->_em->clear();
$y1ref = $this->_em->getReference(get_class($y1), $y1->id);
$this->assertInstanceOf('Doctrine\ORM\Proxy\Proxy', $y1ref);
$this->assertFalse($y1ref->__isInitialized__);
$id = $y1ref->doSomething();
$this->assertTrue($y1ref->__isInitialized__);
$this->assertEquals($this->_em, $y1ref->om);
}
}
/** @Entity @Table(name="ddc2231_y") */
class DDC2231EntityY implements ObjectManagerAware
{
/**
* @Id @Column(type="integer") @GeneratedValue
*/
public $id;
public $om;
public function injectObjectManager(ObjectManager $objectManager, ClassMetadata $classMetadata)
{
$this->om = $objectManager;
}
public function getId()
{
return $this->id;
}
public function doSomething()
{
}
}

View File

@@ -0,0 +1,229 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @group DDC-2252
*/
class DDC2252Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
private $user;
private $merchant;
private $membership;
private $privileges = array();
protected function setUp()
{
parent::setUp();
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\Ticket\DDC2252User'),
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\Ticket\DDC2252Privilege'),
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\Ticket\DDC2252Membership'),
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\Ticket\DDC2252MerchantAccount'),
));
$this->loadFixtures();
}
public function loadFixtures()
{
$this->user = new DDC2252User;
$this->merchant = new DDC2252MerchantAccount;
$this->membership = new DDC2252Membership($this->user, $this->merchant);
$this->privileges[] = new DDC2252Privilege;
$this->privileges[] = new DDC2252Privilege;
$this->privileges[] = new DDC2252Privilege;
$this->membership->addPrivilege($this->privileges[0]);
$this->membership->addPrivilege($this->privileges[1]);
$this->membership->addPrivilege($this->privileges[2]);
$this->_em->persist($this->user);
$this->_em->persist($this->merchant);
$this->_em->persist($this->privileges[0]);
$this->_em->persist($this->privileges[1]);
$this->_em->persist($this->privileges[2]);
$this->_em->flush();
$this->_em->persist($this->membership);
$this->_em->flush();
$this->_em->clear();
}
public function testIssue()
{
$identifier = array(
'merchantAccount' => $this->merchant->getAccountid(),
'userAccount' => $this->user->getUid(),
);
$class = 'Doctrine\Tests\ORM\Functional\Ticket\DDC2252Membership';
$membership = $this->_em->find($class, $identifier);
$this->assertInstanceOf($class, $membership);
$this->assertCount(3, $membership->getPrivileges());
$membership->getPrivileges()->remove(2);
$this->_em->persist($membership);
$this->_em->flush();
$this->_em->clear();
$membership = $this->_em->find($class, $identifier);
$this->assertInstanceOf($class, $membership);
$this->assertCount(2, $membership->getPrivileges());
$membership->getPrivileges()->clear();
$this->_em->persist($membership);
$this->_em->flush();
$this->_em->clear();
$membership = $this->_em->find($class, $identifier);
$this->assertInstanceOf($class, $membership);
$this->assertCount(0, $membership->getPrivileges());
$membership->addPrivilege($privilege3 = new DDC2252Privilege);
$this->_em->persist($privilege3);
$this->_em->persist($membership);
$this->_em->flush();
$this->_em->clear();
$membership = $this->_em->find($class, $identifier);
$this->assertInstanceOf($class, $membership);
$this->assertCount(1, $membership->getPrivileges());
}
}
/**
* @Entity()
* @Table(name="ddc2252_acl_privilege")
*/
class DDC2252Privilege
{
/**
* @Id
* @GeneratedValue
* @Column(type="integer")
*/
protected $privilegeid;
public function getPrivilegeid()
{
return $this->privilegeid;
}
}
/**
* @Entity
* @Table(name="ddc2252_mch_account")
*/
class DDC2252MerchantAccount
{
/**
* @Id
* @Column(type="integer")
*/
protected $accountid = 111;
public function getAccountid()
{
return $this->accountid;
}
}
/**
* @Entity
* @Table(name="ddc2252_user_account")
*/
class DDC2252User {
/**
* @Id
* @Column(type="integer")
*/
protected $uid = 222;
/**
* @OneToMany(targetEntity="DDC2252Membership", mappedBy="userAccount", cascade={"persist"})
* @JoinColumn(name="uid", referencedColumnName="uid")
*/
protected $memberships;
public function __construct()
{
$this->memberships = new ArrayCollection;
}
public function getUid()
{
return $this->uid;
}
public function getMemberships()
{
return $this->memberships;
}
public function addMembership(DDC2252Membership $membership)
{
$this->memberships[] = $membership;
}
}
/**
* @Entity
* @Table(name="ddc2252_mch_account_member")
* @HasLifecycleCallbacks
*/
class DDC2252Membership
{
/**
* @Id
* @ManyToOne(targetEntity="DDC2252User", inversedBy="memberships")
* @JoinColumn(name="uid", referencedColumnName="uid")
*/
protected $userAccount;
/**
* @Id
* @ManyToOne(targetEntity="DDC2252MerchantAccount")
* @JoinColumn(name="mch_accountid", referencedColumnName="accountid")
*/
protected $merchantAccount;
/**
* @ManyToMany(targetEntity="DDC2252Privilege", indexBy="privilegeid")
* @JoinTable(name="ddc2252_user_mch_account_privilege",
* joinColumns={
* @JoinColumn(name="mch_accountid", referencedColumnName="mch_accountid"),
* @JoinColumn(name="uid", referencedColumnName="uid")
* },
* inverseJoinColumns={
* @JoinColumn(name="privilegeid", referencedColumnName="privilegeid")
* }
* )
*/
protected $privileges;
public function __construct(DDC2252User $user, DDC2252MerchantAccount $merchantAccount)
{
$this->userAccount = $user;
$this->merchantAccount = $merchantAccount;
$this->privileges = new ArrayCollection();
}
public function addPrivilege($privilege)
{
$this->privileges[] = $privilege;
}
public function getPrivileges()
{
return $this->privileges;
}
}

View File

@@ -0,0 +1,109 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\DBAL\Logging\DebugStack;
/**
* @group DDC-2346
*/
class DDC2346Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
/**
* @var \Doctrine\DBAL\Logging\DebugStack
*/
protected $logger;
/**
* {@inheritDoc}
*/
protected function setup()
{
parent::setup();
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2346Foo'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2346Bar'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2346Baz'),
));
$this->logger = new DebugStack();
}
/**
* Verifies that fetching a OneToMany association with fetch="EAGER" does not cause N+1 queries
*/
public function testIssue()
{
$foo1 = new DDC2346Foo();
$foo2 = new DDC2346Foo();
$baz1 = new DDC2346Baz();
$baz2 = new DDC2346Baz();
$baz1->foo = $foo1;
$baz2->foo = $foo2;
$foo1->bars[] = $baz1;
$foo1->bars[] = $baz2;
$this->_em->persist($foo1);
$this->_em->persist($foo2);
$this->_em->persist($baz1);
$this->_em->persist($baz2);
$this->_em->flush();
$this->_em->clear();
$this->_em->getConnection()->getConfiguration()->setSQLLogger($this->logger);
$fetchedBazs = $this->_em->getRepository(__NAMESPACE__ . '\\DDC2346Baz')->findAll();
$this->assertCount(2, $fetchedBazs);
$this->assertCount(2, $this->logger->queries, 'The total number of executed queries is 2, and not n+1');
}
}
/** @Entity */
class DDC2346Foo
{
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
/**
* @var DDC2346Bar[]|\Doctrine\Common\Collections\Collection
*
* @OneToMany(targetEntity="DDC2346Bar", mappedBy="foo")
*/
public $bars;
/** Constructor */
public function __construct() {
$this->bars = new ArrayCollection();
}
}
/**
* @Entity
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="discr", type="string")
* @DiscriminatorMap({"baz" = "DDC2346Baz"})
*/
class DDC2346Bar
{
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
/** @ManyToOne(targetEntity="DDC2346Foo", inversedBy="bars", fetch="EAGER") */
public $foo;
}
/**
* @Entity
*/
class DDC2346Baz extends DDC2346Bar
{
}

View File

@@ -0,0 +1,30 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Tests\ORM\Functional\DatabaseDriverTestCase;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
class DDC2387Test extends DatabaseDriverTestCase
{
/**
* @group DDC-2387
*/
public function testCompositeAssociationKeyDetection()
{
$product = new \Doctrine\DBAL\Schema\Table('ddc2387_product');
$product->addColumn('id', 'integer');
$product->setPrimaryKey(array('id'));
$attributes = new \Doctrine\DBAL\Schema\Table('ddc2387_attributes');
$attributes->addColumn('product_id', 'integer');
$attributes->addColumn('attribute_name', 'string');
$attributes->setPrimaryKey(array('product_id', 'attribute_name'));
$attributes->addForeignKeyConstraint('ddc2387_product', array('product_id'), array('product_id'));
$metadata = $this->convertToClassMetadata(array($product, $attributes), array());
$this->assertEquals(ClassMetadataInfo::GENERATOR_TYPE_NONE, $metadata['Ddc2387Attributes']->generatorType);
$this->assertEquals(ClassMetadataInfo::GENERATOR_TYPE_AUTO, $metadata['Ddc2387Product']->generatorType);
}
}

View File

@@ -0,0 +1,72 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\ORM\UnitOfWork;
use Doctrine\Tests\Models\CMS\CmsUser;
use Doctrine\Tests\Models\CMS\CmsArticle;
/**
* @group DDC-2409
*/
class DDC2409Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public function setUp()
{
$this->useModelSet('cms');
parent::setUp();
}
public function testIssue()
{
$em = $this->_em;
$uow = $em->getUnitOfWork();
$originalArticle = new CmsArticle();
$originalUser = new CmsUser();
$originalArticle->topic = 'Unit Test';
$originalArticle->text = 'How to write a test';
$originalUser->name = 'Doctrine Bot';
$originalUser->username = 'DoctrineBot';
$originalUser->status = 'active';
$originalUser->addArticle($originalArticle);
$em->persist($originalUser);
$em->persist($originalArticle);
$em->flush();
$em->clear();
$article = $em->find('Doctrine\Tests\Models\CMS\CmsArticle', $originalArticle->id);
$user = new CmsUser();
$user->name = 'Doctrine Bot 2.0';
$user->username = 'BotDoctrine2';
$user->status = 'new';
$article->setAuthor($user);
$this->assertEquals(UnitOfWork::STATE_DETACHED, $uow->getEntityState($originalArticle));
$this->assertEquals(UnitOfWork::STATE_DETACHED, $uow->getEntityState($originalUser));
$this->assertEquals(UnitOfWork::STATE_MANAGED, $uow->getEntityState($article));
$this->assertEquals(UnitOfWork::STATE_NEW, $uow->getEntityState($user));
$em->detach($user);
$em->detach($article);
$userMerged = $em->merge($user);
$articleMerged = $em->merge($article);
$this->assertEquals(UnitOfWork::STATE_NEW, $uow->getEntityState($user));
$this->assertEquals(UnitOfWork::STATE_DETACHED, $uow->getEntityState($article));
$this->assertEquals(UnitOfWork::STATE_MANAGED, $uow->getEntityState($userMerged));
$this->assertEquals(UnitOfWork::STATE_MANAGED, $uow->getEntityState($articleMerged));
$this->assertNotSame($user, $userMerged);
$this->assertNotSame($article, $articleMerged);
$this->assertNotSame($userMerged, $articleMerged->user);
$this->assertSame($user, $articleMerged->user);
}
}

View File

@@ -34,4 +34,28 @@ class SimpleObjectHydratorTest extends HydrationTestCase
$hydrator = new \Doctrine\ORM\Internal\Hydration\SimpleObjectHydrator($this->_em);
$hydrator->hydrateAll($stmt, $rsm);
}
public function testExtraFieldInResultSetShouldBeIgnore()
{
$rsm = new ResultSetMapping;
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsAddress', 'a');
$rsm->addFieldResult('a', 'a__id', 'id');
$rsm->addFieldResult('a', 'a__city', 'city');
$resultSet = array(
array(
'a__id' => '1',
'a__city' => 'Cracow',
'doctrine_rownum' => '1'
),
);
$expectedEntity = new \Doctrine\Tests\Models\CMS\CmsAddress();
$expectedEntity->id = 1;
$expectedEntity->city = 'Cracow';
$stmt = new HydratorMockStatement($resultSet);
$hydrator = new \Doctrine\ORM\Internal\Hydration\SimpleObjectHydrator($this->_em);
$result = $hydrator->hydrateAll($stmt, $rsm);
$this->assertEquals($result[0], $expectedEntity);
}
}

View File

@@ -156,6 +156,8 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
{
$this->assertTrue($class->isVersioned);
$this->assertEquals("version", $class->versionField);
$this->assertFalse(isset($class->fieldMappings['version']['version']));
}
/**
@@ -475,24 +477,22 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
/**
* @group DDC-889
* @expectedException Doctrine\ORM\Mapping\MappingException
* @expectedExceptionMessage Class "Doctrine\Tests\Models\DDC889\DDC889Class" sub class of "Doctrine\Tests\Models\DDC889\DDC889SuperClass" is not a valid entity or mapped super class.
*/
public function testInvalidEntityOrMappedSuperClassShouldMentionParentClasses()
{
$this->setExpectedException('Doctrine\ORM\Mapping\MappingException', 'Class "Doctrine\Tests\Models\DDC889\DDC889Class" sub class of "Doctrine\Tests\Models\DDC889\DDC889SuperClass" is not a valid entity or mapped super class.');
$this->createClassMetadata('Doctrine\Tests\Models\DDC889\DDC889Class');
}
/**
* @group DDC-889
* @expectedException Doctrine\ORM\Mapping\MappingException
* @expectedExceptionMessage No identifier/primary key specified for Entity "Doctrine\Tests\Models\DDC889\DDC889Entity" sub class of "Doctrine\Tests\Models\DDC889\DDC889SuperClass". Every Entity must have an identifier/primary key.
*/
public function testIdentifierRequiredShouldMentionParentClasses()
{
$factory = $this->createClassMetadataFactory();
$this->setExpectedException('Doctrine\ORM\Mapping\MappingException', 'No identifier/primary key specified for Entity "Doctrine\Tests\Models\DDC889\DDC889Entity" sub class of "Doctrine\Tests\Models\DDC889\DDC889SuperClass". Every Entity must have an identifier/primary key.');
$factory->getMetadataFor('Doctrine\Tests\Models\DDC889\DDC889Entity');
}
@@ -509,7 +509,7 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
*/
public function testNamedNativeQuery()
{
$class = $this->createClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress');
//named native query
@@ -538,7 +538,7 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
$this->assertArrayHasKey('mapping-count', $class->sqlResultSetMappings);
$this->assertArrayHasKey('mapping-find-all', $class->sqlResultSetMappings);
$this->assertArrayHasKey('mapping-without-fields', $class->sqlResultSetMappings);
$findAllMapping = $class->getSqlResultSetMapping('mapping-find-all');
$this->assertEquals('mapping-find-all', $findAllMapping['name']);
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsAddress', $findAllMapping['entities'][0]['entityClass']);
@@ -550,7 +550,7 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals('mapping-without-fields', $withoutFieldsMapping['name']);
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsAddress', $withoutFieldsMapping['entities'][0]['entityClass']);
$this->assertEquals(array(), $withoutFieldsMapping['entities'][0]['fields']);
$countMapping = $class->getSqlResultSetMapping('mapping-count');
$this->assertEquals('mapping-count', $countMapping['name']);
$this->assertEquals(array('name'=>'count'), $countMapping['columns'][0]);
@@ -638,7 +638,7 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
$adminMetadata = $factory->getMetadataFor('Doctrine\Tests\Models\DDC964\DDC964Admin');
$guestMetadata = $factory->getMetadataFor('Doctrine\Tests\Models\DDC964\DDC964Guest');
// assert groups association mappings
$this->assertArrayHasKey('groups', $guestMetadata->associationMappings);
$this->assertArrayHasKey('groups', $adminMetadata->associationMappings);
@@ -697,7 +697,7 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals($guestAddress['isCascadeRefresh'], $adminAddress['isCascadeRefresh']);
$this->assertEquals($guestAddress['isCascadeMerge'], $adminAddress['isCascadeMerge']);
$this->assertEquals($guestAddress['isCascadeDetach'], $adminAddress['isCascadeDetach']);
// assert override
$this->assertEquals('address_id', $guestAddress['joinColumns'][0]['name']);
$this->assertEquals(array('address_id'=>'id'), $guestAddress['sourceToTargetKeyColumns']);
@@ -1071,7 +1071,7 @@ class DDC807Entity
* @GeneratedValue(strategy="NONE")
**/
public $id;
public static function loadMetadata(ClassMetadataInfo $metadata)
{
$metadata->mapField(array(

View File

@@ -5,4 +5,4 @@ Doctrine\Tests\Models\DDC1476\DDC1476EntityWithDefaultFieldType:
generator:
strategy: NONE
fields:
name:
name: ~

View File

@@ -1,7 +1,7 @@
Doctrine\Tests\ORM\Mapping\DDC2069Entity:
type: entity
id:
id:
id: ~
fields:
name:
type: string ( 255 )
@@ -12,4 +12,4 @@ Doctrine\Tests\ORM\Mapping\DDC2069Entity:
columns: name, value
indexes:
0:
columns: value, name
columns: value, name

View File

@@ -409,4 +409,18 @@ class ExprTest extends \Doctrine\Tests\OrmTestCase
$select = new Expr\Select(array('foo', 'bar'));
$this->assertEquals(array('foo', 'bar'), $select->getParts());
}
public function testAddEmpty() {
$andExpr = $this->_expr->andx();
$andExpr->add($this->_expr->andx());
$this->assertEquals(0, $andExpr->count());
}
public function testAddNull() {
$andExpr = $this->_expr->andx();
$andExpr->add(null);
$this->assertEquals(0, $andExpr->count());
}
}

View File

@@ -163,4 +163,16 @@ class QueryTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals('cities', $parameter->getName());
$this->assertEquals($cities, $parameter->getValue());
}
/**
* @group DDC-2224
*/
public function testProcessParameterValueClassMetadata()
{
$query = $this->_em->createQuery("SELECT a FROM Doctrine\Tests\Models\CMS\CmsAddress a WHERE a.city IN (:cities)");
$this->assertEquals(
'Doctrine\Tests\Models\CMS\CmsAddress',
$query->processParameterValue($this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress'))
);
}
}

View File

@@ -474,7 +474,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
{
$this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF ?1",
"SELECT c0_.id AS id0, c0_.name AS name1, c0_.discr AS discr2 FROM company_persons c0_ WHERE c0_.discr IN ('employee')",
"SELECT c0_.id AS id0, c0_.name AS name1, c0_.discr AS discr2 FROM company_persons c0_ WHERE c0_.discr IN (?)",
array(), array(1 => $this->_em->getClassMetadata('Doctrine\Tests\Models\Company\CompanyEmployee'))
);
}

View File

@@ -137,6 +137,19 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
'SELECT u, a FROM Doctrine\Tests\Models\CMS\CmsUser u INNER JOIN u.articles a ON u.id = a.author_id'
);
}
public function testComplexInnerJoinWithIndexBy()
{
$qb = $this->_em->createQueryBuilder()
->select('u', 'a')
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->innerJoin('u.articles', 'a', 'ON', 'u.id = a.author_id', 'a.name');
$this->assertValidQueryBuilder(
$qb,
'SELECT u, a FROM Doctrine\Tests\Models\CMS\CmsUser u INNER JOIN u.articles a INDEX BY a.name ON u.id = a.author_id'
);
}
public function testLeftJoin()
{

View File

@@ -64,6 +64,7 @@ class EntityGeneratorTest extends \Doctrine\Tests\OrmTestCase
$metadata->mapManyToMany(array(
'fieldName' => 'comments',
'targetEntity' => 'Doctrine\Tests\ORM\Tools\EntityGeneratorComment',
'fetch' => ClassMetadataInfo::FETCH_EXTRA_LAZY,
'joinTable' => array(
'name' => 'book_comment',
'joinColumns' => array(array('name' => 'book_id', 'referencedColumnName' => 'id')),
@@ -223,6 +224,8 @@ class EntityGeneratorTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals($cm->identifier, $metadata->identifier);
$this->assertEquals($cm->idGenerator, $metadata->idGenerator);
$this->assertEquals($cm->customRepositoryClassName, $metadata->customRepositoryClassName);
$this->assertEquals(ClassMetadataInfo::FETCH_EXTRA_LAZY, $cm->associationMappings['comments']['fetch']);
}
public function testLoadPrefixedMetadata()

View File

@@ -41,5 +41,22 @@ class CountOutputWalkerTest extends PaginationTestCase
"SELECT COUNT(*) AS dctrn_count FROM (SELECT DISTINCT id1 FROM (SELECT count(u0_.id) AS sclr0, g1_.id AS id1, u0_.id AS id2 FROM groups g1_ LEFT JOIN user_group u2_ ON g1_.id = u2_.group_id LEFT JOIN User u0_ ON u0_.id = u2_.user_id GROUP BY g1_.id HAVING sclr0 > 0) dctrn_result) dctrn_table", $query->getSql()
);
}
public function testCountQueryOrderBySqlServer()
{
if ($this->entityManager->getConnection()->getDatabasePlatform()->getName() !== "mssql") {
$this->markTestSkipped('SQLServer only test.');
}
$query = $this->entityManager->createQuery(
'SELECT p FROM Doctrine\Tests\ORM\Tools\Pagination\BlogPost p ORDER BY p.id');
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Tools\Pagination\CountOutputWalker');
$query->setFirstResult(null)->setMaxResults(null);
$this->assertEquals(
"SELECT COUNT(*) AS dctrn_count FROM (SELECT DISTINCT id0 FROM (SELECT b0_.id AS id0, b0_.author_id AS author_id1, b0_.category_id AS category_id2 FROM BlogPost b0_) dctrn_result) dctrn_table",
$query->getSql()
);
}
}

View File

@@ -227,6 +227,15 @@ class UnitOfWorkTest extends \Doctrine\Tests\OrmTestCase
// This commit should not raise an E_NOTICE
$this->_unitOfWork->commit();
}
/**
* @group DDC-1984
*/
public function testLockWithoutEntityThrowsException()
{
$this->setExpectedException('InvalidArgumentException');
$this->_unitOfWork->lock(null, null, null);
}
}
/**