Compare commits

..

111 Commits

Author SHA1 Message Date
Benjamin Eberlei
5aedac1e5c Release 2.4.8 2015-08-31 15:19:01 +02:00
Benjamin Eberlei
caf30b889b [DCOM-293] Fix security misconfiguration vulnerability allowing local remote arbitrary code execution. 2015-08-31 15:18:15 +02:00
Marco Pivetta
0cf7e0e628 Merge branch 'hotfix/#1352-entity-generator-new-class-metadata-hotfix-2.4' into 2.4
Close #1352
2015-03-31 08:45:37 +01:00
Fedik
2290d1ff9b fix EntityGenerator RegenerateEntityIfExists 2015-03-31 08:45:07 +01:00
Jonathan H. Wage
ecb1e1060a Update docs theme submodule. 2015-03-23 22:22:04 +00:00
Marco Pivetta
9dfa20d3af Merge branch 'hotfix/#1327-entity-generator-default-property-value-export-2.4' into 2.4 2015-03-17 22:48:41 +00:00
Jeremy
33baa41e9f Properly generate default value from yml & xml mapping 2015-03-17 22:48:23 +00:00
Marco Pivetta
1c8f9ca1cc Merge branch 'hotfix/#1338-identity-map-garbage-collection-prevention-on-canceled-remove-2.4' into 2.4 2015-03-17 22:42:48 +00:00
Marco Pivetta
7aa33c6a15 #1338 - Removing redundant test case 2015-03-17 22:41:52 +00:00
Marco Pivetta
0fc476d068 Adding @group annotations for newly introduced tests 2015-03-17 22:41:42 +00:00
Marco Pivetta
1e38d7d07e #1338 DDC-3619 - moved test to unit of work tests 2015-03-17 22:40:21 +00:00
nclavaud
bac6570af1 Update identityMap when entity gets managed again
http://www.doctrine-project.org/jira/browse/DDC-3619

When using SoftDeleteable doctrine extension, an entity can be scheduled
for deletion, then persisted before flushing. In such a case, the entity
was removed from the unit of work identity map and no reference was
hold. This could lead to spl_object_hash collisions, and prevent
another, new entity to be persisted later.

This fix makes sure the unit of work identity map holds a reference to
the entity after it has been soft-deleted.
2015-03-17 22:38:57 +00:00
Marco Pivetta
18c873216b Merge pull request #1300 from Ocramius/hotfix/#1169-DDC-3343-one-to-many-persister-deletes-only-on-extra-lazy-plus-orphan-removal-2.4
[2.4] #1169 DDC-3343 one-to-omany persister deletes only on EXTRA_LAZY plus orphanRemoval
2015-02-16 00:29:00 +00:00
Marco Pivetta
11936a6cac #1169 DDC-3343 - correcting functional test case cleanup logic (sorting deletes by FK dependencies) 2015-02-05 00:53:34 +00:00
Marco Pivetta
f5705d6d95 #1169 DDC-3343 - corrected persister logic - only uses the entity persister to perform deletes on the owning side 2015-02-05 00:52:54 +00:00
Marco Pivetta
a1bd3e8cc9 #1169 DDC-3343 - optimized imports 2015-02-05 00:25:20 +00:00
Marco Pivetta
2fa48c6e88 #1169 DDC-3343 - actually deleting associated elements when they are orphaned and EXTRA_LAZY is used 2015-02-05 00:25:06 +00:00
Marco Pivetta
c4ab4db743 #1169 DDC-3343 - remove duplicate tests introduced by cherry-picking conflicts 2015-02-05 00:23:51 +00:00
Marco Pivetta
c6e7a81849 #1169 DDC-3343 - removing duplicate test method 2015-02-05 00:21:28 +00:00
Marco Pivetta
4bed15b984 #1169 DDC-3343 - one-to-many persister should only interact with the data when orphanRemoval and EXTRA_LAZY are combined 2015-02-05 00:20:39 +00:00
Marco Pivetta
4884183b95 #1169 DDC-3343 - fixing test case typos (referencing wrong/inexisting properties, inexisting owning side assigned 2015-02-05 00:16:58 +00:00
Marco Pivetta
fac410b213 #1169 DDC-3343 - aligning test suite logic to the 2.5 branch (failing tests) 2015-02-05 00:16:07 +00:00
Marco Pivetta
cbe5575f38 #1169 DDC-3343 - adding tests for orphan-removal + extra-lazy + one-to-many element removal behavior 2015-02-05 00:15:18 +00:00
Marco Pivetta
94c0e46c96 #1169 DDC-3343 - updating test expectations - one-to-many changes should be no-op unless orphan removal is specified. 2015-02-05 00:14:19 +00:00
Marco Pivetta
af59ea962f #1169 DDC-3343 - updating test expectations - one-to-many changes should be no-op unless orphan removal is specified. 2015-02-05 00:14:11 +00:00
Marco Pivetta
e05930e714 Merge branch 'hotfix/#1294-avoid-connection-with-detached-metadata-backport-to-2.4' into 2.4 2015-02-04 23:46:22 +00:00
Marco Pivetta
db06355b63 #1294 - fixing differences between 2.5 and 2.4 fixes (reverts DBAL dependency bump) 2015-02-04 23:46:15 +00:00
Ryan Weaver
2e9ffe831c Adding docblock 2015-02-04 23:37:11 +00:00
Ryan Weaver
9d7256aace Small code change thanks to the comments and adding a test 2015-02-04 23:37:03 +00:00
Ryan Weaver
52b3e21969 Only getting the target platform when it's *actually* needed to avoid errors
initialize() is called sometimes, even when the following code doesn't need
the targetPlatform property. Specifically, in AbstractClassMetadataFactory::getAllMetadata().

But as of DBAL 2.5.0, calling Connection::getDatabasePlatform() will make a
connection to the database, which means that sometimes it may fail (e.g. you
haven't configured your database yet). As a result, calling a method like
AbstractClassMetadataFactory::getAllMetadata() - which does not need the
targetPlatform - will fail, because determining the targetPlatform requires
a connection, which fails.

This avoids that - we only get the targetPlatform *when* we need it, which
are cases where we're doing things that do indeed need a connection.
2015-02-04 23:35:02 +00:00
Marco Pivetta
97afe00d0f Merge pull request #1282 from Ocramius/hotfix/#1169-extra-lazy-one-to-many-should-not-delete-referenced-entities-2.4
Hotfix/#1169 extra lazy one to many should not delete referenced entities (backport to 2.4)
2015-01-25 05:44:14 +01:00
Marco Pivetta
51250e987e #1169 DDC-3343 - moved tests to correct test class 2015-01-24 12:51:19 +01:00
Marco Pivetta
c4b59b4eb0 #1169 DDC-3343 - adapting patch to 2.4 branch 2015-01-24 12:50:10 +01:00
Marco Pivetta
daca81861c #1169 DDC-3343 - additional test cases: removing proxies from an extra-lazy collection still updates the owning side values 2015-01-24 12:38:51 +01:00
Marco Pivetta
52fbe35bc7 #1169 DDC-3343 - correcting query count assertions on extra-lazy specific tests (some DELETE operations became UPDATE operations)
Conflicts:
	lib/Doctrine/ORM/Persisters/Collection/OneToManyPersister.php
	tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
2015-01-24 12:38:44 +01:00
Marco Pivetta
50ac97e72d #1169 DDC-3343 - removing duplicate test 2015-01-24 12:37:41 +01:00
Marco Pivetta
cfed92a5cf #1169 DDC-3343 - integrating tests into the existing test suite
Conflicts:
	tests/Doctrine/Tests/ORM/Functional/ValueConversionType/OneToManyExtraLazyTest.php
2015-01-24 12:37:21 +01:00
Marco Pivetta
d69fd91454 #1169 DDC-3343 - importing used classe 2015-01-24 12:36:18 +01:00
Marco Pivetta
41258deed7 #1169 DDC-3343 - optimized imports 2015-01-24 12:36:10 +01:00
Marco Pivetta
193ec51607 #1169 DDC-3343 - refactoring test to use pre-existing test models 2015-01-24 12:36:01 +01:00
Marco Pivetta
7292920b15 #1169 DDC-3343 - refactoring test to use pre-existing test models 2015-01-24 12:35:50 +01:00
Marco Pivetta
24ebfb69cb #1169 DDC-3343 - minor refactoring: constant over string reference 2015-01-24 12:34:10 +01:00
Marco Pivetta
ff0168834e Conflicts:
lib/Doctrine/ORM/Persisters/Collection/OneToManyPersister.php
2015-01-24 12:33:52 +01:00
Andrea Sprega
a88550a70c [DDC-3343] Failing test case (updated) 2015-01-24 12:32:30 +01:00
Andrea Sprega
ee246af7e3 [DDC-3343] Failing test case 2015-01-24 12:32:17 +01:00
Marco Pivetta
ba04c9801d Merge pull request #1276 from TomasVotruba/travis-coverage-speedup
[2.4] travis: run coverage just once
2015-01-22 15:03:10 +01:00
Tomas Votruba
5d637af056 travis: run coverage just once 2015-01-22 13:46:29 +01:00
Marco Pivetta
ec84953af4 Merge pull request #1266 from Ocramius/hotfix/fix-schema-generation-in-tests-on-pgsql
[2.4] Fix schema generation in the test suite
2015-01-22 12:30:16 +01:00
Marco Pivetta
56c5cb41fc DDC-3518 - Schema creation statement is not quoted 2015-01-18 17:39:10 +01:00
Guilherme Blanco
e0077b290b ORM side fixes. 2015-01-18 17:09:29 +01:00
Marco Pivetta
ee9aebf569 #1254 DDC-3500 - fixed duplicate JOIN aliases in CTI + WITH condition joins 2015-01-18 16:43:31 +01:00
Marco Pivetta
91e5c0d443 Merge pull request #1231 from aivus/2.4-DDC-1590-backport
Backport 'Merge pull request #1098 from encoder32/DDC-1590' to 2.4 branch
2015-01-17 22:19:29 +01:00
Marco Pivetta
05342b0b94 Merge pull request #1254 from vitaliyberdylo/2.4
Fix applying ON/WITH conditions to first join in Class Table Inheritance
2015-01-17 21:56:32 +01:00
Marco Pivetta
8198a6ce7e Merge branch 'hotfix/#1250-DDC-3493-fix-class-pseudo-constant-parsing-in-entitygenerator-2.4-backport' into 2.4 2015-01-15 04:20:39 +01:00
Andrea Sprega
b5e40fe5f5 DDC-3493 - fixed EntityGenerator parsing for php 5.5 "::class" syntax 2015-01-15 04:20:16 +01:00
lukasmaz
ddf3125afe Test case for "class" keyword
Test case for http://www.doctrine-project.org/jira/browse/DDC-3493
2015-01-15 04:19:54 +01:00
Strate
8d33ccced1 Fix applying ON/WITH conditions to first join in Class Table Inheritance
Now we build nested joins for CTI when using ON/WITH clause.
2015-01-14 19:55:54 +02:00
Marco Pivetta
b11ae45a2f Merge branch 'hotfix/#1242-lock-uninitialized-proxies' into 2.4
Close #1242
2015-01-13 02:36:08 +01:00
Carnage
d3112bf119 Fixed issue 2015-01-13 02:35:50 +01:00
Carnage
4e4637de2e Added test to demonstrate issue 2015-01-13 02:35:44 +01:00
Marco Pivetta
4c8abd5d83 Backport 'Merge pull request #1098 from encoder32/DDC-1590' to 2.4 branch 2014-12-26 15:56:01 +02:00
Marco Pivetta
71f446f23b Bump version to 2.4.8 2014-12-16 14:47:17 +01:00
Marco Pivetta
2bc4ff3cab Release v2.4.7 2014-12-16 14:45:01 +01:00
Marco Pivetta
39f2f0eb91 Merge branch 'backport/#1202-backport-null-column-option-values' into 2.4 2014-12-08 01:39:22 +01:00
Marco Pivetta
a5a7c879fc #1202 - simplified test and test asset 2014-12-08 01:38:38 +01:00
Gareth Evans
5670912d0d Added test that passes following previous commit 2014-12-08 01:38:31 +01:00
Gareth Evans
fae0f6a29a Checks key exists rather than isset
If the default value is set to `null`, `isset` will return `false` even though the key is actually there for a reason.
2014-12-08 01:38:21 +01:00
Marco Pivetta
f45cf2629e Merge branch 'hotfix/#1211-DDC-3434-backport-to-2.4' into 2.4
Close #1211
2014-12-05 18:11:57 +01:00
Marco Pivetta
4d846c1992 DDC-3434 - removing explicit failure: 2.4 uses different column alias naming strategy logic 2014-12-05 18:11:44 +01:00
Marco Pivetta
37516d7548 DDC-3434 - adding note on why restoring 'HIDDEN' selected fields is relevant 2014-12-05 18:07:47 +01:00
Marco Pivetta
24c4ec91e5 DDC-3434 - HIDDEN modifier marked fields in ORDER BY clause are always preserved when creating a paginator subquery 2014-12-05 18:07:41 +01:00
Marco Pivetta
f31f088f0b DDC-3434 - adding test case for HIDDEN modifier fields in ORDER BY sequences: should be preserved in any case 2014-12-05 18:07:35 +01:00
Marco Pivetta
51da937bbc DDC-3434 - removed unneeded escaping sequences 2014-12-05 18:07:30 +01:00
Marco Pivetta
801e7f0ef7 DDC-3336 - adding $types parameter to ConnectionMock#fetchColumn() for DBAL 2.5 compatibility 2014-12-05 17:30:16 +01:00
Marco Pivetta
f0e6408005 DDC-3336 - removing explicit failure: 2.4 uses different column alias naming strategy logic 2014-12-05 17:29:18 +01:00
Marco Pivetta
c398f8c2c2 Merge branch 'hotfix/backport-DDC-3336-undefined-property-in-paginator-walkers-with-scalar-expressions-in-order-by-clause' into 2.4
Close #1210
2014-12-05 16:46:52 +01:00
Marco Pivetta
060bbb1366 DDC-3336 - applied hotfix: only PathExpression instances have a $field property 2014-12-05 16:45:57 +01:00
Marco Pivetta
34fad084a7 DDC-3336 - adding missing type-hint docblock 2014-12-05 16:45:50 +01:00
Marco Pivetta
bdc54d481c DDC-3336 - renamed test method for clarity 2014-12-05 16:45:44 +01:00
Marco Pivetta
60462919f2 DDC-3336 - adding failing test case: scalar expressions in the ORDER BY clause crash the LimitSubqueryOutputWalker 2014-12-05 16:45:39 +01:00
Marco Pivetta
5a8a017a66 DDC-3336 - importing platform classes 2014-12-05 16:45:31 +01:00
Marco Pivetta
c701e8b9a6 Merge branch 'hotfix/#1188-support-count-queries-with-parameters-in-removed-query-parts-2.4-backport' into 2.4
Merge #1188 into 2.4
2014-11-28 12:20:21 +01:00
Marco Pivetta
df99353f19 #1188 - Simplified and optimized parameter un-setting logic 2014-11-28 12:16:21 +01:00
Marco Pivetta
8b5dae30a5 #1188 - Importing parser class 2014-11-28 12:16:13 +01:00
Marco Pivetta
78770f9da8 #1188 - assertCount instead of assertEquals 2014-11-28 12:16:05 +01:00
Marco Pivetta
2f57c4fef9 #1188 - minor CS fixes (avoiding DQL one-liner) 2014-11-28 12:15:53 +01:00
Marco Pivetta
684ae859ce #1188 - accessing Doctrine\ORM\Tools\Pagination\Paginator#getCountQuery() via reflection for test purposes 2014-11-28 12:15:46 +01:00
Marco Pivetta
5f9dc2e5bc #1188 - making Doctrine\ORM\Tools\Pagination\Paginator#getCountQuery() private, as it is an implementation detail 2014-11-28 12:15:35 +01:00
Marco Pivetta
2dbe28a150 #1188 - removing unused variable assignments 2014-11-28 12:15:28 +01:00
Paweł Kolanowski
ea3856673d Missing doc block, removed parse() parameter.
Missing doc block, removed parse() parameter.
2014-11-28 12:15:17 +01:00
Merixstudio
7c02af8896 Filtering by auto-increnement field causes test error.
Executing the same test many times causes error because AI fields.
2014-11-28 12:15:07 +01:00
Merixstudio
61c18ce046 Testing SQLs in functional test is not necessary 2014-11-28 12:14:49 +01:00
Merixstudio
7f5620a41c Test parameter removing parameters passed to select part of query. 2014-11-28 12:14:40 +01:00
Merixstudio
ae198d5e45 Allowed to get count query from paginator. 2014-11-28 12:14:31 +01:00
Merixstudio
705c33bc35 Fixed counting exception
Fixed "Invalid parameter number: number of bound variables does not match number of tokens " exception during execution count on Query where select part of query contains :parameters.
2014-11-28 12:14:20 +01:00
Marco Pivetta
3cef0fdbfa Merge pull request #1191 from mvar/2.4-hotfix
[2.4] Documenting interface methods (based on entity manager)
2014-11-23 21:47:50 +01:00
Luís Otávio Cobucci Oblonczyk
ccbe849a72 Use docblox from EntityManagerInterface
(cherry picked from commit 6d58824ac5)
2014-11-23 17:08:08 +02:00
Luís Otávio Cobucci Oblonczyk
2b8e03ff12 Fixing FQCN on docblox
(cherry picked from commit 67135e5d6f)
2014-11-23 17:00:22 +02:00
Luís Otávio Cobucci Oblonczyk
c4e93cf68c Documenting interface methods (based on entity manager)
(cherry picked from commit 877ba9bf17)
2014-11-23 16:59:50 +02:00
Marco Pivetta
cfdef3bf19 Merge pull request #925 from deeky666/DDC-2310-2.4
[DDC-2310] [DDC-2675] [2.4] Fix SQL generation on table lock hint capable platforms
2014-11-12 00:31:13 +01:00
Marco Pivetta
8bb1d5448b Bump version to 2.4.7 2014-10-06 15:23:31 +02:00
Marco Pivetta
bebacf79d8 Release 2.4.6 2014-10-06 15:22:50 +02:00
Steve Müller
d46fa4adeb Merge pull request #1154 from Ocramius/hotfix/PHP-5.6-serialization-fix
DDC-3120 - PHP 5.6 internal classes/Serializable serialization fix
2014-10-06 15:08:37 +02:00
Marco Pivetta
64061bafaf DDC-3120 - Adding PHP 5.6 to build matrix 2014-10-06 14:28:05 +02:00
Marco Pivetta
a69584a841 DDC-3120 - Using ReflectionClass#newInstanceWithoutConstructor() also with PHP 5.6+ 2014-10-06 14:26:00 +02:00
Marco Pivetta
8fc1c34b29 DDC-3120 - metadata should be waked up before attempting new instance creation 2014-10-06 14:25:16 +02:00
Marco Pivetta
0d683c1897 DDC-3120 - metadata should be initialized before attempting new instance creation 2014-10-06 14:22:06 +02:00
Marco Pivetta
60b75fefed DDC-3120 - add failing test for un-serialization of an internal PHP class from cached metadata instance 2014-10-06 14:13:40 +02:00
Marco Pivetta
0a7e0617cc DDC-3120 - add failing test for un-serialization of an internal PHP class 2014-10-06 14:13:32 +02:00
Marco Pivetta
072e1eee7b Bump version to 2.4.6 2014-09-23 00:04:35 +02:00
Steve Müller
0fb236f451 fix SQL generation on table lock hint capable platforms 2014-04-17 15:07:11 +02:00
44 changed files with 1209 additions and 332 deletions

View File

@@ -4,6 +4,7 @@ php:
- 5.3
- 5.4
- 5.5
- 5.6
env:
- DB=mysql
@@ -11,14 +12,15 @@ env:
- DB=sqlite
before_script:
- sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'DROP DATABASE IF EXISTS doctrine_tests;' -U postgres; fi"
- sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'DROP DATABASE IF EXISTS doctrine_tests_tmp;' -U postgres; fi"
- sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'create database doctrine_tests;' -U postgres; fi"
- sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'create database doctrine_tests_tmp;' -U postgres; fi"
- sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'create database IF NOT EXISTS doctrine_tests_tmp;create database IF NOT EXISTS doctrine_tests;'; fi"
- if [[ $TRAVIS_PHP_VERSION = '5.6' && $DB = 'sqlite' ]]; then PHPUNIT_FLAGS="--coverage-clover ./build/logs/clover.xml"; else PHPUNIT_FLAGS=""; fi
- if [ $DB = 'pgsql' ]; then psql -c 'DROP DATABASE IF EXISTS doctrine_tests;' -U postgres; fi
- if [ $DB = 'pgsql' ]; then psql -c 'DROP DATABASE IF EXISTS doctrine_tests_tmp;' -U postgres; fi
- if [ $DB = 'pgsql' ]; then psql -c 'create database doctrine_tests;' -U postgres; fi
- if [ $DB = 'pgsql' ]; then psql -c 'create database doctrine_tests_tmp;' -U postgres; fi
- if [ $DB = 'mysql' ]; then mysql -e 'create database IF NOT EXISTS doctrine_tests_tmp;create database IF NOT EXISTS doctrine_tests;'; fi
- composer install --prefer-dist --dev
script: phpunit --configuration tests/travis/$DB.travis.xml
script: phpunit $PHPUNIT_FLAGS --configuration tests/travis/$DB.travis.xml
after_script:
- php vendor/bin/coveralls -v

View File

@@ -165,9 +165,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Gets the database connection object used by the EntityManager.
*
* @return \Doctrine\DBAL\Connection
* {@inheritDoc}
*/
public function getConnection()
{
@@ -185,18 +183,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Gets an ExpressionBuilder used for object-oriented construction of query expressions.
*
* Example:
*
* <code>
* $qb = $em->createQueryBuilder();
* $expr = $em->getExpressionBuilder();
* $qb->select('u')->from('User', 'u')
* ->where($expr->orX($expr->eq('u.id', 1), $expr->eq('u.id', 2)));
* </code>
*
* @return \Doctrine\ORM\Query\Expr
* {@inheritDoc}
*/
public function getExpressionBuilder()
{
@@ -208,9 +195,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Starts a transaction on the underlying database connection.
*
* @return void
* {@inheritDoc}
*/
public function beginTransaction()
{
@@ -218,18 +203,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Executes a function in a transaction.
*
* The function gets passed this EntityManager instance as an (optional) parameter.
*
* {@link flush} is invoked prior to transaction commit.
*
* If an exception occurs during execution of the function or flushing or transaction commit,
* the transaction is rolled back, the EntityManager closed and the exception re-thrown.
*
* @param callable $func The function to execute transactionally.
*
* @return mixed The non-empty value returned from the closure or true instead.
* {@inheritDoc}
*/
public function transactional($func)
{
@@ -255,9 +229,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Commits a transaction on the underlying database connection.
*
* @return void
* {@inheritDoc}
*/
public function commit()
{
@@ -265,9 +237,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Performs a rollback on the underlying database connection.
*
* @return void
* {@inheritDoc}
*/
public function rollback()
{
@@ -296,11 +266,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Creates a new Query object.
*
* @param string $dql The DQL string.
*
* @return \Doctrine\ORM\Query
* {@inheritDoc}
*/
public function createQuery($dql = '')
{
@@ -314,11 +280,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Creates a Query from a named query.
*
* @param string $name
*
* @return \Doctrine\ORM\Query
* {@inheritDoc}
*/
public function createNamedQuery($name)
{
@@ -326,12 +288,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Creates a native SQL query.
*
* @param string $sql
* @param ResultSetMapping $rsm The ResultSetMapping to use.
*
* @return NativeQuery
* {@inheritDoc}
*/
public function createNativeQuery($sql, ResultSetMapping $rsm)
{
@@ -344,11 +301,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Creates a NativeQuery from a named native query.
*
* @param string $name
*
* @return \Doctrine\ORM\NativeQuery
* {@inheritDoc}
*/
public function createNamedNativeQuery($name)
{
@@ -358,9 +311,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Create a QueryBuilder instance
*
* @return QueryBuilder
* {@inheritDoc}
*/
public function createQueryBuilder()
{
@@ -480,15 +431,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Gets a reference to the entity identified by the given type and identifier
* without actually loading it, if the entity is not yet loaded.
*
* @param string $entityName The name of the entity type.
* @param mixed $id The entity identifier.
*
* @return object The entity reference.
*
* @throws ORMException
* {@inheritDoc}
*/
public function getReference($entityName, $id)
{
@@ -529,24 +472,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Gets a partial reference to the entity identified by the given type and identifier
* without actually loading it, if the entity is not yet loaded.
*
* The returned reference may be a partial object if the entity is not yet loaded/managed.
* If it is a partial object it will not initialize the rest of the entity state on access.
* Thus you can only ever safely access the identifier of an entity obtained through
* this method.
*
* The use-cases for partial references involve maintaining bidirectional associations
* without loading one side of the association or to update an entity without loading it.
* Note, however, that in the latter case the original (persistent) entity data will
* never be visible to the application (especially not event listeners) as it will
* never be loaded in the first place.
*
* @param string $entityName The name of the entity type.
* @param mixed $identifier The entity identifier.
*
* @return object The (partial) entity reference.
* {@inheritDoc}
*/
public function getPartialReference($entityName, $identifier)
{
@@ -585,11 +511,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Closes the EntityManager. All entities that are currently managed
* by this EntityManager become detached. The EntityManager may no longer
* be used after it is closed.
*
* @return void
* {@inheritDoc}
*/
public function close()
{
@@ -713,14 +635,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Creates a copy of the given entity. Can create a shallow or a deep copy.
*
* @param object $entity The entity to copy.
* @param boolean $deep FALSE for a shallow copy, TRUE for a deep copy.
*
* @return object The new entity.
*
* @throws \BadMethodCallException
* {@inheritDoc}
*
* @todo Implementation need. This is necessary since $e2 = clone $e1; throws an E_FATAL when access anything on $e:
* Fatal error: Maximum function nesting level of '100' reached, aborting!
@@ -731,16 +646,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Acquire a lock on the given entity.
*
* @param object $entity
* @param int $lockMode
* @param int|null $lockVersion
*
* @return void
*
* @throws OptimisticLockException
* @throws PessimisticLockException
* {@inheritDoc}
*/
public function lock($entity, $lockMode, $lockVersion = null)
{
@@ -774,9 +680,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Gets the EventManager used by the EntityManager.
*
* @return \Doctrine\Common\EventManager
* {@inheritDoc}
*/
public function getEventManager()
{
@@ -784,9 +688,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Gets the Configuration used by the EntityManager.
*
* @return \Doctrine\ORM\Configuration
* {@inheritDoc}
*/
public function getConfiguration()
{
@@ -808,9 +710,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Check if the Entity manager is open or closed.
*
* @return bool
* {@inheritDoc}
*/
public function isOpen()
{
@@ -818,9 +718,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Gets the UnitOfWork used by the EntityManager to coordinate operations.
*
* @return \Doctrine\ORM\UnitOfWork
* {@inheritDoc}
*/
public function getUnitOfWork()
{
@@ -828,16 +726,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Gets a hydrator for the given hydration mode.
*
* This method caches the hydrator instances which is used for all queries that don't
* selectively iterate over the result.
*
* @deprecated
*
* @param int $hydrationMode
*
* @return \Doctrine\ORM\Internal\Hydration\AbstractHydrator
* {@inheritDoc}
*/
public function getHydrator($hydrationMode)
{
@@ -845,13 +734,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Create a new instance for the given hydration mode.
*
* @param int $hydrationMode
*
* @return \Doctrine\ORM\Internal\Hydration\AbstractHydrator
*
* @throws ORMException
* {@inheritDoc}
*/
public function newHydrator($hydrationMode)
{
@@ -881,9 +764,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Gets the proxy factory used by the EntityManager to create entity proxies.
*
* @return ProxyFactory
* {@inheritDoc}
*/
public function getProxyFactory()
{
@@ -891,13 +772,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Helper method to initialize a lazy loading proxy or persistent collection.
*
* This method is a no-op for other objects
*
* @param object $obj
*
* @return void
* {@inheritDoc}
*/
public function initializeObject($obj)
{
@@ -943,9 +818,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Gets the enabled filters.
*
* @return FilterCollection The active filter collection.
* {@inheritDoc}
*/
public function getFilters()
{
@@ -957,9 +830,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Checks whether the state of the filter collection is clean.
*
* @return boolean True, if the filter collection is clean.
* {@inheritDoc}
*/
public function isFiltersStateClean()
{
@@ -967,9 +838,7 @@ use Doctrine\Common\Util\ClassUtils;
}
/**
* Checks whether the Entity Manager has filters.
*
* @return boolean True, if the EM has a filter collection.
* {@inheritDoc}
*/
public function hasFilters()
{

View File

@@ -20,7 +20,6 @@
namespace Doctrine\ORM;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\DBAL\LockMode;
use Doctrine\ORM\Query\ResultSetMapping;
/**
@@ -31,30 +30,258 @@ use Doctrine\ORM\Query\ResultSetMapping;
*/
interface EntityManagerInterface extends ObjectManager
{
/**
* Gets the database connection object used by the EntityManager.
*
* @return \Doctrine\DBAL\Connection
*/
public function getConnection();
/**
* Gets an ExpressionBuilder used for object-oriented construction of query expressions.
*
* Example:
*
* <code>
* $qb = $em->createQueryBuilder();
* $expr = $em->getExpressionBuilder();
* $qb->select('u')->from('User', 'u')
* ->where($expr->orX($expr->eq('u.id', 1), $expr->eq('u.id', 2)));
* </code>
*
* @return \Doctrine\ORM\Query\Expr
*/
public function getExpressionBuilder();
/**
* Starts a transaction on the underlying database connection.
*
* @return void
*/
public function beginTransaction();
/**
* Executes a function in a transaction.
*
* The function gets passed this EntityManager instance as an (optional) parameter.
*
* {@link flush} is invoked prior to transaction commit.
*
* If an exception occurs during execution of the function or flushing or transaction commit,
* the transaction is rolled back, the EntityManager closed and the exception re-thrown.
*
* @param callable $func The function to execute transactionally.
*
* @return mixed The non-empty value returned from the closure or true instead.
*/
public function transactional($func);
/**
* Commits a transaction on the underlying database connection.
*
* @return void
*/
public function commit();
/**
* Performs a rollback on the underlying database connection.
*
* @return void
*/
public function rollback();
/**
* Creates a new Query object.
*
* @param string $dql The DQL string.
*
* @return Query
*/
public function createQuery($dql = '');
/**
* Creates a Query from a named query.
*
* @param string $name
*
* @return Query
*/
public function createNamedQuery($name);
/**
* Creates a native SQL query.
*
* @param string $sql
* @param ResultSetMapping $rsm The ResultSetMapping to use.
*
* @return NativeQuery
*/
public function createNativeQuery($sql, ResultSetMapping $rsm);
/**
* Creates a NativeQuery from a named native query.
*
* @param string $name
*
* @return NativeQuery
*/
public function createNamedNativeQuery($name);
/**
* Create a QueryBuilder instance
*
* @return QueryBuilder
*/
public function createQueryBuilder();
/**
* Gets a reference to the entity identified by the given type and identifier
* without actually loading it, if the entity is not yet loaded.
*
* @param string $entityName The name of the entity type.
* @param mixed $id The entity identifier.
*
* @return object The entity reference.
*
* @throws ORMException
*/
public function getReference($entityName, $id);
/**
* Gets a partial reference to the entity identified by the given type and identifier
* without actually loading it, if the entity is not yet loaded.
*
* The returned reference may be a partial object if the entity is not yet loaded/managed.
* If it is a partial object it will not initialize the rest of the entity state on access.
* Thus you can only ever safely access the identifier of an entity obtained through
* this method.
*
* The use-cases for partial references involve maintaining bidirectional associations
* without loading one side of the association or to update an entity without loading it.
* Note, however, that in the latter case the original (persistent) entity data will
* never be visible to the application (especially not event listeners) as it will
* never be loaded in the first place.
*
* @param string $entityName The name of the entity type.
* @param mixed $identifier The entity identifier.
*
* @return object The (partial) entity reference.
*/
public function getPartialReference($entityName, $identifier);
/**
* Closes the EntityManager. All entities that are currently managed
* by this EntityManager become detached. The EntityManager may no longer
* be used after it is closed.
*
* @return void
*/
public function close();
/**
* Creates a copy of the given entity. Can create a shallow or a deep copy.
*
* @param object $entity The entity to copy.
* @param boolean $deep FALSE for a shallow copy, TRUE for a deep copy.
*
* @return object The new entity.
*
* @throws \BadMethodCallException
*/
public function copy($entity, $deep = false);
/**
* Acquire a lock on the given entity.
*
* @param object $entity
* @param int $lockMode
* @param int|null $lockVersion
*
* @return void
*
* @throws OptimisticLockException
* @throws PessimisticLockException
*/
public function lock($entity, $lockMode, $lockVersion = null);
/**
* Gets the EventManager used by the EntityManager.
*
* @return \Doctrine\Common\EventManager
*/
public function getEventManager();
/**
* Gets the Configuration used by the EntityManager.
*
* @return Configuration
*/
public function getConfiguration();
/**
* Check if the Entity manager is open or closed.
*
* @return bool
*/
public function isOpen();
/**
* Gets the UnitOfWork used by the EntityManager to coordinate operations.
*
* @return UnitOfWork
*/
public function getUnitOfWork();
/**
* Gets a hydrator for the given hydration mode.
*
* This method caches the hydrator instances which is used for all queries that don't
* selectively iterate over the result.
*
* @deprecated
*
* @param int $hydrationMode
*
* @return \Doctrine\ORM\Internal\Hydration\AbstractHydrator
*/
public function getHydrator($hydrationMode);
/**
* Create a new instance for the given hydration mode.
*
* @param int $hydrationMode
*
* @return \Doctrine\ORM\Internal\Hydration\AbstractHydrator
*
* @throws ORMException
*/
public function newHydrator($hydrationMode);
/**
* Gets the proxy factory used by the EntityManager to create entity proxies.
*
* @return \Doctrine\ORM\Proxy\ProxyFactory
*/
public function getProxyFactory();
/**
* Gets the enabled filters.
*
* @return \Doctrine\ORM\Query\FilterCollection The active filter collection.
*/
public function getFilters();
/**
* Checks whether the state of the filter collection is clean.
*
* @return boolean True, if the filter collection is clean.
*/
public function isFiltersStateClean();
/**
* Checks whether the Entity Manager has filters.
*
* @return boolean True, if the EM has a filter collection.
*/
public function hasFilters();
}

View File

@@ -78,7 +78,6 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
protected function initialize()
{
$this->driver = $this->em->getConfiguration()->getMetadataDriverImpl();
$this->targetPlatform = $this->em->getConnection()->getDatabasePlatform();
$this->evm = $this->em->getEventManager();
$this->initialized = true;
}
@@ -432,9 +431,9 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
{
$idGenType = $class->generatorType;
if ($idGenType == ClassMetadata::GENERATOR_TYPE_AUTO) {
if ($this->targetPlatform->prefersSequences()) {
if ($this->getTargetPlatform()->prefersSequences()) {
$class->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_SEQUENCE);
} else if ($this->targetPlatform->prefersIdentityColumns()) {
} else if ($this->getTargetPlatform()->prefersIdentityColumns()) {
$class->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_IDENTITY);
} else {
$class->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_TABLE);
@@ -450,19 +449,23 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
$sequenceName = null;
$fieldName = $class->identifier ? $class->getSingleIdentifierFieldName() : null;
if ($this->targetPlatform instanceof Platforms\PostgreSQLPlatform) {
if ($this->getTargetPlatform() instanceof Platforms\PostgreSQLPlatform) {
$columnName = $class->getSingleIdentifierColumnName();
$quoted = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']);
$sequenceName = $class->getTableName() . '_' . $columnName . '_seq';
$definition = array(
'sequenceName' => $this->targetPlatform->fixSchemaElementName($sequenceName)
'sequenceName' => $this->getTargetPlatform()->fixSchemaElementName($sequenceName)
);
if ($quoted) {
$definition['quoted'] = true;
}
$sequenceName = $this->em->getConfiguration()->getQuoteStrategy()->getSequenceName($definition, $class, $this->targetPlatform);
$sequenceName = $this
->em
->getConfiguration()
->getQuoteStrategy()
->getSequenceName($definition, $class, $this->getTargetPlatform());
}
$generator = ($fieldName && $class->fieldMappings[$fieldName]['type'] === 'bigint')
@@ -483,7 +486,7 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
$quoted = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']);
$sequenceName = $class->getTableName() . '_' . $columnName . '_seq';
$definition = array(
'sequenceName' => $this->targetPlatform->fixSchemaElementName($sequenceName),
'sequenceName' => $this->getTargetPlatform()->fixSchemaElementName($sequenceName),
'allocationSize' => 1,
'initialValue' => 1,
);
@@ -496,7 +499,7 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
}
$sequenceGenerator = new \Doctrine\ORM\Id\SequenceGenerator(
$this->em->getConfiguration()->getQuoteStrategy()->getSequenceName($definition, $class, $this->targetPlatform),
$this->em->getConfiguration()->getQuoteStrategy()->getSequenceName($definition, $class, $this->getTargetPlatform()),
$definition['allocationSize']
);
$class->setIdGenerator($sequenceGenerator);
@@ -569,4 +572,16 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
{
return isset($class->isMappedSuperclass) && $class->isMappedSuperclass === false;
}
/**
* @return Platforms\AbstractPlatform
*/
private function getTargetPlatform()
{
if (!$this->targetPlatform) {
$this->targetPlatform = $this->em->getConnection()->getDatabasePlatform();
}
return $this->targetPlatform;
}
}

View File

@@ -866,7 +866,7 @@ class ClassMetadataInfo implements ClassMetadata
public function newInstance()
{
if ($this->_prototype === null) {
if (PHP_VERSION_ID === 50429 || PHP_VERSION_ID === 50513) {
if (PHP_VERSION_ID === 50429 || PHP_VERSION_ID === 50513 || PHP_VERSION_ID >= 50600) {
$this->_prototype = $this->reflClass->newInstanceWithoutConstructor();
} else {
$this->_prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name));

View File

@@ -416,7 +416,7 @@ class BasicEntityPersister
break;
}
$params[] = $value;
$set[] = $column . ' = ' . $placeholder;
$types[] = $this->columnTypes[$columnName];
@@ -850,7 +850,7 @@ class BasicEntityPersister
$sql = $this->getSelectSQL($id, null, $lockMode);
list($params, $types) = $this->expandParameters($id);
$stmt = $this->conn->executeQuery($sql, $params, $types);
$hydrator = $this->em->newHydrator(Query::HYDRATE_OBJECT);
$hydrator->hydrateAll($stmt, $this->rsm, array(Query::HINT_REFRESH => true));
}
@@ -1130,7 +1130,7 @@ class BasicEntityPersister
$tableName = $this->quoteStrategy->getTableName($this->class, $this->platform);
if ('' !== $filterSql) {
$conditionSql = $conditionSql
$conditionSql = $conditionSql
? $conditionSql . ' AND ' . $filterSql
: $filterSql;
}
@@ -1283,7 +1283,7 @@ class BasicEntityPersister
if ($assoc['isOwningSide']) {
$tableAlias = $this->getSQLTableAlias($association['targetEntity'], $assocAlias);
$this->selectJoinSql .= ' ' . $this->getJoinSQLForJoinColumns($association['joinColumns']);
foreach ($association['joinColumns'] as $joinColumn) {
$sourceCol = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform);
$targetCol = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $this->class, $this->platform);
@@ -1415,7 +1415,7 @@ class BasicEntityPersister
foreach ($columns as $column) {
$placeholder = '?';
if (isset($this->class->fieldNames[$column])
if (isset($this->class->fieldNames[$column])
&& isset($this->columnTypes[$this->class->fieldNames[$column]])
&& isset($this->class->fieldMappings[$this->class->fieldNames[$column]]['requireSQLConversion'])) {
@@ -1488,7 +1488,7 @@ class BasicEntityPersister
$columnName = $this->quoteStrategy->getColumnName($field, $class, $this->platform);
$sql = $tableAlias . '.' . $columnName;
$columnAlias = $this->getSQLColumnAlias($class->columnNames[$field]);
$this->rsm->addFieldResult($alias, $columnAlias, $field);
if (isset($class->fieldMappings[$field]['requireSQLConversion'])) {
@@ -1550,7 +1550,7 @@ class BasicEntityPersister
break;
}
$lock = $this->platform->appendLockHint($this->getLockTablesSql(), $lockMode);
$lock = $this->getLockTablesSql($lockMode);
$where = ($conditionSql ? ' WHERE ' . $conditionSql : '') . ' ';
$sql = 'SELECT 1 '
. $lock
@@ -1565,13 +1565,18 @@ class BasicEntityPersister
/**
* Gets the FROM and optionally JOIN conditions to lock the entity managed by this persister.
*
* @param integer $lockMode One of the Doctrine\DBAL\LockMode::* constants.
*
* @return string
*/
protected function getLockTablesSql()
protected function getLockTablesSql($lockMode)
{
return 'FROM '
. $this->quoteStrategy->getTableName($this->class, $this->platform) . ' '
. $this->getSQLTableAlias($this->class->name);
return $this->platform->appendLockHint(
'FROM '
. $this->quoteStrategy->getTableName($this->class, $this->platform) . ' '
. $this->getSQLTableAlias($this->class->name),
$lockMode
);
}
/**
@@ -1910,7 +1915,7 @@ class BasicEntityPersister
$alias = $this->getSQLTableAlias($this->class->name);
$sql = 'SELECT 1 '
. $this->getLockTablesSql()
. $this->getLockTablesSql(null)
. ' WHERE ' . $this->getSelectConditionSQL($criteria);
if ($filterSql = $this->generateFilterConditionSQL($this->class, $alias)) {

View File

@@ -288,7 +288,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
foreach ($this->class->parentClasses as $parentClass) {
$parentMetadata = $this->em->getClassMetadata($parentClass);
$parentTable = $this->quoteStrategy->getTableName($parentMetadata, $this->platform);
$this->conn->delete($parentTable, $id);
}
}
@@ -342,7 +342,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
// If the current class in the root entity, add the filters
if ($filterSql = $this->generateFilterConditionSQL($this->em->getClassMetadata($this->class->rootEntityName), $this->getSQLTableAlias($this->class->rootEntityName))) {
$conditionSql .= $conditionSql
$conditionSql .= $conditionSql
? ' AND ' . $filterSql
: $filterSql;
}
@@ -387,16 +387,13 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
}
/**
* Get the FROM and optionally JOIN conditions to lock the entity managed by this persister.
*
* @return string
* {@inheritdoc}
*/
public function getLockTablesSql()
protected function getLockTablesSql($lockMode)
{
$joinSql = '';
$identifierColumns = $this->class->getIdentifierColumnNames();
$baseTableAlias = $this->getSQLTableAlias($this->class->name);
$quotedTableName = $this->quoteStrategy->getTableName($this->class, $this->platform);
// INNER JOIN parent tables
foreach ($this->class->parentClasses as $parentClassName) {
@@ -412,7 +409,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
$joinSql .= implode(' AND ', $conditions);
}
return 'FROM ' . $quotedTableName . ' ' . $baseTableAlias . $joinSql;
return parent::getLockTablesSql($lockMode) . $joinSql;
}
/**
@@ -488,8 +485,8 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
// Add join columns (foreign keys)
foreach ($subClass->associationMappings as $mapping) {
if ( ! $mapping['isOwningSide']
|| ! ($mapping['type'] & ClassMetadata::TO_ONE)
if ( ! $mapping['isOwningSide']
|| ! ($mapping['type'] & ClassMetadata::TO_ONE)
|| isset($mapping['inherited'])) {
continue;
}
@@ -505,17 +502,17 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
}
$this->selectColumnListSql = implode(', ', $columnList);
return $this->selectColumnListSql;
}
/**
* {@inheritdoc}
* {@inheritdoc}
*/
protected function getInsertColumnList()
{
// Identifier columns must always come first in the column list of subclasses.
$columns = $this->class->parentClasses
$columns = $this->class->parentClasses
? $this->class->getIdentifierColumnNames()
: array();

View File

@@ -222,6 +222,13 @@ class OneToManyPersister extends AbstractCollectionPersister
*/
public function removeElement(PersistentCollection $coll, $element)
{
$mapping = $coll->getMapping();
if ( ! $mapping['orphanRemoval']) {
// no-op: this is not the owning side, therefore no operations should be applied
return false;
}
$uow = $this->em->getUnitOfWork();
// shortcut for new entities
@@ -237,11 +244,11 @@ class OneToManyPersister extends AbstractCollectionPersister
return false;
}
$mapping = $coll->getMapping();
$class = $this->em->getClassMetadata($mapping['targetEntity']);
$sql = 'DELETE FROM ' . $this->quoteStrategy->getTableName($class, $this->platform)
. ' WHERE ' . implode('= ? AND ', $class->getIdentifierColumnNames()) . ' = ?';
$this
->uow
->getEntityPersister($mapping['targetEntity'])
->delete($element);
return (bool) $this->conn->executeUpdate($sql, $this->getDeleteRowSQLParameters($coll, $element));
return true;
}
}

View File

@@ -456,7 +456,7 @@ class SqlWalker implements TreeWalker
}
$sqlParts[] = (($this->useSqlTableAliases) ? $this->getSQLTableAlias($class->getTableName(), $dqlAlias) . '.' : '')
. $class->discriminatorColumn['name'] . ' IN (' . implode(', ', $values) . ')';
. $class->discriminatorColumn['name'] . ' IN (' . implode(', ', $values) . ')';
}
$sql = implode(' AND ', $sqlParts);
@@ -496,7 +496,7 @@ class SqlWalker implements TreeWalker
default:
//@todo: throw exception?
return '';
break;
break;
}
$filterClauses = array();
@@ -574,7 +574,7 @@ class SqlWalker implements TreeWalker
$this->useSqlTableAliases = false;
return $this->walkUpdateClause($AST->updateClause)
. $this->walkWhereClause($AST->whereClause);
. $this->walkWhereClause($AST->whereClause);
}
/**
@@ -585,7 +585,7 @@ class SqlWalker implements TreeWalker
$this->useSqlTableAliases = false;
return $this->walkDeleteClause($AST->deleteClause)
. $this->walkWhereClause($AST->whereClause);
. $this->walkWhereClause($AST->whereClause);
}
/**
@@ -700,10 +700,10 @@ class SqlWalker implements TreeWalker
}
$addMetaColumns = ! $this->query->getHint(Query::HINT_FORCE_PARTIAL_LOAD) &&
$this->query->getHydrationMode() == Query::HYDRATE_OBJECT
||
$this->query->getHydrationMode() != Query::HYDRATE_OBJECT &&
$this->query->getHint(Query::HINT_INCLUDE_META_COLUMNS);
$this->query->getHydrationMode() == Query::HYDRATE_OBJECT
||
$this->query->getHydrationMode() != Query::HYDRATE_OBJECT &&
$this->query->getHint(Query::HINT_INCLUDE_META_COLUMNS);
foreach ($this->selectedClasses as $selectedClass) {
$class = $selectedClass['class'];
@@ -801,10 +801,7 @@ class SqlWalker implements TreeWalker
$sqlParts = array();
foreach ($identificationVarDecls as $identificationVariableDecl) {
$sql = $this->platform->appendLockHint(
$this->walkRangeVariableDeclaration($identificationVariableDecl->rangeVariableDeclaration),
$this->query->getHint(Query::HINT_LOCK_MODE)
);
$sql = $this->walkRangeVariableDeclaration($identificationVariableDecl->rangeVariableDeclaration);
foreach ($identificationVariableDecl->joins as $join) {
$sql .= $this->walkJoin($join);
@@ -846,8 +843,11 @@ class SqlWalker implements TreeWalker
$this->rootAliases[] = $dqlAlias;
}
$sql = $this->quoteStrategy->getTableName($class,$this->platform) . ' '
. $this->getSQLTableAlias($class->getTableName(), $dqlAlias);
$sql = $this->platform->appendLockHint(
$this->quoteStrategy->getTableName($class, $this->platform) . ' ' .
$this->getSQLTableAlias($class->getTableName(), $dqlAlias),
$this->query->getHint(Query::HINT_LOCK_MODE)
);
if ($class->isInheritanceTypeJoined()) {
$sql .= $this->_generateClassTableInheritanceJoins($class, $dqlAlias);
@@ -892,6 +892,8 @@ class SqlWalker implements TreeWalker
}
}
$targetTableJoin = null;
// This condition is not checking ClassMetadata::MANY_TO_ONE, because by definition it cannot
// be the owning side and previously we ensured that $assoc is always the owning side of the associations.
// The owning side is necessary at this point because only it contains the JoinColumn information.
@@ -899,7 +901,7 @@ class SqlWalker implements TreeWalker
case ($assoc['type'] & ClassMetadata::TO_ONE):
$conditions = array();
foreach ($assoc['joinColumns'] as $joinColumn) {
foreach ($assoc['joinColumns'] as $joinColumn) {
$quotedSourceColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform);
$quotedTargetColumn = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $targetClass, $this->platform);
@@ -926,7 +928,10 @@ class SqlWalker implements TreeWalker
$conditions[] = $filterExpr;
}
$sql .= $targetTableName . ' ' . $targetTableAlias . ' ON ' . implode(' AND ', $conditions);
$targetTableJoin = array(
'table' => $targetTableName . ' ' . $targetTableAlias,
'condition' => implode(' AND ', $conditions),
);
break;
case ($assoc['type'] == ClassMetadata::MANY_TO_MANY):
@@ -978,20 +983,30 @@ class SqlWalker implements TreeWalker
$conditions[] = $filterExpr;
}
$sql .= $targetTableName . ' ' . $targetTableAlias . ' ON ' . implode(' AND ', $conditions);
$targetTableJoin = array(
'table' => $targetTableName . ' ' . $targetTableAlias,
'condition' => implode(' AND ', $conditions),
);
break;
}
// Handle WITH clause
if ($condExpr !== null) {
// Phase 2 AST optimization: Skip processing of ConditionalExpression
// if only one ConditionalTerm is defined
$sql .= ' AND (' . $this->walkConditionalExpression($condExpr) . ')';
$withCondition = (null === $condExpr) ? '' : ('(' . $this->walkConditionalExpression($condExpr) . ')');
if ($targetClass->isInheritanceTypeJoined()) {
$ctiJoins = $this->_generateClassTableInheritanceJoins($targetClass, $joinedDqlAlias);
// If we have WITH condition, we need to build nested joins for target class table and cti joins
if ($withCondition) {
$sql .= '(' . $targetTableJoin['table'] . $ctiJoins . ') ON ' . $targetTableJoin['condition'];
} else {
$sql .= $targetTableJoin['table'] . ' ON ' . $targetTableJoin['condition'] . $ctiJoins;
}
} else {
$sql .= $targetTableJoin['table'] . ' ON ' . $targetTableJoin['condition'];
}
// FIXME: these should either be nested or all forced to be left joins (DDC-XXX)
if ($targetClass->isInheritanceTypeJoined()) {
$sql .= $this->_generateClassTableInheritanceJoins($targetClass, $joinedDqlAlias);
if ($withCondition) {
$sql .= ' AND ' . $withCondition;
}
// Apply the indexes
@@ -1439,10 +1454,7 @@ class SqlWalker implements TreeWalker
$sqlParts = array ();
foreach ($identificationVarDecls as $subselectIdVarDecl) {
$sql = $this->platform->appendLockHint(
$this->walkRangeVariableDeclaration($subselectIdVarDecl->rangeVariableDeclaration),
$this->query->getHint(Query::HINT_LOCK_MODE)
);
$sql = $this->walkRangeVariableDeclaration($subselectIdVarDecl->rangeVariableDeclaration);
foreach ($subselectIdVarDecl->joins as $join) {
$sql .= $this->walkJoin($join);
@@ -1460,7 +1472,7 @@ class SqlWalker implements TreeWalker
public function walkSimpleSelectClause($simpleSelectClause)
{
return 'SELECT' . ($simpleSelectClause->isDistinct ? ' DISTINCT' : '')
. $this->walkSimpleSelectExpression($simpleSelectClause->simpleSelectExpression);
. $this->walkSimpleSelectExpression($simpleSelectClause->simpleSelectExpression);
}
/**
@@ -1592,7 +1604,7 @@ class SqlWalker implements TreeWalker
public function walkAggregateExpression($aggExpression)
{
return $aggExpression->functionName . '(' . ($aggExpression->isDistinct ? 'DISTINCT ' : '')
. $this->walkSimpleArithmeticExpression($aggExpression->pathExpression) . ')';
. $this->walkSimpleArithmeticExpression($aggExpression->pathExpression) . ')';
}
/**
@@ -1887,7 +1899,7 @@ class SqlWalker implements TreeWalker
// join to target table
$sql .= $this->quoteStrategy->getJoinTableName($owningAssoc, $targetClass, $this->platform) . ' ' . $joinTableAlias
. ' INNER JOIN ' . $this->quoteStrategy->getTableName($targetClass, $this->platform) . ' ' . $targetTableAlias . ' ON ';
. ' INNER JOIN ' . $this->quoteStrategy->getTableName($targetClass, $this->platform) . ' ' . $targetTableAlias . ' ON ';
// join conditions
$joinColumns = $assoc['isOwningSide'] ? $joinTable['inverseJoinColumns'] : $joinTable['joinColumns'];
@@ -2067,7 +2079,7 @@ class SqlWalker implements TreeWalker
if ($betweenExpr->not) $sql .= ' NOT';
$sql .= ' BETWEEN ' . $this->walkArithmeticExpression($betweenExpr->leftBetweenExpression)
. ' AND ' . $this->walkArithmeticExpression($betweenExpr->rightBetweenExpression);
. ' AND ' . $this->walkArithmeticExpression($betweenExpr->rightBetweenExpression);
return $sql;
}

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

@@ -340,7 +340,7 @@ public function __construct()
$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);
@@ -365,6 +365,7 @@ public function __construct()
} elseif ( ! $this->isNew && $this->updateEntityIfExists) {
file_put_contents($path, $this->generateUpdatedEntityClass($metadata, $path));
}
chmod($path, 0664);
}
/**
@@ -679,7 +680,7 @@ public function __construct()
if ($token[0] == T_NAMESPACE) {
$lastSeenNamespace = "";
$inNamespace = true;
} elseif ($token[0] == T_CLASS) {
} elseif ($token[0] == T_CLASS && $tokens[$i-1][0] != T_DOUBLE_COLON) {
$inClass = true;
} elseif ($token[0] == T_FUNCTION) {
if ($tokens[$i+2][0] == T_STRING) {
@@ -701,9 +702,9 @@ public function __construct()
*/
protected function hasProperty($property, ClassMetadataInfo $metadata)
{
if ($this->extendsClass()) {
if ($this->extendsClass() || (!$this->isNew && class_exists($metadata->name))) {
// don't generate property if its already on the base class.
$reflClass = new \ReflectionClass($this->getClassToExtend());
$reflClass = new \ReflectionClass($this->getClassToExtend() ?: $metadata->name);
if ($reflClass->hasProperty($property)) {
return true;
}
@@ -723,9 +724,9 @@ public function __construct()
*/
protected function hasMethod($method, ClassMetadataInfo $metadata)
{
if ($this->extendsClass()) {
if ($this->extendsClass() || (!$this->isNew && class_exists($metadata->name))) {
// don't generate method if its already on the base class.
$reflClass = new \ReflectionClass($this->getClassToExtend());
$reflClass = new \ReflectionClass($this->getClassToExtend() ?: $metadata->name);
if ($reflClass->hasMethod($method)) {
return true;
@@ -1074,7 +1075,7 @@ public function __construct()
$lines[] = $this->generateFieldMappingPropertyDocBlock($fieldMapping, $metadata);
$lines[] = $this->spaces . $this->fieldVisibility . ' $' . $fieldMapping['fieldName']
. (isset($fieldMapping['default']) ? ' = ' . var_export($fieldMapping['default'], true) : null) . ";\n";
. (isset($fieldMapping['options']['default']) ? ' = ' . var_export($fieldMapping['options']['default'], true) : null) . ";\n";
}
return implode("\n", $lines);

View File

@@ -96,11 +96,12 @@ class <className> extends EntityRepository
$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

@@ -13,6 +13,7 @@
namespace Doctrine\ORM\Tools\Pagination;
use Doctrine\ORM\Query\AST\PathExpression;
use Doctrine\ORM\Query\SqlWalker;
use Doctrine\ORM\Query\AST\SelectStatement;
use Doctrine\DBAL\Platforms\PostgreSqlPlatform;
@@ -92,25 +93,22 @@ class LimitSubqueryOutputWalker extends SqlWalker
*/
public function walkSelectStatement(SelectStatement $AST)
{
if ($this->platform instanceof PostgreSqlPlatform) {
// Set every select expression as visible(hidden = false) to
// make $AST to have scalar mappings properly
$hiddens = array();
foreach ($AST->selectClause->selectExpressions as $idx => $expr) {
$hiddens[$idx] = $expr->hiddenAliasResultVariable;
$expr->hiddenAliasResultVariable = false;
}
// Set every select expression as visible(hidden = false) to
// make $AST have scalar mappings properly - this is relevant for referencing selected
// fields from outside the subquery, for example in the ORDER BY segment
$hiddens = array();
$innerSql = parent::walkSelectStatement($AST);
// Restore hiddens
foreach ($AST->selectClause->selectExpressions as $idx => $expr) {
$expr->hiddenAliasResultVariable = $hiddens[$idx];
}
} else {
$innerSql = parent::walkSelectStatement($AST);
foreach ($AST->selectClause->selectExpressions as $idx => $expr) {
$hiddens[$idx] = $expr->hiddenAliasResultVariable;
$expr->hiddenAliasResultVariable = false;
}
$innerSql = parent::walkSelectStatement($AST);
// Restore hiddens
foreach ($AST->selectClause->selectExpressions as $idx => $expr) {
$expr->hiddenAliasResultVariable = $hiddens[$idx];
}
// Find out the SQL alias of the identifier column of the root entity.
// It may be possible to make this work with multiple root entities but that
@@ -196,12 +194,14 @@ class LimitSubqueryOutputWalker extends SqlWalker
$orderBy = array();
if (isset($AST->orderByClause)) {
foreach ($AST->orderByClause->orderByItems as $item) {
$possibleAliases = (is_object($item->expression))
? array_keys($this->rsm->fieldMappings, $item->expression->field)
: array_keys($this->rsm->scalarMappings, $item->expression);
$expression = $item->expression;
$possibleAliases = $expression instanceof PathExpression
? array_keys($this->rsm->fieldMappings, $expression->field)
: array_keys($this->rsm->scalarMappings, $expression);
foreach ($possibleAliases as $alias) {
if (!is_object($item->expression) || $this->rsm->columnOwnerMap[$alias] == $item->expression->identificationVariable) {
if (!is_object($expression) || $this->rsm->columnOwnerMap[$alias] == $expression->identificationVariable) {
$sqlOrderColumns[] = $alias;
$orderBy[] = $alias . ' ' . $item->type;
break;

View File

@@ -19,6 +19,7 @@
namespace Doctrine\ORM\Tools\Pagination;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\QueryBuilder;
use Doctrine\ORM\Query;
use Doctrine\ORM\Query\ResultSetMapping;
@@ -118,31 +119,8 @@ class Paginator implements \Countable, \IteratorAggregate
public function count()
{
if ($this->count === null) {
/* @var $countQuery Query */
$countQuery = $this->cloneQuery($this->query);
if ( ! $countQuery->hasHint(CountWalker::HINT_DISTINCT)) {
$countQuery->setHint(CountWalker::HINT_DISTINCT, true);
}
if ($this->useOutputWalker($countQuery)) {
$platform = $countQuery->getEntityManager()->getConnection()->getDatabasePlatform(); // law of demeter win
$rsm = new ResultSetMapping();
$rsm->addScalarResult($platform->getSQLResultCasing('dctrn_count'), 'count');
$countQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Tools\Pagination\CountOutputWalker');
$countQuery->setResultSetMapping($rsm);
} else {
$this->appendTreeWalker($countQuery, 'Doctrine\ORM\Tools\Pagination\CountWalker');
}
$countQuery->setFirstResult(null)->setMaxResults(null);
try {
$data = $countQuery->getScalarResult();
$data = array_map('current', $data);
$this->count = array_sum($data);
$this->count = array_sum(array_map('current', $this->getCountQuery()->getScalarResult()));
} catch(NoResultException $e) {
$this->count = 0;
}
@@ -249,4 +227,50 @@ class Paginator implements \Countable, \IteratorAggregate
$hints[] = $walkerClass;
$query->setHint(Query::HINT_CUSTOM_TREE_WALKERS, $hints);
}
/**
* Returns Query prepared to count.
*
* @return Query
*/
private function getCountQuery()
{
/* @var $countQuery Query */
$countQuery = $this->cloneQuery($this->query);
if ( ! $countQuery->hasHint(CountWalker::HINT_DISTINCT)) {
$countQuery->setHint(CountWalker::HINT_DISTINCT, true);
}
if ($this->useOutputWalker($countQuery)) {
$platform = $countQuery->getEntityManager()->getConnection()->getDatabasePlatform(); // law of demeter win
$rsm = new ResultSetMapping();
$rsm->addScalarResult($platform->getSQLResultCasing('dctrn_count'), 'count');
$countQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Tools\Pagination\CountOutputWalker');
$countQuery->setResultSetMapping($rsm);
} else {
$this->appendTreeWalker($countQuery, 'Doctrine\ORM\Tools\Pagination\CountWalker');
}
$countQuery->setFirstResult(null)->setMaxResults(null);
$parser = new Parser($countQuery);
$parameterMappings = $parser->parse()->getParameterMappings();
/* @var $parameters \Doctrine\Common\Collections\Collection|\Doctrine\ORM\Query\Parameter[] */
$parameters = $countQuery->getParameters();
foreach ($parameters as $key => $parameter) {
$parameterName = $parameter->getName();
if( ! (isset($parameterMappings[$parameterName]) || array_key_exists($parameterName, $parameterMappings))) {
unset($parameters[$key]);
}
}
$countQuery->setParameters($parameters);
return $countQuery;
}
}

View File

@@ -430,7 +430,7 @@ class SchemaTool
$knownOptions = array('comment', 'unsigned', 'fixed', 'default');
foreach ($knownOptions as $knownOption) {
if ( isset($mapping['options'][$knownOption])) {
if (array_key_exists($knownOption, $mapping['options'])) {
$options[$knownOption] = $mapping['options'][$knownOption];
unset($mapping['options'][$knownOption]);

View File

@@ -1630,6 +1630,7 @@ class UnitOfWork implements PropertyChangedListener
case self::STATE_REMOVED:
// Entity becomes managed again
unset($this->entityDeletions[$oid]);
$this->addToIdentityMap($entity);
$this->entityStates[$oid] = self::STATE_MANAGED;
break;
@@ -2314,6 +2315,10 @@ class UnitOfWork implements PropertyChangedListener
return;
}
if ($entity instanceof Proxy && !$entity->__isInitialized__) {
$entity->__load();
}
$entityVersion = $class->reflFields[$class->versionField]->getValue($entity);
if ($entityVersion != $lockVersion) {

View File

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

View File

@@ -83,7 +83,7 @@ class ConnectionMock extends \Doctrine\DBAL\Connection
/**
* {@inheritdoc}
*/
public function fetchColumn($statement, array $params = array(), $colnum = 0)
public function fetchColumn($statement, array $params = array(), $column = 0, array $types = array())
{
return $this->_fetchOneResult;
}

View File

@@ -0,0 +1,56 @@
<?php
namespace Doctrine\Tests\Models\DDC1590;
/**
* @Entity
* @MappedSuperClass
*/
abstract class DDC1590Entity
{
/**
* @Id
* @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @Column(type="datetime")
*/
protected $created_at;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set createdAt
*
* @param \DateTime $createdAt
*
* @return DDC1590User
*/
public function setCreatedAt($createdAt)
{
$this->created_at = $createdAt;
return $this;
}
/**
* Get createdAt
*
* @return \DateTime
*/
public function getCreatedAt()
{
return $this->created_at;
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Doctrine\Tests\Models\DDC1590;
use Doctrine\Tests\Models\DDC1590\DDC1590Entity;
/**
* @Entity
* @Table(name="users")
*/
class DDC1590User extends DDC1590Entity
{
/**
* @Column(type="string", length=255)
*/
protected $name;
}

View File

@@ -0,0 +1,13 @@
<?php
namespace Doctrine\Tests\Models\NullDefault;
/** @Entity */
class NullDefaultColumn
{
/** @Id @GeneratedValue @Column(type="integer") */
public $id;
/** @Column(options={"default":NULL}) */
public $nullDefault;
}

View File

@@ -0,0 +1,37 @@
<?php
namespace Doctrine\Tests\Models\Tweet;
/**
* @Entity
* @Table(name="tweet_tweet")
*/
class Tweet
{
const CLASSNAME = __CLASS__;
/**
* @Id
* @GeneratedValue
* @Column(type="integer")
*/
public $id;
/**
* @Column(type="string", length=140)
*/
public $content = '';
/**
* @ManyToOne(targetEntity="User", inversedBy="tweets", cascade={"persist"}, fetch="EXTRA_LAZY")
*/
public $author;
/**
* @param User $author
*/
public function setAuthor(User $author)
{
$this->author = $author;
}
}

View File

@@ -0,0 +1,54 @@
<?php
namespace Doctrine\Tests\Models\Tweet;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @Entity
* @Table(name="tweet_user")
*/
class User
{
const CLASSNAME = __CLASS__;
/**
* @Id
* @GeneratedValue
* @Column(type="integer")
*/
public $id;
/**
* @Column(type="string")
*/
public $name;
/**
* @OneToMany(targetEntity="Tweet", mappedBy="author", cascade={"persist"}, fetch="EXTRA_LAZY")
*/
public $tweets;
/**
* @OneToMany(targetEntity="UserList", mappedBy="owner", fetch="EXTRA_LAZY", orphanRemoval=true)
*/
public $userLists;
public function __construct()
{
$this->tweets = new ArrayCollection();
$this->userLists = new ArrayCollection();
}
public function addTweet(Tweet $tweet)
{
$tweet->setAuthor($this);
$this->tweets->add($tweet);
}
public function addUserList(UserList $userList)
{
$userList->owner = $this;
$this->userLists->add($userList);
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace Doctrine\Tests\Models\Tweet;
/**
* @Entity
* @Table(name="tweet_user_list")
*/
class UserList
{
const CLASSNAME = __CLASS__;
/**
* @Id
* @GeneratedValue
* @Column(type="integer")
*/
public $id;
/**
* @Column(type="string")
*/
public $listName;
/**
* @ManyToOne(targetEntity="User", inversedBy="userLists")
*/
public $owner;
}

View File

@@ -3,6 +3,9 @@
namespace Doctrine\Tests\ORM\Functional;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\Tests\Models\Tweet\Tweet;
use Doctrine\Tests\Models\Tweet\User;
use Doctrine\Tests\Models\Tweet\UserList;
require_once __DIR__ . '/../../TestInit.php';
@@ -22,7 +25,10 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
public function setUp()
{
$this->useModelSet('tweet');
$this->useModelSet('cms');
$this->useModelSet('tweet');
parent::setUp();
$class = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
@@ -363,7 +369,7 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
$user->articles->removeElement($article);
$this->assertFalse($user->articles->isInitialized(), "Post-Condition: Collection is not initialized.");
$this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
$this->assertEquals($queryCount, $this->getCurrentQueryCount());
// Test One to Many removal with Entity state as new
$article = new \Doctrine\Tests\Models\CMS\CmsArticle();
@@ -384,7 +390,7 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
$user->articles->removeElement($article);
$this->assertEquals($queryCount + 1, $this->getCurrentQueryCount(), "Removing a persisted entity should cause one query to be executed.");
$this->assertEquals($queryCount, $this->getCurrentQueryCount(), "Removing a persisted entity should cause one query to be executed.");
$this->assertFalse($user->articles->isInitialized(), "Post-Condition: Collection is not initialized.");
// Test One to Many removal with Entity state as managed
@@ -650,4 +656,204 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->topic = $article1->topic;
$this->phonenumber = $phonenumber1->phonenumber;
}
/**
* @group DDC-3343
*/
public function testRemoveManagedElementFromOneToManyExtraLazyCollectionIsNoOp()
{
list($userId, $tweetId) = $this->loadTweetFixture();
/* @var $user User */
$user = $this->_em->find(User::CLASSNAME, $userId);
$user->tweets->removeElement($this->_em->find(Tweet::CLASSNAME, $tweetId));
$this->_em->clear();
/* @var $user User */
$user = $this->_em->find(User::CLASSNAME, $userId);
$this->assertCount(1, $user->tweets, 'Element was not removed - need to update the owning side first');
}
/**
* @group DDC-3343
*/
public function testRemoveManagedElementFromOneToManyExtraLazyCollectionWithoutDeletingTheTargetEntityEntryIsNoOp()
{
list($userId, $tweetId) = $this->loadTweetFixture();
/* @var $user User */
$user = $this->_em->find(User::CLASSNAME, $userId);
$tweet = $this->_em->find(Tweet::CLASSNAME, $tweetId);
$user->tweets->removeElement($tweet);
$this->_em->clear();
/* @var $tweet Tweet */
$tweet = $this->_em->find(Tweet::CLASSNAME, $tweetId);
$this->assertInstanceOf(
Tweet::CLASSNAME,
$tweet,
'Even though the collection is extra lazy, the tweet should not have been deleted'
);
$this->assertInstanceOf(
User::CLASSNAME,
$tweet->author,
'Tweet author link has not been removed - need to update the owning side first'
);
}
/**
* @group DDC-3343
*/
public function testRemovingManagedLazyProxyFromExtraLazyOneToManyDoesRemoveTheAssociationButNotTheEntity()
{
list($userId, $tweetId) = $this->loadTweetFixture();
/* @var $user User */
$user = $this->_em->find(User::CLASSNAME, $userId);
$tweet = $this->_em->getReference(Tweet::CLASSNAME, $tweetId);
$user->tweets->removeElement($this->_em->getReference(Tweet::CLASSNAME, $tweetId));
$this->_em->clear();
/* @var $tweet Tweet */
$tweet = $this->_em->find(Tweet::CLASSNAME, $tweet->id);
$this->assertInstanceOf(
Tweet::CLASSNAME,
$tweet,
'Even though the collection is extra lazy, the tweet should not have been deleted'
);
$this->assertInstanceOf(User::CLASSNAME, $tweet->author);
/* @var $user User */
$user = $this->_em->find(User::CLASSNAME, $userId);
$this->assertCount(1, $user->tweets, 'Element was not removed - need to update the owning side first');
}
/**
* @group DDC-3343
*/
public function testRemoveOrphanedManagedElementFromOneToManyExtraLazyCollection()
{
list($userId, $userListId) = $this->loadUserListFixture();
/* @var $user User */
$user = $this->_em->find(User::CLASSNAME, $userId);
$user->userLists->removeElement($this->_em->find(UserList::CLASSNAME, $userListId));
$this->_em->clear();
/* @var $user User */
$user = $this->_em->find(User::CLASSNAME, $userId);
$this->assertCount(0, $user->userLists, 'Element was removed from association due to orphan removal');
$this->assertNull(
$this->_em->find(UserList::CLASSNAME, $userListId),
'Element was deleted due to orphan removal'
);
}
/**
* @group DDC-3343
*/
public function testRemoveOrphanedUnManagedElementFromOneToManyExtraLazyCollection()
{
list($userId, $userListId) = $this->loadUserListFixture();
/* @var $user User */
$user = $this->_em->find(User::CLASSNAME, $userId);
$user->userLists->removeElement(new UserList());
$this->_em->clear();
/* @var $userList UserList */
$userList = $this->_em->find(UserList::CLASSNAME, $userListId);
$this->assertInstanceOf(
UserList::CLASSNAME,
$userList,
'Even though the collection is extra lazy + orphan removal, the user list should not have been deleted'
);
$this->assertInstanceOf(
User::CLASSNAME,
$userList->owner,
'User list to owner link has not been removed'
);
}
/**
* @group DDC-3343
*/
public function testRemoveOrphanedManagedLazyProxyFromExtraLazyOneToMany()
{
list($userId, $userListId) = $this->loadUserListFixture();
/* @var $user User */
$user = $this->_em->find(User::CLASSNAME, $userId);
$user->userLists->removeElement($this->_em->getReference(UserList::CLASSNAME, $userListId));
$this->_em->clear();
/* @var $user User */
$user = $this->_em->find(User::CLASSNAME, $userId);
$this->assertCount(0, $user->userLists, 'Element was removed from association due to orphan removal');
$this->assertNull(
$this->_em->find(UserList::CLASSNAME, $userListId),
'Element was deleted due to orphan removal'
);
}
/**
* @return int[] ordered tuple: user id and tweet id
*/
private function loadTweetFixture()
{
$user = new User();
$tweet = new Tweet();
$user->name = 'ocramius';
$tweet->content = 'The cat is on the table';
$user->addTweet($tweet);
$this->_em->persist($user);
$this->_em->persist($tweet);
$this->_em->flush();
$this->_em->clear();
return array($user->id, $tweet->id);
}
/**
* @return int[] ordered tuple: user id and user list id
*/
private function loadUserListFixture()
{
$user = new User();
$userList = new UserList();
$user->name = 'ocramius';
$userList->listName = 'PHP Developers to follow closely';
$user->addUserList($userList);
$this->_em->persist($user);
$this->_em->persist($userList);
$this->_em->flush();
$this->_em->clear();
return array($user->id, $userList->id);
}
}

View File

@@ -152,6 +152,19 @@ class OptimisticTest extends \Doctrine\Tests\OrmFunctionalTestCase
}
}
public function testLockWorksWithProxy()
{
$test = new OptimisticStandard();
$test->name = 'test';
$this->_em->persist($test);
$this->_em->flush();
$this->_em->clear();
$proxy = $this->_em->getReference('Doctrine\Tests\ORM\Functional\Locking\OptimisticStandard', $test->id);
$this->_em->lock($proxy, LockMode::OPTIMISTIC, 1);
}
public function testOptimisticTimestampSetsDefaultValue()
{
$test = new OptimisticTimestamp();

View File

@@ -11,6 +11,7 @@ use Doctrine\Tests\Models\CMS\CmsGroup;
use Doctrine\Tests\Models\CMS\CmsArticle;
use Doctrine\Tests\Models\CMS\CmsComment;
use Doctrine\ORM\Tools\Pagination\Paginator;
use ReflectionMethod;
/**
* @group DDC-1613
@@ -150,6 +151,36 @@ class PaginationTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertCount(1, $paginator->getIterator());
$this->assertEquals(1, $paginator->count());
}
public function testCountQueryStripsParametersInSelect()
{
$query = $this->_em->createQuery(
'SELECT u, (CASE WHEN u.id < :vipMaxId THEN 1 ELSE 0 END) AS hidden promotedFirst
FROM Doctrine\\Tests\\Models\\CMS\\CmsUser u
WHERE u.id < :id or 1=1'
);
$query->setParameter('vipMaxId', 10);
$query->setParameter('id', 100);
$query->setFirstResult(null)->setMaxResults(null);
$paginator = new Paginator($query);
$getCountQuery = new ReflectionMethod($paginator, 'getCountQuery');
$getCountQuery->setAccessible(true);
$this->assertCount(2, $getCountQuery->invoke($paginator)->getParameters());
$this->assertCount(3, $paginator);
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Query\SqlWalker');
$paginator = new Paginator($query);
// if select part of query is replaced with count(...) paginator should remove
// parameters from query object not used in new query.
$this->assertCount(1, $getCountQuery->invoke($paginator)->getParameters());
$this->assertCount(3, $paginator);
}
public function populate()
{

View File

@@ -9,8 +9,10 @@ require_once __DIR__ . '/../../../TestInit.php';
class PostgreSqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp() {
protected function setUp()
{
parent::setUp();
if ($this->_em->getConnection()->getDatabasePlatform()->getName() !== 'postgresql') {
$this->markTestSkipped('The ' . __CLASS__ .' requires the use of postgresql.');
}
@@ -19,6 +21,7 @@ class PostgreSqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
public function testPostgresMetadataSequenceIncrementedBy10()
{
$address = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress');
$this->assertEquals(1, $address->sequenceGeneratorDefinition['allocationSize']);
}
@@ -97,7 +100,9 @@ class PostgreSqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
$sql = $tool->getDropSchemaSQL($classes);
$this->assertEquals(14, count($sql));
$dropSequenceSQLs = 0;
foreach ($sql AS $stmt) {
if (strpos($stmt, "DROP SEQUENCE") === 0) {
$dropSequenceSQLs++;
@@ -115,10 +120,6 @@ class PostgreSqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC1657Screen'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC1657Avatar'),
);
try {
$this->_em->getConnection()->exec("CREATE SCHEMA stonewood");
} catch(\Exception $e) {
}
$tool = new SchemaTool($this->_em);
$tool->createSchema($classes);

View File

@@ -20,6 +20,7 @@ class DDC1360Test extends OrmFunctionalTestCase
));
$this->assertEquals(array(
'CREATE SCHEMA user',
'CREATE TABLE "user"."user" (id INT NOT NULL, PRIMARY KEY(id))',
'CREATE SEQUENCE "user"."user_id_seq" INCREMENT BY 1 MINVALUE 1 START 1',
), $sql);

View File

@@ -192,15 +192,38 @@ class ClassMetadataFactoryTest extends \Doctrine\Tests\OrmTestCase
$rootMetadata = $cmf->getMetadataFor('Doctrine\Tests\Models\JoinedInheritanceType\RootClass');
}
protected function _createEntityManager($metadataDriver)
public function testGetAllMetadataWorksWithBadConnection()
{
// DDC-3551
$conn = $this->getMockBuilder('Doctrine\DBAL\Connection')
->disableOriginalConstructor()
->getMock();
$mockDriver = new MetadataDriverMock();
$em = $this->_createEntityManager($mockDriver, $conn);
$conn->expects($this->any())
->method('getDatabasePlatform')
->will($this->throwException(new \Exception('Exception thrown in test when calling getDatabasePlatform')));
$cmf = new ClassMetadataFactory();
$cmf->setEntityManager($em);
// getting all the metadata should work, even if get DatabasePlatform blows up
$metadata = $cmf->getAllMetadata();
// this will just be an empty array - there was no error
$this->assertEquals(array(), $metadata);
}
protected function _createEntityManager($metadataDriver, $conn = null)
{
$driverMock = new DriverMock();
$config = new \Doctrine\ORM\Configuration();
$config->setProxyDir(__DIR__ . '/../../Proxies');
$config->setProxyNamespace('Doctrine\Tests\Proxies');
$eventManager = new EventManager();
$conn = new ConnectionMock(array(), $driverMock, $config, $eventManager);
$mockDriver = new MetadataDriverMock();
if (!$conn) {
$conn = new ConnectionMock(array(), $driverMock, $config, $eventManager);
}
$config->setMetadataDriverImpl($metadataDriver);
return EntityManagerMock::create($conn, $config, $eventManager);

View File

@@ -1101,6 +1101,31 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
$this->assertFalse($class->isIdentifier('foo'));
}
/**
* @group DDC-3120
*/
public function testCanInstantiateInternalPhpClassSubclass()
{
$classMetadata = new ClassMetadata(__NAMESPACE__ . '\\MyArrayObjectEntity');
$classMetadata->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
$this->assertInstanceOf(__NAMESPACE__ . '\\MyArrayObjectEntity', $classMetadata->newInstance());
}
/**
* @group DDC-3120
*/
public function testCanInstantiateInternalPhpClassSubclassFromUnserializedMetadata()
{
/* @var $classMetadata ClassMetadata */
$classMetadata = unserialize(serialize(new ClassMetadata(__NAMESPACE__ . '\\MyArrayObjectEntity')));
$classMetadata->wakeupReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
$this->assertInstanceOf(__NAMESPACE__ . '\\MyArrayObjectEntity', $classMetadata->newInstance());
}
}
/**
@@ -1137,3 +1162,7 @@ class MyPrefixNamingStrategy extends \Doctrine\ORM\Mapping\DefaultNamingStrategy
return strtolower($this->classToTableName($className)) . '_' . $propertyName;
}
}
class MyArrayObjectEntity extends \ArrayObject
{
}

View File

@@ -1990,7 +1990,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
"SELECT c0_.id || c0_.name || c0_.status AS sclr0 FROM cms_users c0_ WHERE c0_.id = ?"
);
/*$connMock->setDatabasePlatform(new \Doctrine\DBAL\Platforms\SQLServerPlatform());
$connMock->setDatabasePlatform(new \Doctrine\DBAL\Platforms\SQLServerPlatform());
$this->assertSqlGeneration(
"SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE CONCAT(u.name, u.status, 's') = ?1",
"SELECT c0_.id AS id0 FROM cms_users c0_ WHERE (c0_.name + c0_.status + 's') = ?"
@@ -1998,7 +1998,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
$this->assertSqlGeneration(
"SELECT CONCAT(u.id, u.name, u.status) FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = ?1",
"SELECT (c0_.id + c0_.name + c0_.status) AS sclr0 FROM cms_users c0_ WHERE c0_.id = ?"
);*/
);
$connMock->setDatabasePlatform($orgPlatform);
}
@@ -2058,7 +2058,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
{
$this->assertSqlGeneration(
'SELECT e.id FROM Doctrine\Tests\Models\Company\CompanyOrganization o JOIN o.events e WITH e.id = ?1',
'SELECT c0_.id AS id0 FROM company_organizations c1_ INNER JOIN company_events c0_ ON c1_.id = c0_.org_id AND (c0_.id = ?) LEFT JOIN company_auctions c2_ ON c0_.id = c2_.id LEFT JOIN company_raffles c3_ ON c0_.id = c3_.id',
'SELECT c0_.id AS id0 FROM company_organizations c1_ INNER JOIN (company_events c0_ LEFT JOIN company_auctions c2_ ON c0_.id = c2_.id LEFT JOIN company_raffles c3_ ON c0_.id = c3_.id) ON c1_.id = c0_.org_id AND (c0_.id = ?)',
array(Query::HINT_FORCE_PARTIAL_LOAD => false)
);
}

View File

@@ -2,6 +2,7 @@
namespace Doctrine\Tests\ORM\Tools;
use Doctrine\ORM\Mapping\ClassMetadataFactory;
use Doctrine\ORM\Tools\SchemaTool,
Doctrine\ORM\Tools\EntityGenerator,
Doctrine\ORM\Tools\Export\ClassMetadataExporter,
@@ -55,7 +56,7 @@ class EntityGeneratorTest extends \Doctrine\Tests\OrmTestCase
$metadata->table['uniqueConstraints']['name_uniq'] = array('columns' => array('name'));
$metadata->table['indexes']['status_idx'] = array('columns' => array('status'));
$metadata->mapField(array('fieldName' => 'name', 'type' => 'string'));
$metadata->mapField(array('fieldName' => 'status', 'type' => 'string', 'default' => 'published'));
$metadata->mapField(array('fieldName' => 'status', 'type' => 'string', 'options' => array('default' => 'published')));
$metadata->mapField(array('fieldName' => 'id', 'type' => 'integer', 'id' => true));
$metadata->mapOneToOne(array('fieldName' => 'author', 'targetEntity' => 'Doctrine\Tests\ORM\Tools\EntityGeneratorAuthor', 'mappedBy' => 'book'));
$joinColumns = array(
@@ -454,6 +455,97 @@ class EntityGeneratorTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals($value, $entity->{$getter}());
}
/**
* @group DDC-1590
*/
public function testMethodsAndPropertiesAreNotDuplicatedInChildClasses()
{
$cmf = new ClassMetadataFactory();
$em = $this->_getTestEntityManager();
$cmf->setEntityManager($em);
$ns = $this->_namespace;
$nsdir = $this->_tmpDir . '/' . $ns;
$content = str_replace(
'namespace Doctrine\Tests\Models\DDC1590',
'namespace ' . $ns,
file_get_contents(__DIR__ . '/../../Models/DDC1590/DDC1590User.php')
);
$fname = $nsdir . "/DDC1590User.php";
file_put_contents($fname, $content);
require $fname;
$metadata = $cmf->getMetadataFor($ns . '\DDC1590User');
$this->_generator->writeEntityClass($metadata, $this->_tmpDir);
// class DDC1590User extends DDC1590Entity { ... }
$source = file_get_contents($fname);
// class _DDC1590User extends DDC1590Entity { ... }
$source2 = str_replace('class DDC1590User', 'class _DDC1590User', $source);
$fname2 = $nsdir . "/_DDC1590User.php";
file_put_contents($fname2, $source2);
require $fname2;
// class __DDC1590User { ... }
$source3 = str_replace('class DDC1590User extends DDC1590Entity', 'class __DDC1590User', $source);
$fname3 = $nsdir . "/__DDC1590User.php";
file_put_contents($fname3, $source3);
require $fname3;
// class _DDC1590User extends DDC1590Entity { ... }
$rc2 = new \ReflectionClass($ns.'\_DDC1590User');
$this->assertTrue($rc2->hasProperty('name'));
$this->assertTrue($rc2->hasProperty('id'));
$this->assertTrue($rc2->hasProperty('created_at'));
$this->assertTrue($rc2->hasMethod('getName'));
$this->assertTrue($rc2->hasMethod('setName'));
$this->assertTrue($rc2->hasMethod('getId'));
$this->assertFalse($rc2->hasMethod('setId'));
$this->assertTrue($rc2->hasMethod('getCreatedAt'));
$this->assertTrue($rc2->hasMethod('setCreatedAt'));
// class __DDC1590User { ... }
$rc3 = new \ReflectionClass($ns.'\__DDC1590User');
$this->assertTrue($rc3->hasProperty('name'));
$this->assertFalse($rc3->hasProperty('id'));
$this->assertFalse($rc3->hasProperty('created_at'));
$this->assertTrue($rc3->hasMethod('getName'));
$this->assertTrue($rc3->hasMethod('setName'));
$this->assertFalse($rc3->hasMethod('getId'));
$this->assertFalse($rc3->hasMethod('setId'));
$this->assertFalse($rc3->hasMethod('getCreatedAt'));
$this->assertFalse($rc3->hasMethod('setCreatedAt'));
}
public function testRegenerateEntityClass()
{
$metadata = $this->generateBookEntityFixture();
$this->loadEntityClass($metadata);
$className = basename(str_replace('\\', '/', $metadata->name));
$path = $this->_tmpDir . '/' . $this->_namespace . '/' . $className . '.php';
$classTest = file_get_contents($path);
$this->_generator->setRegenerateEntityIfExists(true);
$this->_generator->setBackupExisting(false);
$this->_generator->writeEntityClass($metadata, $this->_tmpDir);
$classNew = file_get_contents($path);
$this->assertSame($classTest,$classNew);
}
/**
* @return array
*/
@@ -552,9 +644,32 @@ class
',
array('Foo\Bar\Baz'),
),
array(
'
<?php namespace Foo\Bar; class Baz {
public static function someMethod(){
return self::class;
}
}
',
array('Foo\Bar\Baz'),
),
);
}
/**
* @param ClassMetadataInfo $metadata
*/
private function loadEntityClass(ClassMetadataInfo $metadata)
{
$className = basename(str_replace('\\', '/', $metadata->name));
$path = $this->_tmpDir . '/' . $this->_namespace . '/' . $className . '.php';
$this->assertFileExists($path);
require_once $path;
}
/**
* @param string $type
* @param \ReflectionProperty $property

View File

@@ -2,6 +2,9 @@
namespace Doctrine\Tests\ORM\Tools\Pagination;
use Doctrine\DBAL\Platforms\MySqlPlatform;
use Doctrine\DBAL\Platforms\OraclePlatform;
use Doctrine\DBAL\Platforms\PostgreSqlPlatform;
use Doctrine\ORM\Query;
class LimitSubqueryOutputWalkerTest extends PaginationTestCase
@@ -22,7 +25,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase
public function testLimitSubqueryWithSortPg()
{
$odp = $this->entityManager->getConnection()->getDatabasePlatform();
$this->entityManager->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\PostgreSqlPlatform);
$this->entityManager->getConnection()->setDatabasePlatform(new PostgreSqlPlatform);
$query = $this->entityManager->createQuery(
'SELECT p, c, a FROM Doctrine\Tests\ORM\Tools\Pagination\MyBlogPost p JOIN p.category c JOIN p.author a ORDER BY p.title');
@@ -39,7 +42,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase
public function testLimitSubqueryWithScalarSortPg()
{
$odp = $this->entityManager->getConnection()->getDatabasePlatform();
$this->entityManager->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\PostgreSqlPlatform);
$this->entityManager->getConnection()->setDatabasePlatform(new PostgreSqlPlatform);
$query = $this->entityManager->createQuery(
'SELECT u, g, COUNT(g.id) AS g_quantity FROM Doctrine\Tests\ORM\Tools\Pagination\User u JOIN u.groups g ORDER BY g_quantity'
@@ -58,7 +61,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase
public function testLimitSubqueryWithMixedSortPg()
{
$odp = $this->entityManager->getConnection()->getDatabasePlatform();
$this->entityManager->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\PostgreSqlPlatform);
$this->entityManager->getConnection()->setDatabasePlatform(new PostgreSqlPlatform);
$query = $this->entityManager->createQuery(
'SELECT u, g, COUNT(g.id) AS g_quantity FROM Doctrine\Tests\ORM\Tools\Pagination\User u JOIN u.groups g ORDER BY g_quantity, u.id DESC'
@@ -77,7 +80,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase
public function testLimitSubqueryWithHiddenScalarSortPg()
{
$odp = $this->entityManager->getConnection()->getDatabasePlatform();
$this->entityManager->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\PostgreSqlPlatform);
$this->entityManager->getConnection()->setDatabasePlatform(new PostgreSqlPlatform);
$query = $this->entityManager->createQuery(
'SELECT u, g, COUNT(g.id) AS hidden g_quantity FROM Doctrine\Tests\ORM\Tools\Pagination\User u JOIN u.groups g ORDER BY g_quantity, u.id DESC'
@@ -96,7 +99,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase
public function testLimitSubqueryPg()
{
$odp = $this->entityManager->getConnection()->getDatabasePlatform();
$this->entityManager->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\PostgreSqlPlatform);
$this->entityManager->getConnection()->setDatabasePlatform(new PostgreSqlPlatform);
$this->testLimitSubquery();
@@ -106,7 +109,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase
public function testLimitSubqueryWithSortOracle()
{
$odp = $this->entityManager->getConnection()->getDatabasePlatform();
$this->entityManager->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\OraclePlatform);
$this->entityManager->getConnection()->setDatabasePlatform(new OraclePlatform);
$query = $this->entityManager->createQuery(
'SELECT p, c, a FROM Doctrine\Tests\ORM\Tools\Pagination\MyBlogPost p JOIN p.category c JOIN p.author a ORDER BY p.title');
@@ -124,7 +127,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase
public function testLimitSubqueryWithScalarSortOracle()
{
$odp = $this->entityManager->getConnection()->getDatabasePlatform();
$this->entityManager->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\OraclePlatform);
$this->entityManager->getConnection()->setDatabasePlatform(new OraclePlatform);
$query = $this->entityManager->createQuery(
'SELECT u, g, COUNT(g.id) AS g_quantity FROM Doctrine\Tests\ORM\Tools\Pagination\User u JOIN u.groups g ORDER BY g_quantity'
@@ -144,7 +147,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase
public function testLimitSubqueryWithMixedSortOracle()
{
$odp = $this->entityManager->getConnection()->getDatabasePlatform();
$this->entityManager->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\OraclePlatform);
$this->entityManager->getConnection()->setDatabasePlatform(new OraclePlatform);
$query = $this->entityManager->createQuery(
'SELECT u, g, COUNT(g.id) AS g_quantity FROM Doctrine\Tests\ORM\Tools\Pagination\User u JOIN u.groups g ORDER BY g_quantity, u.id DESC'
@@ -164,7 +167,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase
public function testLimitSubqueryOracle()
{
$odp = $this->entityManager->getConnection()->getDatabasePlatform();
$this->entityManager->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\OraclePlatform);
$this->entityManager->getConnection()->setDatabasePlatform(new OraclePlatform);
$query = $this->entityManager->createQuery(
'SELECT p, c, a FROM Doctrine\Tests\ORM\Tools\Pagination\MyBlogPost p JOIN p.category c JOIN p.author a');
@@ -179,7 +182,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase
$this->entityManager->getConnection()->setDatabasePlatform($odp);
}
public function testCountQuery_MixedResultsWithName()
public function testCountQueryMixedResultsWithName()
{
$query = $this->entityManager->createQuery(
'SELECT a, sum(a.name) as foo FROM Doctrine\Tests\ORM\Tools\Pagination\Author a');
@@ -190,5 +193,40 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase
"SELECT DISTINCT id0 FROM (SELECT a0_.id AS id0, a0_.name AS name1, sum(a0_.name) AS sclr2 FROM Author a0_) dctrn_result", $limitQuery->getSql()
);
}
/**
* @group DDC-3336
*/
public function testCountQueryWithArithmeticOrderByCondition()
{
$query = $this->entityManager->createQuery(
'SELECT a FROM Doctrine\Tests\ORM\Tools\Pagination\Author a ORDER BY (1 - 1000) * 1 DESC'
);
$this->entityManager->getConnection()->setDatabasePlatform(new MySqlPlatform());
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Tools\Pagination\LimitSubqueryOutputWalker');
$this->assertSame(
'SELECT DISTINCT id0 FROM (SELECT a0_.id AS id0, a0_.name AS name1 FROM Author a0_ ORDER BY (1 - 1000) * 1 DESC) dctrn_result',
$query->getSQL()
);
}
/**
* @group DDC-3434
*/
public function testLimitSubqueryWithHiddenSelectionInOrderBy()
{
$query = $this->entityManager->createQuery(
'SELECT a, a.name AS HIDDEN ord FROM Doctrine\Tests\ORM\Tools\Pagination\Author a ORDER BY ord DESC'
);
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Tools\Pagination\LimitSubqueryOutputWalker');
$this->assertEquals(
'SELECT DISTINCT id0, name2 FROM (SELECT a0_.id AS id0, a0_.name AS name1, a0_.name AS name2 FROM Author a0_ ORDER BY name2 DESC) dctrn_result ORDER BY name2 DESC',
$query->getSql()
);
}
}

View File

@@ -6,6 +6,9 @@ use Doctrine\Tests\OrmTestCase;
abstract class PaginationTestCase extends OrmTestCase
{
/**
* @var \Doctrine\ORM\EntityManagerInterface
*/
public $entityManager;
public function setUp()

View File

@@ -101,6 +101,23 @@ class SchemaToolTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals(count($classes), $listener->tableCalls);
$this->assertTrue($listener->schemaCalled);
}
public function testNullDefaultNotAddedToCustomSchemaOptions()
{
$em = $this->_getTestEntityManager();
$schemaTool = new SchemaTool($em);
$classes = array(
$em->getClassMetadata('Doctrine\Tests\Models\NullDefault\NullDefaultColumn'),
);
$customSchemaOptions = $schemaTool->getSchemaFromMetadata($classes)
->getTable('NullDefaultColumn')
->getColumn('nullDefault')
->getCustomSchemaOptions();
$this->assertSame(array(), $customSchemaOptions);
}
}
/**

View File

@@ -229,6 +229,25 @@ class UnitOfWorkTest extends \Doctrine\Tests\OrmTestCase
$this->setExpectedException('InvalidArgumentException');
$this->_unitOfWork->lock(null, null, null);
}
/**
* @group DDC-3619
* @group 1338
*/
public function testRemovedAndRePersistedEntitiesAreInTheIdentityMapAndAreNotGarbageCollected()
{
$entity = new ForumUser();
$entity->id = 123;
$this->_unitOfWork->registerManaged($entity, array('id' => 123), array());
$this->assertTrue($this->_unitOfWork->isInIdentityMap($entity));
$this->_unitOfWork->remove($entity);
$this->assertFalse($this->_unitOfWork->isInIdentityMap($entity));
$this->_unitOfWork->persist($entity);
$this->assertTrue($this->_unitOfWork->isInIdentityMap($entity));
}
}
/**

View File

@@ -139,6 +139,10 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
'Doctrine\Tests\Models\StockExchange\Stock',
'Doctrine\Tests\Models\StockExchange\Market',
),
'tweet' => array(
'Doctrine\Tests\Models\Tweet\Tweet',
'Doctrine\Tests\Models\Tweet\User',
),
'legacy' => array(
'Doctrine\Tests\Models\Legacy\LegacyUser',
'Doctrine\Tests\Models\Legacy\LegacyUserReference',
@@ -162,6 +166,11 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
'Doctrine\Tests\Models\Taxi\Car',
'Doctrine\Tests\Models\Taxi\Driver',
),
'tweet' => array(
'Doctrine\Tests\Models\Tweet\User',
'Doctrine\Tests\Models\Tweet\Tweet',
'Doctrine\Tests\Models\Tweet\UserList',
),
);
/**
@@ -269,6 +278,11 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
$conn->executeUpdate('DELETE FROM exchange_stocks');
$conn->executeUpdate('DELETE FROM exchange_markets');
}
if (isset($this->_usedModelSets['tweet'])) {
$conn->executeUpdate('DELETE FROM tweet_tweet');
$conn->executeUpdate('DELETE FROM tweet_user_list');
$conn->executeUpdate('DELETE FROM tweet_user');
}
if (isset($this->_usedModelSets['legacy'])) {
$conn->executeUpdate('DELETE FROM legacy_users_cars');
$conn->executeUpdate('DELETE FROM legacy_users_reference');
@@ -297,6 +311,12 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
$conn->executeUpdate('DELETE FROM taxi_driver');
}
if (isset($this->_usedModelSets['tweet'])) {
$conn->executeUpdate('DELETE FROM tweet_tweet');
$conn->executeUpdate('DELETE FROM tweet_user_list');
$conn->executeUpdate('DELETE FROM tweet_user');
}
$this->_em->clear();
}

View File

@@ -16,10 +16,6 @@
<var name="tmpdb_port" value="3306"/>
</php>
<logging>
<log type="coverage-clover" target="../../build/logs/clover.xml"/>
</logging>
<testsuites>
<testsuite name="Doctrine ORM Test Suite">
<directory>./../Doctrine/Tests/ORM</directory>

View File

@@ -19,10 +19,6 @@
<var name="tmpdb_port" value="5432"/>
</php>
<logging>
<log type="coverage-clover" target="../../build/logs/clover.xml"/>
</logging>
<testsuites>
<testsuite name="Doctrine ORM Test Suite">
<directory>./../Doctrine/Tests/ORM</directory>

View File

@@ -1,10 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<phpunit>
<logging>
<log type="coverage-clover" target="../../build/logs/clover.xml"/>
</logging>
<testsuites>
<testsuite name="Doctrine ORM Test Suite">
<directory>./../Doctrine/Tests/ORM</directory>