Compare commits

...

91 Commits

Author SHA1 Message Date
Marco Pivetta
bc4ddbfb01 Release 2.5.4 2016-01-05 22:34:58 +01:00
Marco Pivetta
14499f5021 Removing coveralls installation/reporting from 2.5: not required 2016-01-05 22:25:57 +01:00
Marco Pivetta
aae43cbb77 Merge branch 'hotfix/#1568-identifier-type-cached-incorrectly-backport-2-5' into 2.5
Backport #1568 to 2.5
2016-01-05 22:14:40 +01:00
Jan Langer
db6cb8dedc Second level cache stores identifier with correct type even if findById is called with wrong identifier type 2016-01-05 22:13:03 +01:00
Guido Contreras Woda
5092da074a Test that reflects the issue described in http://www.doctrine-project.org/jira/browse/DDC-3967 2016-01-05 22:12:55 +01:00
Marco Pivetta
1c6524db55 Bumping to development version 2.5.4-DEV 2015-12-25 16:50:31 +01:00
Marco Pivetta
d9fc5388f1 2.5.3 release 2015-12-25 16:50:05 +01:00
Marco Pivetta
d2e51eacff Reverting incorrect DBAL 2.6 bump 2015-12-25 16:49:48 +01:00
Marco Pivetta
5a6ae4686f Allowing doctrine/common 2.6 2015-12-25 15:58:40 +01:00
Marco Pivetta
8b8a1cbe81 Merge branch 'hotfix/common-2.6-upgrade-compat-2.5' into 2.5 2015-12-25 15:26:15 +01:00
Marco Pivetta
27a5284899 doctrine/common 2.6.0 compat
Less strict assertion - no need to check the exact file name
2015-12-25 15:24:37 +01:00
Marco Pivetta
0086d17afe Common 2.6 compatibility
Internal structure of the ArrayCache has changed, therefore we should fix the tests depending on it instead
2015-12-25 15:24:32 +01:00
Marco Pivetta
ab62167c8a Merge branch 'hotfix/#4884-support-proxy-php7-hints-generation-2.5' into 2.5
Close #4884
2015-12-25 14:47:12 +01:00
Marco Pivetta
6d43195669 #4884 - allow installation of doctrine/common 2.6.x, which allows generating type-hints on proxies 2015-12-25 14:46:59 +01:00
Marco Pivetta
7065ff0ac9 Merge branch 'hotfix/#1572-target-entity-resolver-dql-with-interfaces-support' into 2.5
Close #1572
2015-12-11 21:35:18 +01:00
Marco Pivetta
aa61328e90 #1572 - test coverage - interfaces should also resolve to target entities when in DQL 2015-12-11 21:30:19 +01:00
Marco Pivetta
62719f2a97 Merge branch 'hotfix/#1573-merge-associated-versioned-entity-2.5.x' into 2.5
Close #1573
2015-12-11 20:19:10 +01:00
Marco Pivetta
66770c5bfe #1573 - correcting test asset namespace, removing unused properties and bi-directional association 2015-12-11 20:18:53 +01:00
Marco Pivetta
42691c21b4 Removing empty newline 2015-12-11 20:18:48 +01:00
Marco Pivetta
596e895763 #1573 - correcting docblock arguments/description 2015-12-11 20:18:42 +01:00
Marco Pivetta
d5c82094df #1573 removing unused API 2015-12-11 20:18:37 +01:00
bilouwan
4148220f9c Refactor testing Proxy not initilized 2015-12-11 20:18:31 +01:00
bilouwan
e173c930ec Fix superflous whitespaces & empty lines 2015-12-11 20:18:25 +01:00
bilouwan
7071984559 Fix compatibility with php5.4 2015-12-11 20:18:19 +01:00
bilouwan
216c466233 Unit test & fix for merge versionned entity 2015-12-11 20:18:12 +01:00
Marco Pivetta
65f5777e60 Merge branch 'hotfix/php7-xdebug-incompatibility-fixes-2.5.x' into 2.5
Close #5547
2015-12-11 19:35:42 +01:00
Marco Pivetta
6e3ce26429 Correcting minor test case incompatibility with XDebug 2.4.x
In PHP 5.x + XDebug < 2.4, the output would be "string:..."
In PHP 7.x + XDebug >= 2.4, the output would be "the/file/name.php:11:string:..."

This is an improvement in XDebug that is quite annoying for our purposes, but is actually welcome to most users anyway.

This commit simply fixes that incompatibility
2015-12-11 19:35:28 +01:00
oprokidnev
752d4f9eac Target entity resolver for DQL
Since we have target entity resolver in doctrine this class check is not enought.
To gain interface resolution it is better to add interface check in addition to class_check here.
2015-11-27 16:00:56 +05:00
Marco Pivetta
2983081a60 Bumping current dev version to 2.5.3-DEV 2015-11-23 13:44:56 +01:00
Marco Pivetta
464b5fdbfb Release 2.5.2 2015-11-23 13:44:25 +01:00
Guilherme Blanco
04254a8e34 Merge pull request #1512 from neoglez/2.5
Backport of "LimitSubqueryOutputWalker: fix aliasing of property in OrderBy from MappedSuperclass"
2015-11-15 22:08:59 -05:00
Guilherme Blanco
1d213e6733 Merge pull request #1543 from nicolas-grekas/dep-30
Allow symfony 3.0 components on 2.5
2015-11-09 14:54:44 -05:00
Klein Thomas
bc82e94afc Move to 2.5 section 2015-11-09 03:56:16 +00:00
Klein Thomas
b9af1c8fa5 Update Upgrade.md after minor bc break in 2.5.1
The introduction of the second parameter in EntityRepository#createQueryBuilder generates a runtime notice if you have a sub-class of EntityRepository that has a second parameter in the createQueryBuilder method
2015-11-09 03:56:07 +00:00
Pantel
d606efd4eb [DDC-3711] add Test that check if the association key are composite 2015-11-09 03:46:06 +00:00
Pantel
581e1638a2 [DDC-3711] add Tests that check if the association key are composite 2015-11-09 03:45:56 +00:00
Pantel
17ae8d1b2d [DDC-3711] Correct Error on manyToMany with composite primary key 2015-11-09 03:45:46 +00:00
Guilherme Blanco
3a058f8522 Merge branch 'hotfix/#1375-prevent-duplicate-unique-index' into 2.5
Backported #1375 to 2.5
2015-11-07 16:47:26 +00:00
Michał Bundyra
567220ef71 prevent duplicate unique index 2015-11-07 16:46:22 +00:00
Marco Pivetta
39098ce415 Merge branch 'hotfix/#1507-fixed-wrong-property-name-in-resultset-mapping-builder' into 2.5
Backport merge #1507 into 2.5.x
Close #1507
2015-11-07 10:35:30 -05:00
François-Xavier de Guillebon
1eb9c8a7f6 Added test 2015-11-07 10:35:08 -05:00
François-Xavier de Guillebon
f2f53ba9dc Fixed wrong variable used as array key 2015-11-07 10:35:02 -05:00
François-Xavier de Guillebon
ebbc443ec3 Fixed wrong property name 2015-11-07 10:34:55 -05:00
Nicolas Grekas
16802d2614 Allow symfony 3.0 components
Tests should tell if any deprecated interfaces of Symfony are used. If not, then the bundle is defacto compatible with 3.0
2015-11-05 11:43:20 +01:00
neoglez
ef73249bc7 Entity to test a mapped superclass
Backport of https://github.com/doctrine/doctrine2/pull/1377/files to branch 2.5
2015-09-21 09:32:54 +02:00
neoglez
ed637e51b9 Backport of "fix aliasing of property in OrderBy from MappedSuperclass"
Backport of "LimitSubqueryOutputWalker: fix aliasing of property in OrderBy from MappedSuperclass" ( e501137d1a )
See my comment on a3ece3b419
2015-09-21 08:58:30 +02:00
neoglez
a3ece3b419 UnitTest backport of "Failing test case for broken paginator case"
UnitTest backport of "Failing test case for broken paginator case" ( 192da14842 ).
The branch 2.x is very important because it's related to ZF2 doctrine module (see https://github.com/doctrine/DoctrineORMModule/blob/master/composer.json ) and specially this issue affects the use case of extending the ZF2 user entity defined in ZfcUser ( https://github.com/ZF-Commons/ZfcUser ).
This test is meant to show the need of the backport of e501137d1a
2015-09-21 08:52:46 +02:00
Marco Pivetta
2d1bc78749 Merge branch 'hotfix/#1510-DDC-3908-fix-cache-related-tests-in-2.5' into 2.5
Close #1510
2015-09-19 10:45:24 +02:00
Matthias Pigulla
eaf8b1c7ca Fix tests related to caches, as per doctrine/cache 1.5.0 changes
Backports #1510
Fixes DDC-3908

dd47003641 removes the 'DoctrineNamespaceCacheKey[]' entry from the cache. Thus, all tests counting cache entries were off by one.
2015-09-19 10:44:47 +02:00
Benjamin Eberlei
8070b50150 Bump version to 2.5.2 2015-08-31 14:59:39 +02:00
Benjamin Eberlei
e6a83bedbe Release 2.5.1 2015-08-31 14:59:39 +02:00
Benjamin Eberlei
b6e5464b98 Fix version 2015-08-31 14:59:36 +02:00
Benjamin Eberlei
6366d190d7 [DCOM-293] Fix security misconfiguration vulnerability allowing local remote arbitrary code execution. 2015-08-31 14:58:12 +02:00
Bill Schaller
89eed31e79 Merge pull request #1463 from ehimen/paginate-order-by-subselect
Fixed issue when paginator orders by a subselect expression
Conflicts:
	tests/Doctrine/Tests/ORM/Tools/Pagination/LimitSubqueryOutputWalkerTest.php
2015-08-04 14:31:08 -04:00
Marco Pivetta
4ca00f7a9d Merge branch 'hotfix/#1387-DDC-3699-do-not-merge-managed-uninitialized-entities-2.5' into 2.5
Close #1387
2015-07-15 21:52:41 +01:00
Marco Pivetta
6bc405455e DDC-3699 - #1387 - leveraging the OrmFunctionalTestCase API 2015-07-15 21:52:25 +01:00
Marco Pivetta
173729e560 DDC-3699 - #1387 - catching specific exceptions 2015-07-15 21:52:20 +01:00
Marco Pivetta
86abbb0e78 DDC-3699 - #1387 - simpifying tests, clarifying on test method names 2015-07-15 21:52:16 +01:00
Lenard Palko
69ef75ff2d Added test cases for both one-to-one and one-to-many cases. 2015-07-15 21:52:08 +01:00
Lenard Palko
c68edec0c2 Fix skipping properties if they are listed after a not loaded relation. 2015-07-15 21:51:55 +01:00
Marco Pivetta
f9bbd953a7 Merge branch 'hotfix/#1381-wakeup-reflection-with-embeddable-and-staticreflection-serialization-fix-2.5' into 2.5
Close #1381
2015-07-15 20:50:28 +01:00
Nico Vogelaar
9097014c3d Fixes ClassMetadata wakeupReflection with embeddable and StaticReflectionService 2015-07-15 20:50:05 +01:00
Marco Pivetta
12d178777a Merge branch 'hotfix/#1380-non-cache-persister-bug-2.5' into 2.5
Close #1380
2015-07-15 20:45:38 +01:00
Marco Pivetta
ed1c4de2b6 DDC-3683 - #1380 - reverting BC break, annotating correct types, cs fixes 2015-07-15 20:45:02 +01:00
Darien Hager
fff56c7f3f Remove runtime assertion 2015-07-15 20:44:55 +01:00
Darien Hager
97e90ddefc Clarify state-changes, replace array_key_exists() with isset() for speed 2015-07-15 20:44:50 +01:00
Darien Hager
d5adda954d Whitespace formatting tweaks 2015-07-15 20:44:39 +01:00
Darien Hager
c507b52f20 Remove now-superfluous EntityManager check 2015-07-15 20:44:33 +01:00
Darien Hager
08be905fc3 Refactor LoadClassMetadataEventArgs to ensure it contains an EntityManager 2015-07-15 20:44:24 +01:00
Darien Hager
d29cc3660f Change the test listener than layers on second-level-caching so that it is more conservative, only turning on caching-associations when it knows the target entity is cache-able. 2015-07-15 20:44:10 +01:00
Darien Hager
768c291cd1 Stumbled across a bug where signatures didn't match, but also the current persister-type didn't support getCacheRegion(). Unsure of exact mechanism, but clearly the constructor doesn't take the second argument anyway, may be old code. 2015-07-15 20:43:51 +01:00
Bill Schaller
10ed690d99 Backport Merge pull request #1430 from michael-lavaveshkul/master
"INSTANCE OF" example doesn't match description.
2015-06-18 10:41:56 -04:00
Benjamin Eberlei
e4e59d8064 Merge branch 'DDC-3756' into 2.5 2015-06-16 21:44:14 +02:00
Restless-ET
0e208f7538 [2.5][Bug] Fix ConvertDoctrine1Schema->getMetadata
This bug was introduced at #1205 while resolving #1200.
2015-06-16 21:43:54 +02:00
Guilherme Blanco
3e6c6af845 Merge pull request #1382 from holtkamp/patch-second-level-cache-association-hydration
Patch second level cache association hydration
2015-04-14 11:57:54 -04:00
Marco Pivetta
584345397b Merge branch 'hotfix/#1374-fix-ddc-767-test-php7-pg94-2.5' into 2.5 2015-04-06 04:23:17 +01:00
Matteo Beccati
786791b8fe Fix DDC767Test failing on php7 + pg94
The failure happens when running the full suite or even just:

phpunit tests/Doctrine/Tests/ORM/Functional/Ticket
2015-04-06 04:23:03 +01:00
Marco Pivetta
724dfa0de3 Merge branch 'hotfix/#1361-persistent-collection-collection-hint-fix' into 2.5 2015-04-05 01:30:32 +01:00
Marco Pivetta
39592ba59c Correcting ObjectHydrator logic: if an array is a default value for a collection-valued property, it should be cast to a Collection 2015-04-05 01:29:59 +01:00
Marco Pivetta
58a6013d15 Correcting static introspection issue in cache specific tests (null was being passed to a PersistentCollection) 2015-04-05 01:29:52 +01:00
Marco Pivetta
4580429616 Removing irrelevant tests (as per discussion with @guilhermeblanco and @stof 2015-04-05 01:29:42 +01:00
Marco Pivetta
6e563a313e a PersistentCollection should only allow another collection as a wrapped collection 2015-04-05 01:29:35 +01:00
Marco Pivetta
e8c9cb2f23 Reverting BC break: PersistentConnection#__construct() now accepts null|array|Collection again 2015-04-05 01:29:28 +01:00
Marco Pivetta
4792b4f974 FQCN reference (class was not imported correctly) 2015-04-05 01:29:19 +01:00
Marco Pivetta
c2f6b09ee0 PersistentCollection should still accept null and array as constructor argument, as it did before 2015-04-05 01:29:08 +01:00
Marco Pivetta
cb3179865b Minor docblock correction (discovered during testing) 2015-04-05 01:29:00 +01:00
Marco Pivetta
a1602bd91f Hydration of fetch-joined results fails when an entity has a default value of array for the collection property 2015-04-05 01:28:53 +01:00
Marco Pivetta
34696126e0 Merge branch 'hotfix/#1365-query-dql-function-test-determinism-2.5' into 2.5 2015-04-05 00:10:25 +01:00
Bill Schaller
aa4b2e59ce fix rare query test failures due to nondeterminism without order by clause 2015-04-05 00:10:11 +01:00
Marco Pivetta
2cd86deeb4 Merge branch 'hotfix/#1360-docs-fix-misleading-embeddable-documentation-prefix' into 2.5 2015-04-02 23:25:11 +01:00
Marco Pivetta
52288abf48 Merge branch 'docs/#1359-correcting-mapping-in-working-with-objects-reference' into 2.5 2015-04-02 21:56:03 +01:00
71 changed files with 1176 additions and 119 deletions

View File

@@ -23,9 +23,6 @@ script:
- ENABLE_SECOND_LEVEL_CACHE=0 ./vendor/bin/phpunit -v -c tests/travis/$DB.travis.xml $PHPUNIT_FLAGS
- ENABLE_SECOND_LEVEL_CACHE=1 ./vendor/bin/phpunit -v -c tests/travis/$DB.travis.xml --exclude-group performance,non-cacheable,locking_functional
after_script:
- php vendor/bin/coveralls -v
matrix:
exclude:
- php: hhvm

View File

@@ -138,6 +138,10 @@ From now on, the resultset will look like this:
...
)
## Minor BC BREAK: added second parameter $indexBy in EntityRepository#createQueryBuilder method signature
Added way to access the underlying QueryBuilder#from() method's 'indexBy' parameter when using EntityRepository#createQueryBuilder()
# Upgrade to 2.4
## BC BREAK: Compatibility Bugfix in PersistentCollection#matching()

View File

@@ -18,14 +18,13 @@
"doctrine/collections": "~1.2",
"doctrine/dbal": ">=2.5-dev,<2.6-dev",
"doctrine/instantiator": "~1.0.1",
"doctrine/common": ">=2.5-dev,<2.6-dev",
"doctrine/common": ">=2.5-dev,<2.7-dev",
"doctrine/cache": "~1.4",
"symfony/console": "~2.5"
"symfony/console": "~2.5|~3.0"
},
"require-dev": {
"symfony/yaml": "~2.1",
"phpunit/phpunit": "~4.0",
"satooshi/php-coveralls": "dev-master"
"symfony/yaml": "~2.3|~3.0",
"phpunit/phpunit": "~4.0"
},
"suggest": {
"symfony/yaml": "If you want to use YAML Metadata Mapping Driver"

View File

@@ -601,5 +601,5 @@ Querying for the staffs without getting any technicians can be achieved by this
.. code-block:: php
<?php
$query = $em->createQuery("SELECT staff FROM MyProject\Model\Staff staff WHERE staff INSTANCE OF MyProject\Model\Staff");
$query = $em->createQuery("SELECT staff FROM MyProject\Model\Staff staff WHERE staff NOT INSTANCE OF MyProject\Model\Technician");
$staffs = $query->getResult();

View File

@@ -180,13 +180,7 @@ class DefaultCacheFactory implements CacheFactory
*/
public function buildCollectionHydrator(EntityManagerInterface $em, array $mapping)
{
/* @var $targetPersister \Doctrine\ORM\Cache\Persister\CachedPersister */
$targetPersister = $em->getUnitOfWork()->getEntityPersister($mapping['targetEntity']);
return new DefaultCollectionHydrator(
$em,
$targetPersister->getCacheRegion()
);
return new DefaultCollectionHydrator($em);
}
/**

View File

@@ -73,7 +73,7 @@ class DefaultEntityHydrator implements EntityHydrator
public function buildCacheEntry(ClassMetadata $metadata, EntityCacheKey $key, $entity)
{
$data = $this->uow->getOriginalEntityData($entity);
$data = array_merge($data, $key->identifier); // why update has no identifier values ?
$data = array_merge($data, $metadata->getIdentifierValues($entity)); // why update has no identifier values ?
foreach ($metadata->associationMappings as $name => $assoc) {

View File

@@ -23,7 +23,7 @@ namespace Doctrine\ORM\Cache;
/**
* Defines a region that supports multi-get reading.
*
* With one method call we can get multipe items.
* With one method call we can get multiple items.
*
* @since 2.5
* @author Asmir Mustafic
@@ -31,7 +31,7 @@ namespace Doctrine\ORM\Cache;
interface MultiGetRegion
{
/**
* Get all items from the cache indentifed by $keys.
* Get all items from the cache identified by $keys.
* It returns NULL if some elements can not be found.
*
* @param CollectionCacheEntry $collection The collection of the items to be retrieved.

View File

@@ -57,8 +57,9 @@ class DefaultMultiGetRegion extends DefaultRegion
public function getMultiple(CollectionCacheEntry $collection)
{
$keysToRetrieve = array();
foreach ($collection->identifiers as $index => $key) {
$keysToRetrieve[$index] = $this->name . '_' . $key->hash;
$keysToRetrieve[$index] = $this->getCacheEntryKey($key);
}
$items = $this->cache->fetchMultiple($keysToRetrieve);
@@ -70,6 +71,7 @@ class DefaultMultiGetRegion extends DefaultRegion
foreach ($keysToRetrieve as $index => $key) {
$returnableItems[$index] = $items[$key];
}
return $returnableItems;
}
}

View File

@@ -36,6 +36,8 @@ use Doctrine\ORM\Cache\Region;
*/
class DefaultRegion implements Region
{
const REGION_KEY_SEPARATOR = '_';
/**
* @var CacheAdapter
*/
@@ -84,7 +86,7 @@ class DefaultRegion implements Region
*/
public function contains(CacheKey $key)
{
return $this->cache->contains($this->name . '_' . $key->hash);
return $this->cache->contains($this->getCacheEntryKey($key));
}
/**
@@ -92,7 +94,7 @@ class DefaultRegion implements Region
*/
public function get(CacheKey $key)
{
return $this->cache->fetch($this->name . '_' . $key->hash) ?: null;
return $this->cache->fetch($this->getCacheEntryKey($key)) ?: null;
}
/**
@@ -100,30 +102,29 @@ class DefaultRegion implements Region
*/
public function getMultiple(CollectionCacheEntry $collection)
{
$keysToRetrieve = array();
$result = array();
foreach ($collection->identifiers as $index => $key) {
$keysToRetrieve[$index] = $this->name . '_' . $key->hash;
}
foreach ($collection->identifiers as $key) {
$entryKey = $this->getCacheEntryKey($key);
$entryValue = $this->cache->fetch($entryKey);
$items = array_filter(
array_map([$this->cache, 'fetch'], $keysToRetrieve),
function ($retrieved) {
return false !== $retrieved;
if ($entryValue === false) {
return null;
}
);
if (count($items) !== count($keysToRetrieve)) {
return null;
$result[] = $entryValue;
}
$returnableItems = array();
return $result;
}
foreach ($keysToRetrieve as $index => $key) {
$returnableItems[$index] = $items[$key];
}
return $returnableItems;
/**
* @param CacheKey $key
* @return string
*/
protected function getCacheEntryKey(CacheKey $key)
{
return $this->name . self::REGION_KEY_SEPARATOR . $key->hash;
}
/**
@@ -131,7 +132,7 @@ class DefaultRegion implements Region
*/
public function put(CacheKey $key, CacheEntry $entry, Lock $lock = null)
{
return $this->cache->save($this->name . '_' . $key->hash, $entry, $this->lifetime);
return $this->cache->save($this->getCacheEntryKey($key), $entry, $this->lifetime);
}
/**
@@ -139,7 +140,7 @@ class DefaultRegion implements Region
*/
public function evict(CacheKey $key)
{
return $this->cache->delete($this->name . '_' . $key->hash);
return $this->cache->delete($this->getCacheEntryKey($key));
}
/**

View File

@@ -61,7 +61,7 @@ class FileLockRegion implements ConcurrentRegion
*/
public function __construct(Region $region, $directory, $lockLifetime)
{
if ( ! is_dir($directory) && ! @mkdir($directory, 0777, true)) {
if ( ! is_dir($directory) && ! @mkdir($directory, 0775, true)) {
throw new \InvalidArgumentException(sprintf('The directory "%s" does not exist and could not be created.', $directory));
}
@@ -242,6 +242,7 @@ class FileLockRegion implements ConcurrentRegion
if ( ! @file_put_contents($filename, $lock->value, LOCK_EX)) {
return null;
}
chmod($filename, 0664);
return $lock;
}

View File

@@ -26,6 +26,11 @@ use Doctrine\Common\Persistence\Event\LoadClassMetadataEventArgs as BaseLoadClas
*
* @author Jonathan H. Wage <jonwage@gmail.com>
* @since 2.0
*
* Note: method annotations are used instead of method overrides (due to BC policy)
*
* @method __construct(\Doctrine\ORM\Mapping\ClassMetadata $classMetadata, \Doctrine\ORM\EntityManager $objectManager)
* @method \Doctrine\ORM\EntityManager getClassMetadata()
*/
class LoadClassMetadataEventArgs extends BaseLoadClassMetadataEventArgs
{

View File

@@ -189,8 +189,8 @@ class ObjectHydrator extends AbstractHydrator
$relation = $class->associationMappings[$fieldName];
$value = $class->reflFields[$fieldName]->getValue($entity);
if ($value === null) {
$value = new ArrayCollection;
if ($value === null || is_array($value)) {
$value = new ArrayCollection((array) $value);
}
if ( ! $value instanceof PersistentCollection) {

View File

@@ -945,7 +945,7 @@ class ClassMetadataInfo implements ClassMetadata
}
foreach ($this->fieldMappings as $field => $mapping) {
if (isset($mapping['declaredField'])) {
if (isset($mapping['declaredField']) && isset($parentReflFields[$mapping['declaredField']])) {
$this->reflFields[$field] = new ReflectionEmbeddedProperty(
$parentReflFields[$mapping['declaredField']],
$reflService->getAccessibleProperty($mapping['originalClass'], $mapping['originalField']),

View File

@@ -514,9 +514,8 @@ class YamlDriver extends FileDriver
if ( ! isset($joinColumnElement['name'])) {
$joinColumnElement['name'] = $joinColumnName;
}
$joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement);
}
$joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement);
}
if (isset($joinTableElement['inverseJoinColumns'])) {
@@ -524,9 +523,8 @@ class YamlDriver extends FileDriver
if ( ! isset($joinColumnElement['name'])) {
$joinColumnElement['name'] = $joinColumnName;
}
$joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement);
}
$joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement);
}
$mapping['joinTable'] = $joinTable;

View File

@@ -101,13 +101,13 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
/**
* Creates a new persistent collection.
*
* @param EntityManagerInterface $em The EntityManager the collection will be associated with.
* @param ClassMetadata $class The class descriptor of the entity type of this collection.
* @param Collection $coll The collection elements.
* @param EntityManagerInterface $em The EntityManager the collection will be associated with.
* @param ClassMetadata $class The class descriptor of the entity type of this collection.
* @param Collection $collection The collection elements.
*/
public function __construct(EntityManagerInterface $em, $class, $coll)
public function __construct(EntityManagerInterface $em, $class, Collection $collection)
{
$this->collection = $coll;
$this->collection = $collection;
$this->em = $em;
$this->typeClass = $class;
$this->initialized = true;

View File

@@ -965,7 +965,7 @@ class Parser
$schemaName = $this->em->getConfiguration()->getEntityNamespace($namespaceAlias) . '\\' . $simpleClassName;
}
$exists = class_exists($schemaName, true);
$exists = class_exists($schemaName, true) || interface_exists($schemaName, true);
if ( ! $exists) {
$this->semanticalError("Class '$schemaName' is not defined.", $this->lexer->token);

View File

@@ -347,7 +347,7 @@ class ResultSetMapping
* @param string $class The class name of the joined entity.
* @param string $alias The unique alias to use for the joined entity.
* @param string $parentAlias The alias of the entity result that is the parent of this joined result.
* @param object $relation The association field that connects the parent entity result
* @param string $relation The association field that connects the parent entity result
* with the joined entity result.
*
* @return ResultSetMapping This ResultSetMapping instance.

View File

@@ -438,8 +438,8 @@ class ResultSetMappingBuilder extends ResultSetMapping
$sql .= $class->fieldMappings[$this->fieldMappings[$columnName]]['columnName'];
} else if (isset($this->metaMappings[$columnName])) {
$sql .= $this->metaMappings[$columnName];
} else if (isset($this->discriminatorColumn[$columnName])) {
$sql .= $this->discriminatorColumn[$columnName];
} else if (isset($this->discriminatorColumns[$dqlAlias])) {
$sql .= $this->discriminatorColumns[$dqlAlias];
}
$sql .= " AS " . $columnName;

View File

@@ -1093,6 +1093,10 @@ class SqlWalker implements TreeWalker
$this->orderedColumnsMap[$sql] = $type;
if ($expr instanceof AST\Subselect) {
return '(' . $sql . ') ' . $type;
}
return $sql . ' ' . $type;
}

View File

@@ -137,7 +137,7 @@ EOT
// Process destination directory
if ( ! is_dir($destPath = $input->getArgument('dest-path'))) {
mkdir($destPath, 0777, true);
mkdir($destPath, 0775, true);
}
$destPath = realpath($destPath);

View File

@@ -79,7 +79,7 @@ EOT
}
if ( ! is_dir($destPath)) {
mkdir($destPath, 0777, true);
mkdir($destPath, 0775, true);
}
$destPath = realpath($destPath);

View File

@@ -80,7 +80,7 @@ class ConvertDoctrine1Schema
$schema = array_merge($schema, (array) Yaml::parse(file_get_contents($file)));
}
} else {
$schema = array_merge($schema, (array) Yaml::parse(file_get_contents($file)));
$schema = array_merge($schema, (array) Yaml::parse(file_get_contents($path)));
}
}

View File

@@ -364,7 +364,7 @@ public function __construct(<params>)
$dir = dirname($path);
if ( ! is_dir($dir)) {
mkdir($dir, 0777, true);
mkdir($dir, 0775, true);
}
$this->isNew = !file_exists($path) || (file_exists($path) && $this->regenerateEntityIfExists);
@@ -389,6 +389,7 @@ public function __construct(<params>)
} elseif ( ! $this->isNew && $this->updateEntityIfExists) {
file_put_contents($path, $this->generateUpdatedEntityClass($metadata, $path));
}
chmod($path, 0664);
}
/**

View File

@@ -147,11 +147,12 @@ class <className> extends <repositoryName>
$dir = dirname($path);
if ( ! is_dir($dir)) {
mkdir($dir, 0777, true);
mkdir($dir, 0775, true);
}
if ( ! file_exists($path)) {
file_put_contents($path, $code);
chmod($path, 0664);
}
}

View File

@@ -130,7 +130,7 @@ abstract class AbstractExporter
public function export()
{
if ( ! is_dir($this->_outputDir)) {
mkdir($this->_outputDir, 0777, true);
mkdir($this->_outputDir, 0775, true);
}
foreach ($this->_metadata as $metadata) {
@@ -139,12 +139,13 @@ abstract class AbstractExporter
$path = $this->_generateOutputPath($metadata);
$dir = dirname($path);
if ( ! is_dir($dir)) {
mkdir($dir, 0777, true);
mkdir($dir, 0775, true);
}
if (file_exists($path) && !$this->_overwriteExistingFiles) {
throw ExportException::attemptOverwriteExistingFile($path);
}
file_put_contents($path, $output);
chmod($path, 0664);
}
}
}

View File

@@ -438,7 +438,10 @@ class LimitSubqueryOutputWalker extends SqlWalker
// Field was declared in a parent class, so we need to get the proper SQL table alias
// for the joined parent table.
$otherClassMetadata = $this->em->getClassMetadata($fieldMapping['declared']);
$sqlTableAliasForFieldAlias = $this->getSQLTableAlias($otherClassMetadata->getTableName(), $dqlAliasForFieldAlias);
if (!$otherClassMetadata->isMappedSuperclass) {
$sqlTableAliasForFieldAlias = $this->getSQLTableAlias($otherClassMetadata->getTableName(), $dqlAliasForFieldAlias);
}
}
// Compose search/replace patterns

View File

@@ -21,6 +21,7 @@ namespace Doctrine\ORM\Tools;
use Doctrine\ORM\ORMException;
use Doctrine\DBAL\Schema\Comparator;
use Doctrine\DBAL\Schema\Index;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\Visitor\DropSchemaSqlCollector;
@@ -274,6 +275,15 @@ class SchemaTool
if (isset($class->table['uniqueConstraints'])) {
foreach ($class->table['uniqueConstraints'] as $indexName => $indexData) {
$uniqIndex = new Index($indexName, $indexData['columns'], true, false, [], isset($indexData['options']) ? $indexData['options'] : []);
foreach ($table->getIndexes() as $tableIndexName => $tableIndex) {
if ($tableIndex->isFullfilledBy($uniqIndex)) {
$table->dropIndex($tableIndexName);
break;
}
}
$table->addUniqueIndex($indexData['columns'], is_numeric($indexName) ? null : $indexName, isset($indexData['options']) ? $indexData['options'] : array());
}
}

View File

@@ -1870,7 +1870,7 @@ class UnitOfWork implements PropertyChangedListener
}
}
if ($class->isVersioned) {
if ($class->isVersioned && $this->isLoaded($managedCopy) && $this->isLoaded($entity)) {
$reflField = $class->reflFields[$class->versionField];
$managedCopyVersion = $reflField->getValue($managedCopy);
$entityVersion = $reflField->getValue($entity);
@@ -1883,7 +1883,7 @@ class UnitOfWork implements PropertyChangedListener
$visited[$oid] = $managedCopy; // mark visited
if (!($entity instanceof Proxy && ! $entity->__isInitialized())) {
if ($this->isLoaded($entity)) {
if ($managedCopy instanceof Proxy && ! $managedCopy->__isInitialized()) {
$managedCopy->__load();
}
@@ -1908,6 +1908,18 @@ class UnitOfWork implements PropertyChangedListener
return $managedCopy;
}
/**
* Tests if an entity is loaded - must either be a loaded proxy or not a proxy
*
* @param object $entity
*
* @return bool
*/
private function isLoaded($entity)
{
return !($entity instanceof Proxy) || $entity->__isInitialized();
}
/**
* Sets/adds associated managed copies into the previous entity's association field
*
@@ -3378,7 +3390,7 @@ class UnitOfWork implements PropertyChangedListener
} else {
if ($other instanceof Proxy && !$other->__isInitialized()) {
// do not merge fields marked lazy that have not been fetched.
return;
continue;
}
if ( ! $assoc2['isCascadeMerge']) {
@@ -3406,7 +3418,7 @@ class UnitOfWork implements PropertyChangedListener
if ($mergeCol instanceof PersistentCollection && ! $mergeCol->isInitialized()) {
// do not merge fields marked lazy that have not been fetched.
// keep the lazy persistent collection of the managed copy.
return;
continue;
}
$managedCol = $prop->getValue($managedCopy);

View File

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

View File

@@ -3,33 +3,87 @@
namespace Doctrine\Tests\EventListener;
use Doctrine\Common\Persistence\Event\LoadClassMetadataEventArgs;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\ClassMetadata;
class CacheMetadataListener
{
/**
* Tracks which entities we have already forced caching enabled on. This is
* important to avoid some potential infinite-recursion issues.
*
* Key is the name of the entity, payload is unimportant.
*
* @var array
*/
protected $enabledItems = array();
/**
* @param \Doctrine\Common\Persistence\Event\LoadClassMetadataEventArgs $event
*/
public function loadClassMetadata(LoadClassMetadataEventArgs $event)
{
$metadata = $event->getClassMetadata();
$cache = array(
'usage' => ClassMetadata::CACHE_USAGE_NONSTRICT_READ_WRITE
);
$em = $event->getObjectManager();
/** @var $metadata \Doctrine\ORM\Mapping\ClassMetadata */
if (strstr($metadata->name, 'Doctrine\Tests\Models\Cache')) {
return;
}
$this->enableCaching($metadata, $em);
}
/**
* @param ClassMetadata $metadata
*
* @return bool
*/
private function isVisited(ClassMetaData $metadata)
{
return isset($this->enabledItems[$metadata->getName()]);
}
/**
* @param ClassMetadata $metadata
*/
private function recordVisit(ClassMetaData $metadata)
{
$this->enabledItems[$metadata->getName()] = true;
}
/**
* @param ClassMetadata $metadata
* @param EntityManager $em
*/
protected function enableCaching(ClassMetadata $metadata, EntityManager $em)
{
if ($this->isVisited($metadata)) {
return; // Already handled in the past
}
$cache = array(
'usage' => ClassMetadata::CACHE_USAGE_NONSTRICT_READ_WRITE
);
if ($metadata->isVersioned) {
return;
}
$metadata->enableCache($cache);
$this->recordVisit($metadata);
// only enable association-caching when the target has already been
// given caching settings
foreach ($metadata->associationMappings as $mapping) {
$metadata->enableAssociationCache($mapping['fieldName'], $cache);
$targetMeta = $em->getClassMetadata($mapping['targetEntity']);
$this->enableCaching($targetMeta, $em);
if ($this->isVisited($targetMeta)) {
$metadata->enableAssociationCache($mapping['fieldName'], $cache);
}
}
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Doctrine\Tests\Models\DDC3699;
/** @Entity @Table(name="ddc3699_child") */
class DDC3699Child extends DDC3699Parent
{
const CLASSNAME = __CLASS__;
/** @Id @Column(type="integer") */
public $id;
/** @Column(type="string") */
public $childField;
/** @OneToOne(targetEntity="DDC3699RelationOne", inversedBy="child") */
public $oneRelation;
/** @OneToMany(targetEntity="DDC3699RelationMany", mappedBy="child") */
public $relations;
}

View File

@@ -0,0 +1,12 @@
<?php
namespace Doctrine\Tests\Models\DDC3699;
/** @MappedSuperclass */
abstract class DDC3699Parent
{
const CLASSNAME = __CLASS__;
/** @Column(type="string") */
public $parentField;
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Doctrine\Tests\Models\DDC3699;
/**
* @Entity
* @Table(name="ddc3699_relation_many")
*/
class DDC3699RelationMany
{
const CLASSNAME = __CLASS__;
/** @Id @Column(type="integer") */
public $id;
/** @ManyToOne(targetEntity="DDC3699Child", inversedBy="relations") */
public $child;
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Doctrine\Tests\Models\DDC3699;
/**
* @Entity
* @Table(name="ddc3699_relation_one")
*/
class DDC3699RelationOne
{
const CLASSNAME = __CLASS__;
/** @Id @Column(type="integer") */
public $id;
/** @OneToOne(targetEntity="DDC3699Child", mappedBy="oneRelation") */
public $child;
}

View File

@@ -0,0 +1,78 @@
<?php
/**
* @author Marc Pantel <pantel.m@gmail.com>
*/
namespace Doctrine\Tests\Models\DDC3711;
use Doctrine\Common\Collections\ArrayCollection;
class DDC3711EntityA
{
/**
* @var int
*/
private $id1;
/**
* @var int
*/
private $id2;
/**
* @var ArrayCollection
*/
private $entityB;
/**
* @return mixed
*/
public function getId1()
{
return $this->id1;
}
/**
* @param mixed $id1
*/
public function setId1($id1)
{
$this->id1 = $id1;
}
/**
* @return mixed
*/
public function getId2()
{
return $this->id2;
}
/**
* @param mixed $id2
*/
public function setId2($id2)
{
$this->id2 = $id2;
}
/**
* @return ArrayCollection
*/
public function getEntityB()
{
return $this->entityB;
}
/**
* @param ArrayCollection $entityB
*
* @return DDC3711EntityA
*/
public function addEntityB($entityB)
{
$this->entityB[] = $entityB;
return $this;
}
}

View File

@@ -0,0 +1,75 @@
<?php
/**
* @author Marc Pantel <pantel.m@gmail.com>
*/
namespace Doctrine\Tests\Models\DDC3711;
use Doctrine\Common\Collections\ArrayCollection;
class DDC3711EntityB
{
/**
* @var int
*/
private $id1;
/**
* @var int
*/
private $id2;
/**
* @var ArrayCollection
*/
private $entityA;
/**
* @return int
*/
public function getId1()
{
return $this->id1;
}
/**
* @param int $id1
*/
public function setId1($id1)
{
$this->id1 = $id1;
}
/**
* @return int
*/
public function getId2()
{
return $this->id2;
}
/**
* @param int $id2
*/
public function setId2($id2)
{
$this->id2 = $id2;
}
/**
* @return ArrayCollection
*/
public function getEntityA()
{
return $this->entityA;
}
/**
* @param ArrayCollection $entityA
*/
public function addEntityA($entityA)
{
$this->entityA[] = $entityA;
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace Doctrine\Tests\Models\DDC3899;
/**
* @Entity
* @Table(name="dc3899_contracts")
* @InheritanceType("SINGLE_TABLE")
* @DiscriminatorColumn(name="discr", type="string")
* @DiscriminatorMap({
* "fix" = "DDC3899FixContract",
* "flexible" = "DDC3899FlexContract"
* })
*/
abstract class DDC3899Contract
{
/** @Id @Column(type="integer") */
public $id;
/** @Column(type="boolean") */
public $completed = false;
/** @ManyToOne(targetEntity="DDC3899User", inversedBy="contract") */
public $user;
}

View File

@@ -0,0 +1,12 @@
<?php
namespace Doctrine\Tests\Models\DDC3899;
/**
* @Entity
*/
class DDC3899FixContract extends DDC3899Contract
{
/** @column(type="integer") */
public $fixPrice = 0;
}

View File

@@ -0,0 +1,15 @@
<?php
namespace Doctrine\Tests\Models\DDC3899;
/**
* @Entity
*/
class DDC3899FlexContract extends DDC3899Contract
{
/** @column(type="integer") */
public $hoursWorked = 0;
/** @column(type="integer") */
public $pricePerHour = 0;
}

View File

@@ -0,0 +1,16 @@
<?php
namespace Doctrine\Tests\Models\DDC3899;
/**
* @Entity
* @Table(name="dc3899_users")
*/
class DDC3899User
{
/** @Id @Column(type="integer") */
public $id;
/** @OneToMany(targetEntity="DDC3899Contract", mappedBy="user") */
public $contracts;
}

View File

@@ -0,0 +1,15 @@
<?php
namespace Doctrine\Tests\Models\Hydration;
/** @Entity */
class EntityWithArrayDefaultArrayValueM2M
{
const CLASSNAME = __CLASS__;
/** @Id @Column(type="integer") @GeneratedValue(strategy="AUTO") */
public $id;
/** @ManyToMany(targetEntity=SimpleEntity::class) */
public $collection = [];
}

View File

@@ -0,0 +1,12 @@
<?php
namespace Doctrine\Tests\Models\Hydration;
/** @Entity */
class SimpleEntity
{
const CLASSNAME = __CLASS__;
/** @Id @Column(type="integer") @GeneratedValue(strategy="AUTO") */
public $id;
}

View File

@@ -0,0 +1,37 @@
<?php
namespace Doctrine\Tests\Models\VersionedManyToOne;
/**
* @Entity
* @Table(name="versioned_many_to_one_article")
*/
class Article
{
const CLASSNAME = __CLASS__;
/**
* @Id
* @Column(name="id", type="integer")
* @GeneratedValue(strategy="AUTO")
*/
public $id;
/**
* @Column(name="name")
*/
public $name;
/**
* @ManyToOne(targetEntity="Category", cascade={"merge", "persist"})
*/
public $category;
/**
* Version column
*
* @Column(type="integer", name="version")
* @Version
*/
public $version;
}

View File

@@ -0,0 +1,27 @@
<?php
namespace Doctrine\Tests\Models\VersionedManyToOne;
/**
* @Entity
* @Table(name="versioned_many_to_one_category")
*/
class Category
{
const CLASSNAME = __CLASS__;
/**
* @Id
* @Column(name="id", type="integer")
* @GeneratedValue(strategy="AUTO")
*/
public $id;
/**
* Version column
*
* @Column(type="integer", name="version")
* @Version
*/
public $version;
}

View File

@@ -119,7 +119,7 @@ class DefaultEntityHydratorTest extends OrmTestCase
$this->assertArrayHasKey('name', $cache->data);
$this->assertArrayHasKey('country', $cache->data);
$this->assertEquals(array(
'id' => 11,
'id' => 12,
'name' => 'Bar',
'country' => new AssociationCacheEntry(Country::CLASSNAME, array('id' => 11)),
), $cache->data);
@@ -147,9 +147,39 @@ class DefaultEntityHydratorTest extends OrmTestCase
$this->assertArrayHasKey('name', $cache->data);
$this->assertArrayHasKey('country', $cache->data);
$this->assertEquals(array(
'id' => 11,
'id' => 12,
'name' => 'Bar',
'country' => new AssociationCacheEntry(Country::CLASSNAME, array('id' => 11)),
), $cache->data);
}
}
public function testCacheEntryWithWrongIdentifierType()
{
$proxy = $this->em->getReference(Country::CLASSNAME, 11);
$entity = new State('Bat', $proxy);
$uow = $this->em->getUnitOfWork();
$entityData = array('id'=> 12, 'name'=>'Bar', 'country' => $proxy);
$metadata = $this->em->getClassMetadata(State::CLASSNAME);
$key = new EntityCacheKey($metadata->name, array('id'=>'12'));
$entity->setId(12);
$uow->registerManaged($entity, array('id'=>12), $entityData);
$cache = $this->structure->buildCacheEntry($metadata, $key, $entity);
$this->assertInstanceOf('Doctrine\ORM\Cache\CacheEntry', $cache);
$this->assertInstanceOf('Doctrine\ORM\Cache\EntityCacheEntry', $cache);
$this->assertArrayHasKey('id', $cache->data);
$this->assertArrayHasKey('name', $cache->data);
$this->assertArrayHasKey('country', $cache->data);
$this->assertSame($entity->getId(), $cache->data['id']);
$this->assertEquals(array(
'id' => 12,
'name' => 'Bar',
'country' => new AssociationCacheEntry(Country::CLASSNAME, array('id' => 11)),
), $cache->data);
}
}

View File

@@ -3,10 +3,12 @@
namespace Doctrine\Tests\ORM\Cache;
use Doctrine\Common\Cache\ArrayCache;
use Doctrine\ORM\Cache\CollectionCacheEntry;
use Doctrine\ORM\Cache\Region\DefaultRegion;
use Doctrine\Tests\Mocks\CacheEntryMock;
use Doctrine\Tests\Mocks\CacheKeyMock;
/**
* @group DDC-2183
*/
@@ -72,4 +74,27 @@ class DefaultRegionTest extends AbstractRegionTest
$region->evictAll();
}
public function testGetMulti()
{
$key1 = new CacheKeyMock('key.1');
$value1 = new CacheEntryMock(array('id' => 1, 'name' => 'bar'));
$key2 = new CacheKeyMock('key.2');
$value2 = new CacheEntryMock(array('id' => 2, 'name' => 'bar'));
$this->assertFalse($this->region->contains($key1));
$this->assertFalse($this->region->contains($key2));
$this->region->put($key1, $value1);
$this->region->put($key2, $value2);
$this->assertTrue($this->region->contains($key1));
$this->assertTrue($this->region->contains($key2));
$actual = $this->region->getMultiple(new CollectionCacheEntry(array($key1, $key2)));
$this->assertEquals($value1, $actual[0]);
$this->assertEquals($value2, $actual[1]);
}
}

View File

@@ -22,10 +22,10 @@ class MultiGetRegionTest extends AbstractRegionTest
public function testGetMulti()
{
$key1 = new CacheKeyMock('key.1');
$value1 = new CacheEntryMock(array('id'=>1, 'name' => 'bar'));
$value1 = new CacheEntryMock(array('id' => 1, 'name' => 'bar'));
$key2 = new CacheKeyMock('key.2');
$value2 = new CacheEntryMock(array('id'=>2, 'name' => 'bar'));
$value2 = new CacheEntryMock(array('id' => 2, 'name' => 'bar'));
$this->assertFalse($this->region->contains($key1));
$this->assertFalse($this->region->contains($key2));
@@ -33,6 +33,9 @@ class MultiGetRegionTest extends AbstractRegionTest
$this->region->put($key1, $value1);
$this->region->put($key2, $value2);
$this->assertTrue($this->region->contains($key1));
$this->assertTrue($this->region->contains($key2));
$actual = $this->region->getMultiple(new CollectionCacheEntry(array($key1, $key2)));
$this->assertEquals($value1, $actual[0]);

View File

@@ -11,6 +11,7 @@ use Doctrine\ORM\Persisters\Entity\EntityPersister;
use Doctrine\Tests\Models\Cache\Country;
use Doctrine\Common\Collections\Criteria;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Query\ResultSetMappingBuilder;
use Doctrine\ORM\PersistentCollection;
@@ -390,7 +391,7 @@ abstract class AbstractEntityPersisterTest extends OrmTestCase
{
$mapping = $this->em->getClassMetadata('Doctrine\Tests\Models\Cache\Country');
$assoc = array('type' => 1);
$coll = new PersistentCollection($this->em, $mapping, null);
$coll = new PersistentCollection($this->em, $mapping, new ArrayCollection());
$persister = $this->createPersisterDefault();
$entity = new Country("Foo");
@@ -406,7 +407,7 @@ abstract class AbstractEntityPersisterTest extends OrmTestCase
{
$mapping = $this->em->getClassMetadata('Doctrine\Tests\Models\Cache\Country');
$assoc = array('type' => 1);
$coll = new PersistentCollection($this->em, $mapping, null);
$coll = new PersistentCollection($this->em, $mapping, new ArrayCollection());
$persister = $this->createPersisterDefault();
$entity = new Country("Foo");

View File

@@ -0,0 +1,45 @@
<?php
namespace Doctrine\Tests\ORM\Functional;
use Doctrine\ORM\OptimisticLockException;
use Doctrine\ORM\ORMException;
use Doctrine\Tests\Models\VersionedManyToOne\Article;
use Doctrine\Tests\Models\VersionedManyToOne\Category;
/**
* @group MergeVersionedOneToMany
*/
class MergeVersionedManyToOneTest extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
$this->useModelSet('versioned_many_to_one');
parent::setUp();
}
/**
* This test case asserts that a detached and unmodified entity could be merge without firing
* OptimisticLockException.
*/
public function testSetVersionOnCreate()
{
$category = new Category();
$article = new Article();
$article->name = 'Article';
$article->category = $category;
$this->_em->persist($article);
$this->_em->flush();
$this->_em->clear();
$articleMerged = $this->_em->merge($article);
$articleMerged->name = 'Article Merged';
$this->_em->flush();
$this->assertEquals(2, $articleMerged->version);
}
}

View File

@@ -791,4 +791,20 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertSQLEquals('u.id AS id0, u.status AS status1, u.username AS username2, u.name AS name3, u.email_id AS email_id4', (string)$rsm);
}
/**
* @group DDC-3899
*/
public function testGenerateSelectClauseWithDiscriminatorColumn()
{
$rsm = new ResultSetMappingBuilder($this->_em, ResultSetMappingBuilder::COLUMN_RENAMING_INCREMENT);
$rsm->addEntityResult('Doctrine\Tests\Models\DDC3899\DDC3899User', 'u');
$rsm->addJoinedEntityResult('Doctrine\Tests\Models\DDC3899\DDC3899FixContract', 'c', 'u', 'contracts');
$rsm->addFieldResult('u', $this->platform->getSQLResultCasing('id'), 'id');
$rsm->setDiscriminatorColumn('c', $this->platform->getSQLResultCasing('discr'));
$selectClause = $rsm->generateSelectClause(array('u' => 'u1', 'c' => 'c1'));
$this->assertSQLEquals('u1.id as id, c1.discr as discr', $selectClause);
}
}

View File

@@ -669,6 +669,28 @@ class PaginationTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertCount(9, $paginator);
}
/**
* @dataProvider useOutputWalkersAndFetchJoinCollection
*/
public function testPaginationWithSubSelectOrderByExpression($useOutputWalker, $fetchJoinCollection)
{
$query = $this->_em->createQuery(
"SELECT u,
(
SELECT MAX(a.version)
FROM Doctrine\\Tests\\Models\\CMS\\CmsArticle a
WHERE a.user = u
) AS HIDDEN max_version
FROM Doctrine\\Tests\\Models\\CMS\\CmsUser u
ORDER BY max_version DESC"
);
$paginator = new Paginator($query, $fetchJoinCollection);
$paginator->setUseOutputWalkers($useOutputWalker);
$this->assertCount(9, $paginator->getIterator());
}
public function populate()
{
$groups = array();

View File

@@ -45,12 +45,12 @@ class QueryCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
$query->setQueryCacheDriver($cache);
$query->getResult();
$this->assertEquals(2, $this->getCacheSize($cache));
$this->assertEquals(1, $this->getCacheSize($cache));
$query->setHint('foo', 'bar');
$query->getResult();
$this->assertEquals(3, $this->getCacheSize($cache));
$this->assertEquals(2, $this->getCacheSize($cache));
return $query;
}
@@ -105,16 +105,16 @@ class QueryCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
$query = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux');
$cache = new \Doctrine\Common\Cache\ArrayCache();
$cache = $this->getMock('Doctrine\Common\Cache\Cache');
$query->setQueryCacheDriver($cache);
$users = $query->getResult();
$cache
->expects(self::once())
->method('save')
->with(self::isType('string'), self::isInstanceOf('Doctrine\ORM\Query\ParserResult'));
$data = $this->cacheDataReflection->getValue($cache);
$this->assertEquals(2, count($data));
$this->assertInstanceOf('Doctrine\ORM\Query\ParserResult', array_pop($data));
$query->getResult();
}
public function testQueryCache_HitDoesNotSaveParserResult()

View File

@@ -61,7 +61,7 @@ class QueryDqlFunctionTest extends \Doctrine\Tests\OrmFunctionalTestCase
public function testFunctionAbs()
{
$result = $this->_em->createQuery('SELECT m, ABS(m.salary * -1) AS abs FROM Doctrine\Tests\Models\Company\CompanyManager m')
$result = $this->_em->createQuery('SELECT m, ABS(m.salary * -1) AS abs FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC')
->getResult();
$this->assertEquals(4, count($result));
@@ -73,7 +73,7 @@ class QueryDqlFunctionTest extends \Doctrine\Tests\OrmFunctionalTestCase
public function testFunctionConcat()
{
$arg = $this->_em->createQuery('SELECT m, CONCAT(m.name, m.department) AS namedep FROM Doctrine\Tests\Models\Company\CompanyManager m')
$arg = $this->_em->createQuery('SELECT m, CONCAT(m.name, m.department) AS namedep FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC')
->getArrayResult();
$this->assertEquals(4, count($arg));
@@ -85,7 +85,7 @@ class QueryDqlFunctionTest extends \Doctrine\Tests\OrmFunctionalTestCase
public function testFunctionLength()
{
$result = $this->_em->createQuery('SELECT m, LENGTH(CONCAT(m.name, m.department)) AS namedeplength FROM Doctrine\Tests\Models\Company\CompanyManager m')
$result = $this->_em->createQuery('SELECT m, LENGTH(CONCAT(m.name, m.department)) AS namedeplength FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC')
->getArrayResult();
$this->assertEquals(4, count($result));
@@ -98,7 +98,7 @@ class QueryDqlFunctionTest extends \Doctrine\Tests\OrmFunctionalTestCase
public function testFunctionLocate()
{
$dql = "SELECT m, LOCATE('e', LOWER(m.name)) AS loc, LOCATE('e', LOWER(m.name), 7) AS loc2 ".
"FROM Doctrine\Tests\Models\Company\CompanyManager m";
"FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC";
$result = $this->_em->createQuery($dql)
->getArrayResult();
@@ -116,7 +116,7 @@ class QueryDqlFunctionTest extends \Doctrine\Tests\OrmFunctionalTestCase
public function testFunctionLower()
{
$result = $this->_em->createQuery("SELECT m, LOWER(m.name) AS lowername FROM Doctrine\Tests\Models\Company\CompanyManager m")
$result = $this->_em->createQuery("SELECT m, LOWER(m.name) AS lowername FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC")
->getArrayResult();
$this->assertEquals(4, count($result));
@@ -128,7 +128,7 @@ class QueryDqlFunctionTest extends \Doctrine\Tests\OrmFunctionalTestCase
public function testFunctionMod()
{
$result = $this->_em->createQuery("SELECT m, MOD(m.salary, 3500) AS amod FROM Doctrine\Tests\Models\Company\CompanyManager m")
$result = $this->_em->createQuery("SELECT m, MOD(m.salary, 3500) AS amod FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC")
->getArrayResult();
$this->assertEquals(4, count($result));
@@ -140,7 +140,7 @@ class QueryDqlFunctionTest extends \Doctrine\Tests\OrmFunctionalTestCase
public function testFunctionSqrt()
{
$result = $this->_em->createQuery("SELECT m, SQRT(m.salary) AS sqrtsalary FROM Doctrine\Tests\Models\Company\CompanyManager m")
$result = $this->_em->createQuery("SELECT m, SQRT(m.salary) AS sqrtsalary FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC")
->getArrayResult();
$this->assertEquals(4, count($result));
@@ -152,7 +152,7 @@ class QueryDqlFunctionTest extends \Doctrine\Tests\OrmFunctionalTestCase
public function testFunctionUpper()
{
$result = $this->_em->createQuery("SELECT m, UPPER(m.name) AS uppername FROM Doctrine\Tests\Models\Company\CompanyManager m")
$result = $this->_em->createQuery("SELECT m, UPPER(m.name) AS uppername FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC")
->getArrayResult();
$this->assertEquals(4, count($result));
@@ -186,7 +186,7 @@ class QueryDqlFunctionTest extends \Doctrine\Tests\OrmFunctionalTestCase
{
$dql = "SELECT m, TRIM(TRAILING '.' FROM m.name) AS str1, ".
" TRIM(LEADING '.' FROM m.name) AS str2, TRIM(CONCAT(' ', CONCAT(m.name, ' '))) AS str3 ".
"FROM Doctrine\Tests\Models\Company\CompanyManager m";
"FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC";
$result = $this->_em->createQuery($dql)->getArrayResult();
@@ -207,7 +207,7 @@ class QueryDqlFunctionTest extends \Doctrine\Tests\OrmFunctionalTestCase
public function testOperatorAdd()
{
$result = $this->_em->createQuery('SELECT m, m.salary+2500 AS add FROM Doctrine\Tests\Models\Company\CompanyManager m')
$result = $this->_em->createQuery('SELECT m, m.salary+2500 AS add FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC')
->getResult();
$this->assertEquals(4, count($result));
@@ -219,7 +219,7 @@ class QueryDqlFunctionTest extends \Doctrine\Tests\OrmFunctionalTestCase
public function testOperatorSub()
{
$result = $this->_em->createQuery('SELECT m, m.salary-2500 AS sub FROM Doctrine\Tests\Models\Company\CompanyManager m')
$result = $this->_em->createQuery('SELECT m, m.salary-2500 AS sub FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC')
->getResult();
$this->assertEquals(4, count($result));
@@ -231,7 +231,7 @@ class QueryDqlFunctionTest extends \Doctrine\Tests\OrmFunctionalTestCase
public function testOperatorMultiply()
{
$result = $this->_em->createQuery('SELECT m, m.salary*2 AS op FROM Doctrine\Tests\Models\Company\CompanyManager m')
$result = $this->_em->createQuery('SELECT m, m.salary*2 AS op FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC')
->getResult();
$this->assertEquals(4, count($result));
@@ -246,7 +246,7 @@ class QueryDqlFunctionTest extends \Doctrine\Tests\OrmFunctionalTestCase
*/
public function testOperatorDiv()
{
$result = $this->_em->createQuery('SELECT m, (m.salary/0.5) AS op FROM Doctrine\Tests\Models\Company\CompanyManager m')
$result = $this->_em->createQuery('SELECT m, (m.salary/0.5) AS op FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC')
->getResult();
$this->assertEquals(4, count($result));

View File

@@ -141,7 +141,7 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals(0, $this->getCacheSize($cache));
$query->getResult();
$this->assertEquals(2, $this->getCacheSize($cache));
$this->assertEquals(1, $this->getCacheSize($cache));
return $query;
}

View File

@@ -343,18 +343,18 @@ class SQLFilterTest extends \Doctrine\Tests\OrmFunctionalTestCase
$query->setQueryCacheDriver($cache);
$query->getResult();
$this->assertEquals(2, sizeof($cacheDataReflection->getValue($cache)));
$this->assertEquals(1, sizeof($cacheDataReflection->getValue($cache)));
$conf = $this->_em->getConfiguration();
$conf->addFilter("locale", "\Doctrine\Tests\ORM\Functional\MyLocaleFilter");
$this->_em->getFilters()->enable("locale");
$query->getResult();
$this->assertEquals(3, sizeof($cacheDataReflection->getValue($cache)));
$this->assertEquals(2, sizeof($cacheDataReflection->getValue($cache)));
// Another time doesn't add another cache entry
$query->getResult();
$this->assertEquals(3, sizeof($cacheDataReflection->getValue($cache)));
$this->assertEquals(2, sizeof($cacheDataReflection->getValue($cache)));
}
public function testQueryGeneration_DependsOnFilters()

View File

@@ -0,0 +1,104 @@
<?php
use Doctrine\DBAL\Schema\SchemaException;
use Doctrine\Tests\Models\DDC3699\DDC3699Parent;
use Doctrine\Tests\Models\DDC3699\DDC3699RelationOne;
use Doctrine\Tests\Models\DDC3699\DDC3699RelationMany;
use Doctrine\Tests\Models\DDC3699\DDC3699Child;
/**
* @group DDC-3699
*/
class DDC3597Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
$this->useModelSet('ddc3699');
parent::setUp();
}
/**
* @group DDC-3699
*/
public function testMergingParentClassFieldsDoesNotStopMergingScalarFieldsForToOneUninitializedAssociations()
{
$id = 1;
$child = new DDC3699Child();
$child->id = $id;
$child->childField = 'childValue';
$child->parentField = 'parentValue';
$relation = new DDC3699RelationOne();
$relation->id = $id;
$relation->child = $child ;
$child->oneRelation = $relation;
$this->_em->persist($relation);
$this->_em->persist($child);
$this->_em->flush();
$this->_em->clear();
// fixtures loaded
/* @var $unManagedChild DDC3699Child */
$unManagedChild = $this->_em->find(DDC3699Child::CLASSNAME, $id);
$this->_em->detach($unManagedChild);
// make it managed again
$this->_em->find(DDC3699Child::CLASSNAME, $id);
$unManagedChild->childField = 'modifiedChildValue';
$unManagedChild->parentField = 'modifiedParentValue';
/* @var $mergedChild DDC3699Child */
$mergedChild = $this->_em->merge($unManagedChild);
$this->assertSame($mergedChild->childField, 'modifiedChildValue');
$this->assertSame($mergedChild->parentField, 'modifiedParentValue');
}
/**
* @group DDC-3699
*/
public function testMergingParentClassFieldsDoesNotStopMergingScalarFieldsForToManyUninitializedAssociations()
{
$id = 2;
$child = new DDC3699Child();
$child->id = $id;
$child->childField = 'childValue';
$child->parentField = 'parentValue';
$relation = new DDC3699RelationMany();
$relation->id = $id;
$relation->child = $child ;
$child->relations[] = $relation;
$this->_em->persist($relation);
$this->_em->persist($child);
$this->_em->flush();
$this->_em->clear();
/* @var $unmanagedChild DDC3699Child */
$unmanagedChild = $this->_em->find(DDC3699Child::CLASSNAME, $id);
$this->_em->detach($unmanagedChild);
// make it managed again
$this->_em->find(DDC3699Child::CLASSNAME, $id);
$unmanagedChild->childField = 'modifiedChildValue';
$unmanagedChild->parentField = 'modifiedParentValue';
/* @var $mergedChild DDC3699Child */
$mergedChild = $this->_em->merge($unmanagedChild);
$this->assertSame($mergedChild->childField, 'modifiedChildValue');
$this->assertSame($mergedChild->parentField, 'modifiedParentValue');
}
}

View File

@@ -0,0 +1,30 @@
<?php
/**
* @author Marc Pantel <pantel.m@gmail.com>
*/
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\Tests\ORM\Mapping\YamlMappingDriverTest;
class DDC3711Test extends YamlMappingDriverTest
{
public function testCompositeKeyForJoinTableInManyToManyCreation()
{
$yamlDriver = $this->_loadDriver();
$em = $this->_getTestEntityManager();
$em->getConfiguration()->setMetadataDriverImpl($yamlDriver);
$factory = new \Doctrine\ORM\Mapping\ClassMetadataFactory();
$factory->setEntityManager($em);
$entityA = new ClassMetadata('Doctrine\Tests\Models\DDC3711\DDC3711EntityA');
$entityA = $factory->getMetadataFor('Doctrine\Tests\Models\DDC3711\DDC3711EntityA');
$this->assertEquals(array('link_a_id1' => "id1", 'link_a_id2' => "id2"), $entityA->associationMappings['entityB']['relationToSourceKeyColumns']);
$this->assertEquals(array('link_b_id1' => "id1", 'link_b_id2' => "id2"), $entityA->associationMappings['entityB']['relationToTargetKeyColumns']);
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Tests\Models\Cache\Country;
use Doctrine\Tests\ORM\Functional\SecondLevelCacheAbstractTest;
class DDC3967Test extends SecondLevelCacheAbstractTest
{
protected function setUp()
{
parent::setUp();
$this->loadFixturesCountries();
$this->_em->getCache()->evictEntityRegion(Country::CLASSNAME);
$this->_em->clear();
}
public function testIdentifierCachedWithProperType()
{
$country = array_pop($this->countries);
$id = $country->getId();
// First time, loaded from database
$this->_em->find(Country::CLASSNAME, "$id");
$this->_em->clear();
// Second time, loaded from cache
/** @var Country $country */
$country = $this->_em->find(Country::CLASSNAME, "$id");
// Identifier type should be integer
$this->assertSame($country->getId(), $id);
}
}

View File

@@ -49,7 +49,7 @@ class DDC767Test extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertNotNull($pUser, "User not retrieved from database.");
$groups = array(2, 3);
$groups = array($group2->id, $group3->id);
try {
$this->_em->beginTransaction();

View File

@@ -8,6 +8,8 @@ use Doctrine\ORM\Proxy\ProxyFactory;
use Doctrine\ORM\Mapping\AssociationMapping;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Query;
use Doctrine\Tests\Models\Hydration\EntityWithArrayDefaultArrayValueM2M;
use Doctrine\Tests\Models\Hydration\SimpleEntity;
use Doctrine\Tests\Models\CMS\CmsUser;
@@ -1956,4 +1958,29 @@ class ObjectHydratorTest extends HydrationTestCase
$hydrator = new \Doctrine\ORM\Internal\Hydration\ObjectHydrator($this->_em);
$hydrator->hydrateAll($stmt, $rsm);
}
public function testFetchJoinCollectionValuedAssociationWithDefaultArrayValue()
{
$rsm = new ResultSetMapping;
$rsm->addEntityResult(EntityWithArrayDefaultArrayValueM2M::CLASSNAME, 'e1', null);
$rsm->addJoinedEntityResult(SimpleEntity::CLASSNAME, 'e2', 'e1', 'collection');
$rsm->addFieldResult('e1', 'a1__id', 'id');
$rsm->addFieldResult('e2', 'e2__id', 'id');
$result = (new \Doctrine\ORM\Internal\Hydration\ObjectHydrator($this->_em))
->hydrateAll(
new HydratorMockStatement([[
'a1__id' => '1',
'e2__id' => '1',
]]),
$rsm
);
$this->assertCount(1, $result);
$this->assertInstanceOf(EntityWithArrayDefaultArrayValueM2M::CLASSNAME, $result[0]);
$this->assertInstanceOf('Doctrine\ORM\PersistentCollection', $result[0]->collection);
$this->assertCount(1, $result[0]->collection);
$this->assertInstanceOf(SimpleEntity::CLASSNAME, $result[0]->collection[0]);
}
}

View File

@@ -3,6 +3,7 @@
namespace Doctrine\Tests\ORM\Mapping;
use Doctrine\Common\Persistence\Mapping\RuntimeReflectionService;
use Doctrine\Common\Persistence\Mapping\StaticReflectionService;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Events;
use Doctrine\ORM\Mapping\DefaultNamingStrategy;
@@ -1125,6 +1126,30 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
$this->assertInstanceOf(__NAMESPACE__ . '\\MyArrayObjectEntity', $classMetadata->newInstance());
}
public function testWakeupReflectionWithEmbeddableAndStaticReflectionService()
{
$classMetadata = new ClassMetadata('Doctrine\Tests\ORM\Mapping\TestEntity1');
$classMetadata->mapEmbedded(array(
'fieldName' => 'test',
'class' => 'Doctrine\Tests\ORM\Mapping\TestEntity1',
'columnPrefix' => false,
));
$field = array(
'fieldName' => 'test.embeddedProperty',
'type' => 'string',
'originalClass' => 'Doctrine\Tests\ORM\Mapping\TestEntity1',
'declaredField' => 'test',
'originalField' => 'embeddedProperty'
);
$classMetadata->mapField($field);
$classMetadata->wakeupReflection(new StaticReflectionService());
$this->assertEquals(array('test' => null, 'test.embeddedProperty' => null), $classMetadata->getReflectionProperties());
}
}
/**

View File

@@ -49,7 +49,7 @@ abstract class AbstractDriverTest extends \PHPUnit_Framework_TestCase
{
$this->setExpectedException(
'Doctrine\Common\Persistence\Mapping\MappingException',
"No mapping file found named '".$this->dir."/Foo".$this->getFileExtension()."' for class 'MyNamespace\MySubnamespace\Entity\Foo'."
"No mapping file found named"
);
$driver = $this->getDriver(array(

View File

@@ -0,0 +1,23 @@
Doctrine\Tests\Models\DDC3711\DDC3711EntityA:
type: entity
table: ddc3711.entityA
id:
id1:
type: int
id2:
type: int
manyToMany:
entityB:
targetEntity: Doctrine\Tests\Models\DDC3711\DDC3711EntityB
joinTable:
name: link
joinColumns:
link_a_id1:
referencedColumnName: id1
link_a_id2:
referencedColumnName: id2
inverseJoinColumns:
link_b_id1:
referencedColumnName: id1
link_b_id2:
referencedColumnName: id2

View File

@@ -0,0 +1,8 @@
Doctrine\Tests\Models\DDC3711\DDC3711EntityB:
type: entity
table: ddc3711.entityB
id:
id1:
type: int
id2:
type: int

View File

@@ -3,8 +3,10 @@
namespace Doctrine\Tests\ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\PersistentCollection;
use Doctrine\Tests\Mocks\ConnectionMock;
use Doctrine\Tests\Mocks\DriverMock;
use Doctrine\Tests\Mocks\EntityManagerMock;
use Doctrine\Tests\Models\ECommerce\ECommerceCart;
use Doctrine\Tests\OrmTestCase;
@@ -21,15 +23,16 @@ class PersistentCollectionTest extends OrmTestCase
*/
protected $collection;
private $_connectionMock;
/**
* @var \Doctrine\ORM\EntityManagerInterface
*/
private $_emMock;
protected function setUp()
{
parent::setUp();
// SUT
$this->_connectionMock = new ConnectionMock(array(), new \Doctrine\Tests\Mocks\DriverMock());
$this->_emMock = EntityManagerMock::create($this->_connectionMock);
$this->_emMock = EntityManagerMock::create(new ConnectionMock([], new DriverMock()));
}
/**

View File

@@ -85,6 +85,6 @@ class RunDqlCommandTest extends OrmFunctionalTestCase
))
);
$this->assertStringMatchesFormat('string%sSELECT %a', $this->tester->getDisplay());
$this->assertStringMatchesFormat('%Astring%sSELECT %a', $this->tester->getDisplay());
}
}

View File

@@ -350,5 +350,99 @@ ORDER BY b.id DESC'
$query->getSQL()
);
}
/**
* This tests ordering by property that has the 'declared' field.
*/
public function testLimitSubqueryOrderByFieldFromMappedSuperclass()
{
$this->entityManager->getConnection()->setDatabasePlatform(new MySqlPlatform());
// now use the third one in query
$query = $this->entityManager->createQuery(
'SELECT b FROM Doctrine\Tests\ORM\Tools\Pagination\Banner b ORDER BY b.id DESC'
);
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Tools\Pagination\LimitSubqueryOutputWalker');
$this->assertEquals(
'SELECT DISTINCT id_0 FROM (SELECT b0_.id AS id_0, b0_.name AS name_1 FROM Banner b0_) dctrn_result ORDER BY id_0 DESC',
$query->getSQL()
);
}
/**
* Tests order by on a subselect expression (mysql).
*/
public function testLimitSubqueryOrderBySubSelectOrderByExpression()
{
$this->entityManager->getConnection()->setDatabasePlatform(new MysqlPlatform());
$query = $this->entityManager->createQuery(
'SELECT a,
(
SELECT MIN(bp.title)
FROM Doctrine\Tests\ORM\Tools\Pagination\MyBlogPost bp
WHERE bp.author = a
) AS HIDDEN first_blog_post
FROM Doctrine\Tests\ORM\Tools\Pagination\Author a
ORDER BY first_blog_post DESC'
);
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Tools\Pagination\LimitSubqueryOutputWalker');
$this->assertEquals(
'SELECT DISTINCT id_0 FROM (SELECT a0_.id AS id_0, a0_.name AS name_1, (SELECT MIN(m1_.title) AS dctrn__1 FROM MyBlogPost m1_ WHERE m1_.author_id = a0_.id) AS sclr_2 FROM Author a0_) dctrn_result ORDER BY sclr_2 DESC',
$query->getSQL()
);
}
/**
* Tests order by on a subselect expression invoking RowNumberOverFunction (postgres).
*/
public function testLimitSubqueryOrderBySubSelectOrderByExpressionPg()
{
$this->entityManager->getConnection()->setDatabasePlatform(new PostgreSqlPlatform());
$query = $this->entityManager->createQuery(
'SELECT a,
(
SELECT MIN(bp.title)
FROM Doctrine\Tests\ORM\Tools\Pagination\MyBlogPost bp
WHERE bp.author = a
) AS HIDDEN first_blog_post
FROM Doctrine\Tests\ORM\Tools\Pagination\Author a
ORDER BY first_blog_post DESC'
);
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Tools\Pagination\LimitSubqueryOutputWalker');
$this->assertEquals(
'SELECT DISTINCT id_0, MIN(sclr_3) AS dctrn_minrownum FROM (SELECT a0_.id AS id_0, a0_.name AS name_1, (SELECT MIN(m1_.title) AS dctrn__1 FROM MyBlogPost m1_ WHERE m1_.author_id = a0_.id) AS sclr_2, ROW_NUMBER() OVER(ORDER BY (SELECT MIN(m1_.title) AS dctrn__2 FROM MyBlogPost m1_ WHERE m1_.author_id = a0_.id) DESC) AS sclr_3 FROM Author a0_) dctrn_result GROUP BY id_0 ORDER BY dctrn_minrownum ASC',
$query->getSQL()
);
}
/**
* Tests order by on a subselect expression invoking RowNumberOverFunction (oracle).
*/
public function testLimitSubqueryOrderBySubSelectOrderByExpressionOracle()
{
$this->entityManager->getConnection()->setDatabasePlatform(new OraclePlatform());
$query = $this->entityManager->createQuery(
'SELECT a,
(
SELECT MIN(bp.title)
FROM Doctrine\Tests\ORM\Tools\Pagination\MyBlogPost bp
WHERE bp.author = a
) AS HIDDEN first_blog_post
FROM Doctrine\Tests\ORM\Tools\Pagination\Author a
ORDER BY first_blog_post DESC'
);
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Tools\Pagination\LimitSubqueryOutputWalker');
$this->assertEquals(
'SELECT DISTINCT ID_0, MIN(SCLR_3) AS dctrn_minrownum FROM (SELECT a0_.id AS ID_0, a0_.name AS NAME_1, (SELECT MIN(m1_.title) AS dctrn__1 FROM MyBlogPost m1_ WHERE m1_.author_id = a0_.id) AS SCLR_2, ROW_NUMBER() OVER(ORDER BY (SELECT MIN(m1_.title) AS dctrn__2 FROM MyBlogPost m1_ WHERE m1_.author_id = a0_.id) DESC) AS SCLR_3 FROM Author a0_) dctrn_result GROUP BY ID_0 ORDER BY dctrn_minrownum ASC',
$query->getSQL()
);
}
}

View File

@@ -168,4 +168,22 @@ class Avatar
public $image_width;
/** @Column(type="string", length=255) */
public $image_alt_desc;
}
}
/** @MappedSuperclass */
abstract class Identified
{
/** @Id @Column(type="integer") @GeneratedValue */
private $id;
public function getId()
{
return $this->id;
}
}
/** @Entity */
class Banner extends Identified
{
/** @Column(type="string") */
public $name;
}

View File

@@ -9,19 +9,19 @@ use Doctrine\ORM\Events;
class ResolveTargetEntityListenerTest extends \Doctrine\Tests\OrmTestCase
{
/**
* @var EntityManager
* @var \Doctrine\ORM\EntityManager
*/
private $em = null;
private $em;
/**
* @var ResolveTargetEntityListener
*/
private $listener = null;
private $listener;
/**
* @var ClassMetadataFactory
*/
private $factory = null;
private $factory;
public function setUp()
{
@@ -106,6 +106,32 @@ class ResolveTargetEntityListenerTest extends \Doctrine\Tests\OrmTestCase
$this->assertSame('Doctrine\Tests\ORM\Tools\TargetEntity', $meta['targetEntity']);
$this->assertEquals(array('resolvetargetentity_id', 'targetinterface_id'), $meta['joinTableColumns']);
}
/**
* @group 1572
* @group functional
*
* @coversNothing
*/
public function testDoesResolveTargetEntitiesInDQLAlsoWithInterfaces()
{
$evm = $this->em->getEventManager();
$this->listener->addResolveTargetEntity(
'Doctrine\Tests\ORM\Tools\ResolveTargetInterface',
'Doctrine\Tests\ORM\Tools\ResolveTargetEntity',
array()
);
$evm->addEventSubscriber($this->listener);
$this->assertStringMatchesFormat(
'SELECT%AFROM ResolveTargetEntity%A',
$this
->em
->createQuery('SELECT f FROM Doctrine\Tests\ORM\Tools\ResolveTargetInterface f')
->getSQL()
);
}
}
interface ResolveTargetInterface

View File

@@ -116,6 +116,28 @@ class SchemaToolTest extends \Doctrine\Tests\OrmTestCase
$this->assertSame(array(), $customSchemaOptions);
}
/**
* @group DDC-3671
*/
public function testSchemaHasProperIndexesFromUniqueConstraintAnnotation()
{
$em = $this->_getTestEntityManager();
$schemaTool = new SchemaTool($em);
$classes = [
$em->getClassMetadata(__NAMESPACE__ . '\\UniqueConstraintAnnotationModel'),
];
$schema = $schemaTool->getSchemaFromMetadata($classes);
$this->assertTrue($schema->hasTable('unique_constraint_annotation_table'));
$table = $schema->getTable('unique_constraint_annotation_table');
$this->assertEquals(2, count($table->getIndexes()));
$this->assertTrue($table->hasIndex('primary'));
$this->assertTrue($table->hasIndex('uniq_hash'));
}
}
/**
@@ -148,3 +170,20 @@ class GenerateSchemaEventListener
$this->schemaCalled = true;
}
}
/**
* @Entity
* @Table(name="unique_constraint_annotation_table", uniqueConstraints={
* @UniqueConstraint(name="uniq_hash", columns={"hash"})
* })
*/
class UniqueConstraintAnnotationModel
{
/** @Id @Column */
private $id;
/**
* @Column(name="hash", type="string", length=8, nullable=false, unique=true)
*/
private $hash;
}

View File

@@ -139,6 +139,12 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
'Doctrine\Tests\Models\DDC117\DDC117Editor',
'Doctrine\Tests\Models\DDC117\DDC117Link',
),
'ddc3699' => array(
'Doctrine\Tests\Models\DDC3699\DDC3699Parent',
'Doctrine\Tests\Models\DDC3699\DDC3699RelationOne',
'Doctrine\Tests\Models\DDC3699\DDC3699RelationMany',
'Doctrine\Tests\Models\DDC3699\DDC3699Child',
),
'stockexchange' => array(
'Doctrine\Tests\Models\StockExchange\Bond',
'Doctrine\Tests\Models\StockExchange\Stock',
@@ -274,6 +280,10 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
'Doctrine\Tests\Models\Pagination\User',
'Doctrine\Tests\Models\Pagination\User1',
),
'versioned_many_to_one' => array(
'Doctrine\Tests\Models\VersionedManyToOne\Category',
'Doctrine\Tests\Models\VersionedManyToOne\Article',
),
);
/**
@@ -529,6 +539,11 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
$conn->executeUpdate('DELETE FROM pagination_user');
}
if (isset($this->_usedModelSets['versioned_many_to_one'])) {
$conn->executeUpdate('DELETE FROM versioned_many_to_one_article');
$conn->executeUpdate('DELETE FROM versioned_many_to_one_category');
}
$this->_em->clear();
}