Compare commits

...

84 Commits

Author SHA1 Message Date
Alexander M. Turek d2de4ec03c Revert "Introduce FilterCollection#restore method (#10537)"
This reverts commit 8e20e1598e.
2023-07-28 16:08:17 +02:00
Vincent Langlet 8e20e1598e Introduce FilterCollection#restore method (#10537)
* Introduce FilterCollection#restore method

* Add suspend method instead

* Add more tests
2023-07-28 16:05:51 +02:00
Grégoire Paris 24df74d61d Merge pull request #10856 from VincentLanglet/fixDeprecation
Fix/Self deprecation with getQueryCacheImpl
2023-07-26 23:41:39 +02:00
Vincent Langlet 442f073d25 Fix static analysis 2023-07-26 17:42:20 +02:00
Vincent Langlet a5161e9485 Other solution 2023-07-26 16:00:37 +02:00
Vincent Langlet ddc7d953b9 Avoid self deprecation 2023-07-26 12:37:42 +02:00
Kévin Dunglas db51ed4f4c fix: use platform options instead of deprecated custom options (#10855) 2023-07-25 16:23:46 +02:00
Grégoire Paris f7e4b61459 Merge pull request #10847 from greg0ire/remove-toc 2023-07-18 09:50:04 +02:00
Grégoire Paris 6b0afdbd58 Avoid triple colons
It confuses the guides, and is ugly.
2023-07-18 08:57:09 +02:00
Grégoire Paris d3cf17b26d Remove toc
We already have the sidebar for this.
2023-07-18 08:56:24 +02:00
Alexander M. Turek 5213228a64 PHPStan 1.10.25, Psalm 5.13.1 (#10842) 2023-07-16 23:38:29 +02:00
Grégoire Paris 7848417488 Merge pull request #10838 from greg0ire/remove-dummy-title 2023-07-12 11:07:46 +02:00
Grégoire Paris 56e5856ad7 Remove dummy title
This was never meant to be under version control. Did not spot it in the
diff.

Closes #10836
2023-07-12 11:06:06 +02:00
Grégoire Paris 385bdd33f1 Merge pull request #10798 from greg0ire/less-partial-load
Resort on Query::HINT_FORCE_PARTIAL_LOAD less
2023-07-11 23:46:17 +02:00
Grégoire Paris 1413b496d7 Merge pull request #10824 from greg0ire/fix-build 2023-07-11 12:10:23 +02:00
Grégoire Paris ec7a8a7a0f Merge pull request #10828 from greg0ire/matching-xml
Match namespace in XML file with namespace in XSD file
2023-07-09 23:02:43 +02:00
Grégoire Paris e94fa8588d Match namespace in XML file with namespace in XSD file
In 7fa3e6ec7c, a global search and replace
was used for http and https.
This broke the documentation examples in that as soon as you turn on XSD
validation, it will fail because the namespace in the XML file does not
match the ones defined in the XSD file, which do not exhibit the https.

Note that this is not a security concern, because these URIs are
not meant to be actually resolved, but to serve as a unique identifier
for the namespace in which we define our elements.
2023-07-09 21:18:57 +02:00
Grégoire Paris 450cae2caa Add dummy title to the sidebar before checking docs
The way we have our docs, the sidebar is a separate document and as
such, needs a title. Let us prepend a dummy title until the guides-cli
provides a way to ignore that particular error.
2023-07-07 13:59:27 +02:00
Grégoire Paris 4978e0e336 Merge pull request #10819 from nicolas-grekas/fix-proxy-clone 2023-07-06 16:23:53 +02:00
Nicolas Grekas eee87c376d Fix cloning entities when using lazy-ghost proxies 2023-07-06 15:08:59 +02:00
Grégoire Paris 0b9060c728 Merge pull request #10806 from rmikalkenas/fix-enum-recomputation 2023-07-06 10:23:59 +02:00
Grégoire Paris 514f6b8c28 Merge pull request #10813 from Greg0/fix-primary-id-mapping-xml-driver 2023-07-06 09:12:53 +02:00
Rokas Mikalkėnas c1018fe299 Fixes recomputation of single entity change set when entity contains enum attributes.
Due to the fact that originalEntityData contains enum objects and
ReflectionEnumProperty::getValue() returns value of enum,
comparison of values are always falsy, resulting to update
columns value even though it has not changes.
2023-07-05 23:57:34 +03:00
Grzegorz Kuźnik 075824f5b5 Fix code style issues 2023-07-05 21:10:48 +02:00
Grégoire Paris d6f4834476 Merge pull request #10815 from greg0ire/test-docs 2023-07-05 10:01:37 +02:00
Grégoire Paris 9dadffe270 Use absolute references
According to the Sphinx docs, when in reference/architecture.rst, a
reference to reference/inheritance-mapping would resolve to
reference/reference/inheritance-mapping.rst, because it is relative to
the current document
2023-07-04 17:44:44 +02:00
Grégoire Paris b6e7e6d723 Avoid colon followed by double colon
It seems to confuse the guides-cli, if it is even valid.
2023-07-04 17:31:05 +02:00
Grégoire Paris 710937d6f8 Use correct syntax for references
doc was used when it is clearly a ref, plus there was a leading
underscore preventing the resolution.
2023-07-04 17:26:04 +02:00
Grégoire Paris 5d2d6642c8 Fix invalid reference syntax
Without this change, a hash is displayed for some reason.
2023-07-04 17:14:03 +02:00
Grégoire Paris 4d56711d8c Use rst syntax
Using underscore for emphasis is not an RST thing, in rst the difference
between emphasis and strong emphasis is in the number of asterisks.

Right now these underscores are just ignored and displayed on the
website.

See https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#emphasis
2023-07-04 17:11:46 +02:00
Grégoire Paris a157bc3fb3 Use internal link 2023-07-04 17:05:47 +02:00
Grégoire Paris 1aeab391c7 Escape pipes
Pipes can be used to define substitutions, it is part of the rst
standard. This explains why some of the links in this document are not
displayed on the website.

See https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#substitution-definitions
2023-07-04 16:48:14 +02:00
Grégoire Paris a4ecd02349 Introduce new workflow to test docs
This allows to check compatibility with phpDocumentor/guides, but also
should allow to spot embarassing mistakes in our existing docs.
2023-07-04 16:45:18 +02:00
Grégoire Paris 8c59828f6c Remove lone dash (#10812) 2023-07-03 21:46:12 +02:00
Grzegorz K 0877ecbe56 Treat id field proprites same as regular field 2023-07-03 15:15:08 +02:00
Grégoire Paris 4887359827 Merge pull request #10807 from mpdude/move-tests
Move three "Ticket/"-style tests to the right namespace
2023-06-28 20:54:43 +02:00
Matthias Pigulla 5afe9b80a8 Move three "Ticket/"-style tests to the right namespace 2023-06-28 16:39:47 +02:00
Grégoire Paris 584c4aeed1 Merge pull request #10804 from greg0ire/parenthesized 2023-06-28 14:11:41 +02:00
Grégoire Paris c9c5157fda Follow recommendation about multiline type
Apparently, there is consensus about multiline types between:

- PHPStan
- Psalm
- Slevomat Coding Standard

See https://github.com/slevomat/coding-standard/issues/1586#issuecomment-1610195706

Using parenthesis is less ambiguous, it makes it clear to the parser
where the type begins and where it ends.

The change has a positive impact on the Psalm baseline, showing
that psalm-return annotation was not really understood previously.
2023-06-28 07:46:35 +02:00
Grégoire Paris dba90c1a91 Merge pull request #10786 from vuongxuongminh/fix-attach-entity-listener-when-reset-class-metadata-factory
Fix attach entity listener when reset class metadata factory
2023-06-27 23:53:01 +02:00
Nicolas Grekas 55d477dc50 Fix unserialize() errors when running tests on PHP 8.3 (#10803) 2023-06-27 17:47:09 +02:00
Grégoire Paris 4da8d3be96 Resort on Query::HINT_FORCE_PARTIAL_LOAD less
A lot of our tests mention it, but I do not think it is important to the
test. Maybe it was a way to have more efficient tests? Most times,
removing the hint does not affect the test outcome.
2023-06-27 08:37:05 +02:00
Matthias Pigulla 4aadba65ce Explain EntityManager::getReference() peculiarities (#10800)
* Explain `EntityManager::getReference()` peculiarities

As one takeaway from https://github.com/doctrine/orm/issues/3037#issuecomment-1605657003 and #843, we should look into better explaining the `EntityManager::getReference()` method, it’s semantics, caveats and potential responsibilities placed on the user.

This PR tries to do that, so it fixes #10797.

* Update docs/en/reference/advanced-configuration.rst

Co-authored-by: Grégoire Paris <postmaster@greg0ire.fr>

---------

Co-authored-by: Grégoire Paris <postmaster@greg0ire.fr>
2023-06-27 00:16:55 +02:00
Grégoire Paris 814d8d4d39 Merge pull request #10802 from greg0ire/psalm-5-13
Upgrade to Psalm 5.13
2023-06-27 00:05:00 +02:00
Grégoire Paris dc411954ad Upgrade to Psalm 5.13
This is a nice release as far as the ORM is concerned:
- a small baseline reduction;
- lots of useless calls to sprintf spotted.
2023-06-26 19:12:02 +02:00
Minh Vuong da29eb675c test: assert postLoad has data first 2023-06-26 09:29:00 +07:00
Grégoire Paris b17e52ba6b Merge pull request #10791 from mpdude/understand-3037
Avoid creating unmanaged proxy instances for referred-to entities during `merge()`
2023-06-25 23:52:53 +02:00
Grégoire Paris 4e138903d0 Merge pull request #10789 from macroparts/distinct-updates-state-correctly
distinct() updates QueryBuilder state correctly
2023-06-25 18:11:37 +02:00
Daniel Jurkovic efb50b9bdd distinct() updates QueryBuilder state correctly
Previously calling distinct() when the QueryBuilder was in clean state would cause subsequent getDQL() calls to ignore the distinct queryPart

Fixes #10784
2023-06-25 17:53:24 +02:00
Matthias Pigulla 1989531d4f Update tests/Doctrine/Tests/ORM/Functional/Ticket/GH7407Test.php
Co-authored-by: Grégoire Paris <postmaster@greg0ire.fr>
2023-06-23 22:47:34 +02:00
Matthias Pigulla d738ecfcfe Avoid creating unmanaged proxy instances for referred-to entities during merge()
This PR tries to improve the situation/problem explained in #3037:

Under certain conditions – there may be multiple and not all are known/well-understood – we may get inconsistencies between the `\Doctrine\ORM\UnitOfWork::$entityIdentifiers` and `\Doctrine\ORM\UnitOfWork::$identityMap` arrays.

Since the `::$identityMap` is a plain array holding object references, objects contained in it cannot be garbage-collected.
`::$entityIdentifiers`, however, is indexed by `spl_object_id` values. When those objects are destructed and/or garbage-collected, the OID may be reused and reassigned to other objects later on.

When the OID re-assignment happens to be for another entity, the UoW may assume incorrect entity states and, for example, miss INSERT or UPDATE operations.

One cause for such inconsistencies is _replacing_ identity map entries with other object instances: This makes it possible that the old object becomes GC'd, while its OID is not cleaned up. Since that is not a use case we need to support (IMHO), #10785 is about adding a safeguard against it.

In this test shown here, the `merge()` operation is currently too eager in creating a proxy object for another referred-to entity. This proxy represents an entity already present in the identity map at that time, potentially leading to this problem later on.
2023-06-23 22:19:06 +02:00
Grégoire Paris f76bab2b73 Merge pull request #10790 from greg0ire/slevomat-cs-upgrade
Work around slevomat/coding-standard issues
2023-06-23 22:13:30 +02:00
Grégoire Paris 0e06d6b67d Apply latest coding standard rules 2023-06-23 18:11:22 +02:00
Grégoire Paris 5114dcee0b Work around slevomat/coding-standard issues
I tweaked the code so that it would not fall victim to
https://github.com/slevomat/coding-standard/issues/1585 or
https://github.com/slevomat/coding-standard/issues/1586, thus fixing the
phpcs job without losing information or breaking other jobs.
2023-06-23 18:11:07 +02:00
Alexander Dmitryuk 4c3bd20801 Fix missing setFilterSchemaAssetsExpression in phpdoc (#10776) 2023-06-22 14:36:06 +02:00
Grégoire Paris f2abf6143b Merge pull request #10763 from mpdude/defer-collection-entity-removals-to-post-commit 2023-06-22 14:35:20 +02:00
Minh Vuong 338deacb58 fix: attach entity listener when reset metadata factory 2023-06-22 17:02:24 +07:00
Grégoire Paris 829d5fbb9f Merge pull request #10780 from greg0ire/avoid-partial 2023-06-22 10:04:27 +02:00
Matthias Pigulla d220494edc Improve documentation on exact behaviour of many-to-many deletion operations 2023-06-21 19:14:55 +02:00
Matthias Pigulla c235901544 Move a check up (continue early) 2023-06-21 19:14:55 +02:00
Matthias Pigulla ba089e551a Avoid unnecessary changes 2023-06-21 19:14:55 +02:00
Matthias Pigulla ee0b3f214d Write tests more concisely 2023-06-21 19:14:55 +02:00
Matthias Pigulla 930fa831b2 Test expected query counts in ManyToManyBasicAssociationTest
When collection updates/join table cleanups do not happen through specialized Entity-/CollectionPersister methods but instead as "plain" updates, we may issue a lot more queries than expected.
2023-06-21 19:14:55 +02:00
Matthias Pigulla 98b404875f Defer removing removed entities from to-many collections until after transaction commit 2023-06-21 19:14:55 +02:00
Grégoire Paris fcc5c106b4 Rely on partial objects less when in tests
Partial objects are deprecated. They were handy to make the generated
SQL more legible, but we should refrain from relying on them.
2023-06-18 18:20:29 +02:00
Grégoire Paris 5132f0deb0 Stop using $message argument
It brings nothing over what PHPUnit now natively does.
2023-06-18 18:16:29 +02:00
Grégoire Paris fe8e313731 Merge pull request #10747 from wtfzdotnet/feature/fix-one-to-many-custom-id-orphan-removal 2023-06-16 10:07:29 +02:00
Grégoire Paris 1adb5c0c70 Merge pull request #10774 from greg0ire/document-dto-in-rsm 2023-06-12 13:52:10 +02:00
Grégoire Paris e5174af669 Document how to produce DTOs with a result set mapping 2023-06-11 18:02:18 +02:00
Vaidas c3106f9fe7 Restore document proxy state to uninitialized on load exception (#10645) 2023-06-09 08:54:22 +02:00
Alexander M. Turek cbf45dd97e PHPStan 1.10.18, Psalm 5.12.0 (#10771) 2023-06-08 16:57:07 +02:00
Michael Roterman 3c0d140e52 OneToManyPersister does not take custom identifier types into account for orphan removal.
In my case a custom doctrine type of Uuid object is converted to string by simply casting it, resulting in a hex DELETE FROM x WHERE id = ? query,
whilst it should've been converted along the way to it's binary representation. This leads to no deletions being made at all as you would expect making use of doctrine custom type's as an identifier.

This commit fixes usage of ramsey/uuid or symfony/uid as custom id types when making use of orphan removal.
2023-06-06 19:51:41 +02:00
Michael Roterman 33675ff4a9 fix: Update baseline and assertions for OneToManyPersister 2023-06-06 18:18:26 +02:00
Nicolas Grekas 3827dd769e Don't call deprecated getSQLResultCasing and usesSequenceEmulatedIdentityColumns when we know the platform (#10759) 2023-06-06 11:27:31 +02:00
Nicolas Grekas 6c9b29f237 Don't call canEmulateSchemas in SchemaTool when possible (#10762) 2023-06-05 21:42:13 +02:00
Grégoire Paris 2afe2dc8af Merge pull request #10758 from Gwemox/partial-revert-enum-id-hash 2023-06-05 11:41:32 +02:00
Thibault Buathier cc3d872b95 revert: transform backed enum to value 2023-06-05 10:58:32 +02:00
Grégoire Paris 65dc154ce5 Merge pull request #10754 from greg0ire/fix-build
Fix build
2023-06-05 08:35:26 +02:00
Grégoire Paris caaa0d6192 Ignore error about get_class($metadata)
This is the result of the contradiction between the phpdoc
(ClassMetadata), and the condition, which guarantees $metadata is not a
ClassMetadata. Relaxing the phpdoc leads to other phpstan issues, about
properties that exist in ClassMetadata but not in
PersistentClassMetadata. The right way to fix this would be to switch
from a deprecation to an exception, but that is not the path we have
taken, and all this will disappear in 3.0.x anyway, so let's not bother.
2023-06-03 20:59:29 +02:00
Grégoire Paris 68d3a63957 Use class name directly
Static analysis points out $this->getName() may return null. But there
is worse: the message mentions a "command class", and getName() is not a
class.
2023-06-03 20:59:29 +02:00
Matthias Pigulla 76b8a215c2 Update docs that name in @Index/@UniqueConstraint is optional (#10748)
Fixes #4283.
2023-06-03 00:14:43 +02:00
Matthias Pigulla b163cea61c Update the FAQ entry on setting MySQL charset and collation for columns (#10746)
Fixes #2986.
2023-06-03 00:13:07 +02:00
Grégoire Paris 4dfbe13897 Merge pull request #10740 from greg0ire/remove-ignore-rule
Remove useless ignore rule
2023-06-02 00:14:27 +02:00
Grégoire Paris b64e1c9b1f Remove useless ignore rule
This is useless since 152f91fa3
2023-06-01 21:03:58 +02:00
76 changed files with 1408 additions and 632 deletions
+51
View File
@@ -0,0 +1,51 @@
name: "Documentation"
on:
pull_request:
branches:
- "*.x"
paths:
- .github/workflows/documentation.yml
- docs/**
push:
branches:
- "*.x"
paths:
- .github/workflows/documentation.yml
- docs/**
jobs:
validate-with-guides:
name: "Validate documentation with phpDocumentor/guides"
runs-on: "ubuntu-22.04"
steps:
- name: "Checkout code"
uses: "actions/checkout@v3"
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
with:
coverage: "none"
php-version: "8.2"
- name: "Remove existing composer file"
run: "rm composer.json"
- name: "Require phpdocumentor/guides-cli"
run: "composer require --dev phpdocumentor/guides-cli dev-main@dev --no-update"
- name: "Configure minimum stability"
run: "composer config minimum-stability dev"
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v2"
with:
dependency-versions: "highest"
- name: "Add dummy title to the sidebar"
run: |
printf '%s\n%s\n\n%s\n' "Dummy title" "===========" "$(cat docs/en/sidebar.rst)" > docs/en/sidebar.rst
- name: "Run guides-cli"
run: "vendor/bin/guides -vvv --no-progress docs/en /tmp/test 2>&1 | ( ! grep WARNING )"
+2 -2
View File
@@ -42,14 +42,14 @@
"doctrine/annotations": "^1.13 || ^2",
"doctrine/coding-standard": "^9.0.2 || ^12.0",
"phpbench/phpbench": "^0.16.10 || ^1.0",
"phpstan/phpstan": "~1.4.10 || 1.10.14",
"phpstan/phpstan": "~1.4.10 || 1.10.25",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.6",
"psr/log": "^1 || ^2 || ^3",
"squizlabs/php_codesniffer": "3.7.2",
"symfony/cache": "^4.4 || ^5.4 || ^6.0",
"symfony/var-exporter": "^4.4 || ^5.4 || ^6.2",
"symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0",
"vimeo/psalm": "4.30.0 || 5.11.0"
"vimeo/psalm": "4.30.0 || 5.13.1"
},
"conflict": {
"doctrine/annotations": "<1.13 || >= 3.0"
+21 -23
View File
@@ -18,8 +18,8 @@ Doctrine ORM don't panic. You can get help from different sources:
- Report a bug on `GitHub <https://github.com/doctrine/orm/issues>`_.
- On `StackOverflow <https://stackoverflow.com/questions/tagged/doctrine-orm>`_
If you need more structure over the different topics you can browse the :doc:`table
of contents <toc>`.
If you need more structure over the different topics you can browse the table
of contents.
Getting Started
---------------
@@ -34,32 +34,32 @@ Mapping Objects onto a Database
-------------------------------
* **Mapping**:
:doc:`Objects <reference/basic-mapping>` |
:doc:`Associations <reference/association-mapping>` |
:doc:`Objects <reference/basic-mapping>` \|
:doc:`Associations <reference/association-mapping>` \|
:doc:`Inheritance <reference/inheritance-mapping>`
* **Drivers**:
:doc:`Docblock Annotations <reference/annotations-reference>` |
:doc:`Attributes <reference/attributes-reference>` |
:doc:`XML <reference/xml-mapping>` |
:doc:`YAML <reference/yaml-mapping>` |
:doc:`Docblock Annotations <reference/annotations-reference>` \|
:doc:`Attributes <reference/attributes-reference>` \|
:doc:`XML <reference/xml-mapping>` \|
:doc:`YAML <reference/yaml-mapping>` \|
:doc:`PHP <reference/php-mapping>`
Working with Objects
--------------------
* **Basic Reference**:
:doc:`Entities <reference/working-with-objects>` |
:doc:`Associations <reference/working-with-associations>` |
:doc:`Entities <reference/working-with-objects>` \|
:doc:`Associations <reference/working-with-associations>` \|
:doc:`Events <reference/events>`
* **Query Reference**:
:doc:`DQL <reference/dql-doctrine-query-language>` |
:doc:`QueryBuilder <reference/query-builder>` |
:doc:`DQL <reference/dql-doctrine-query-language>` \|
:doc:`QueryBuilder <reference/query-builder>` \|
:doc:`Native SQL <reference/native-sql>`
* **Internals**:
:doc:`Internals explained <reference/unitofwork>` |
:doc:`Internals explained <reference/unitofwork>` \|
:doc:`Associations <reference/unitofwork-associations>`
Advanced Topics
@@ -102,20 +102,20 @@ Cookbook
--------
* **Patterns**:
:doc:`Aggregate Fields <cookbook/aggregate-fields>` |
:doc:`Decorator Pattern <cookbook/decorator-pattern>` |
:doc:`Aggregate Fields <cookbook/aggregate-fields>` \|
:doc:`Decorator Pattern <cookbook/decorator-pattern>` \|
:doc:`Strategy Pattern <cookbook/strategy-cookbook-introduction>`
* **DQL Extension Points**:
:doc:`DQL Custom Walkers <cookbook/dql-custom-walkers>` |
:doc:`DQL Custom Walkers <cookbook/dql-custom-walkers>` \|
:doc:`DQL User-Defined-Functions <cookbook/dql-user-defined-functions>`
* **Implementation**:
:doc:`Array Access <cookbook/implementing-arrayaccess-for-domain-objects>` |
:doc:`Notify ChangeTracking Example <cookbook/implementing-the-notify-changetracking-policy>` |
:doc:`Working with DateTime <cookbook/working-with-datetime>` |
:doc:`Validation <cookbook/validation-of-entities>` |
:doc:`Entities in the Session <cookbook/entities-in-session>` |
:doc:`Array Access <cookbook/implementing-arrayaccess-for-domain-objects>` \|
:doc:`Notify ChangeTracking Example <cookbook/implementing-the-notify-changetracking-policy>` \|
:doc:`Working with DateTime <cookbook/working-with-datetime>` \|
:doc:`Validation <cookbook/validation-of-entities>` \|
:doc:`Entities in the Session <cookbook/entities-in-session>` \|
:doc:`Keeping your Modules independent <cookbook/resolve-target-entity-listener>`
* **Hidden Gems**
@@ -124,5 +124,3 @@ Cookbook
* **Custom Datatypes**
:doc:`MySQL Enums <cookbook/mysql-enums>`
:doc:`Advanced Field Value Conversion <cookbook/advanced-field-value-conversion-using-custom-mapping-types>`
.. include:: toc.rst
+31 -11
View File
@@ -311,10 +311,12 @@ Reference Proxies
The method ``EntityManager#getReference($entityName, $identifier)``
lets you obtain a reference to an entity for which the identifier
is known, without loading that entity from the database. This is
useful, for example, as a performance enhancement, when you want to
establish an association to an entity for which you have the
identifier. You could simply do this:
is known, without necessarily loading that entity from the database.
This is useful, for example, as a performance enhancement, when you
want to establish an association to an entity for which you have the
identifier.
Consider the following example:
.. code-block:: php
@@ -324,15 +326,33 @@ identifier. You could simply do this:
$item = $em->getReference('MyProject\Model\Item', $itemId);
$cart->addItem($item);
Here, we added an Item to a Cart without loading the Item from the
database. If you access any state that isn't yet available in the
Item instance, the proxying mechanism would fully initialize the
object's state transparently from the database. Here
$item is actually an instance of the proxy class that was generated
for the Item class but your code does not need to care. In fact it
**should not care**. Proxy objects should be transparent to your
Whether the object being returned from ``EntityManager#getReference()``
is a proxy or a direct instance of the entity class may depend on different
factors, including whether the entity has already been loaded into memory
or entity inheritance being used. But your code does not need to care
and in fact it **should not care**. Proxy objects should be transparent to your
code.
When using the ``EntityManager#getReference()`` method, you need to be aware
of a few peculiarities.
At the best case, the ORM can avoid querying the database at all. But, that
also means that this method will not throw an exception when an invalid value
for the ``$identifier`` parameter is passed. ``$identifier`` values are
not checked and there is no guarantee that the requested entity instance even
exists the method will still return a proxy object.
Its only when the proxy has to be fully initialized or associations cannot
be written to the database that invalid ``$identifier`` values may lead to
exceptions.
The ``EntityManager#getReference()`` is mostly useful when you only
need a reference to some entity to make an association, like in the example
above. In that case, it can save you from loading data from the database
that you don't need. But remember as soon as you read any property values
besides those making up the ID, a database request will be made to initialize
all fields.
Association proxies
~~~~~~~~~~~~~~~~~~~
+2 -2
View File
@@ -545,12 +545,12 @@ has meaning in the SchemaTool schema generation context.
Required attributes:
- **name**: Name of the Index
- **fields**: Array of fields. Exactly one of **fields**, **columns** is required.
- **columns**: Array of columns. Exactly one of **fields**, **columns** is required.
Optional attributes:
- **name**: Name of the Index. If not provided, a generated name will be assigned.
- **options**: Array of platform specific options:
- ``where``: SQL WHERE condition to be used for partial indexes. It will
@@ -1316,12 +1316,12 @@ context.
Required attributes:
- **name**: Name of the Index
- **fields**: Array of fields. Exactly one of **fields**, **columns** is required.
- **columns**: Array of columns. Exactly one of **fields**, **columns** is required.
Optional attributes:
- **name**: Name of the Index. If not provided, a generated name will be assigned.
- **options**: Array of platform specific options:
- ``where``: SQL WHERE condition to be used for partial indexes. It will
+1 -1
View File
@@ -102,7 +102,7 @@ persistent entity state and mapping information for its subclasses,
but which is not itself an entity.
Mapped superclasses are explained in greater detail in the chapter
on :doc:`inheritance mapping <reference/inheritance-mapping>`.
on :doc:`inheritance mapping </reference/inheritance-mapping>`.
Transient Classes
~~~~~~~~~~~~~~~~~
+18
View File
@@ -881,6 +881,15 @@ Generated MySQL Schema:
replaced by one-to-many/many-to-one associations between the 3
participating classes.
.. note::
For many-to-many associations, the ORM takes care of managing rows
in the join table connecting both sides. Due to the way it deals
with entity removals, database-level constraints may not work the
way one might intuitively assume. Thus, be sure not to miss the section
on :ref:`join table management <remove_object_many_to_many_join_tables>`.
Many-To-Many, Bidirectional
---------------------------
@@ -1019,6 +1028,15 @@ one is bidirectional.
The MySQL schema is exactly the same as for the Many-To-Many
uni-directional case above.
.. note::
For many-to-many associations, the ORM takes care of managing rows
in the join table connecting both sides. Due to the way it deals
with entity removals, database-level constraints may not work the
way one might intuitively assume. Thus, be sure not to miss the section
on :ref:`join table management <remove_object_many_to_many_join_tables>`.
Owning and Inverse Side on a ManyToMany Association
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+2 -2
View File
@@ -540,13 +540,13 @@ has meaning in the ``SchemaTool`` schema generation context.
Required parameters:
- **name**: Name of the Index
- **fields**: Array of fields. Exactly one of **fields, columns** is required.
- **columns**: Array of columns. Exactly one of **fields, columns** is required.
Optional parameters:
- **name**: Name of the Index. If not provided, a generated name will be assigned.
- **options**: Array of platform specific options:
- ``where``: SQL WHERE condition to be used for partial indexes. It will
@@ -1104,12 +1104,12 @@ context.
Required parameters:
- **name**: Name of the Index
- **fields**: Array of fields (the names of the properties, used in the entity class).
- **columns**: Array of columns (the names of the columns, used in the schema).
Optional parameters:
- **name**: Name of the Index. If not provided, a generated name will be assigned.
- **options**: Array of platform specific options:
- ``where``: SQL WHERE condition to be used for partial indexes. It will
+1 -1
View File
@@ -460,7 +460,7 @@ Here is the list of possible generation strategies:
a new entity is passed to ``EntityManager#persist``. NONE is the
same as leaving off the ``#[GeneratedValue]`` entirely.
- ``CUSTOM``: With this option, you can use the ``#[CustomIdGenerator]`` attribute.
It will allow you to pass a :doc:`class of your own to generate the identifiers.<_annref_customidgenerator>`
It will allow you to pass a :ref:`class of your own to generate the identifiers.<annref_customidgenerator>`
Sequence Generator
^^^^^^^^^^^^^^^^^^
+1 -1
View File
@@ -104,7 +104,7 @@ Inside the ``ORMSetup`` methods several assumptions are made:
In order to have ``ORMSetup`` configure the cache automatically, the library ``symfony/cache``
has to be installed as a dependency.
If you want to configure Doctrine in more detail, take a look at the :doc:`Advanced Configuration <reference/advanced-configuration>` section.
If you want to configure Doctrine in more detail, take a look at the :doc:`Advanced Configuration </reference/advanced-configuration>` section.
.. note::
@@ -1336,8 +1336,8 @@ There are situations when a query you want to execute returns a
very large result-set that needs to be processed. All the
previously described hydration modes completely load a result-set
into memory which might not be feasible with large result sets. See
the `Batch Processing <batch-processing.html>`_ section on details how
to iterate large result sets.
the :doc:`Batch Processing </reference/batch-processing>` section on
details how to iterate large result sets.
Functions
~~~~~~~~~
+4 -4
View File
@@ -281,10 +281,10 @@ specific to a particular entity class's lifecycle.
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="User">
<!-- ... -->
<lifecycle-callbacks>
+4 -5
View File
@@ -13,11 +13,10 @@ Database Schema
How do I set the charset and collation for MySQL tables?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can't set these values with attributes, annotations or inside yml or
xml mapping files. To make a database work with the default charset and
collation you should configure MySQL to use it as default charset, or
create the database with charset and collation details. This way they
get inherited to all newly created database tables and columns.
In your mapping configuration, the column definition (for example, the
``#[Column]`` attribute) has an ``options`` parameter where you can specify
the ``charset`` and ``collation``. The default values are ``utf8`` and
``utf8_unicode_ci``, respectively.
Entity Classes
--------------
+1 -1
View File
@@ -91,7 +91,7 @@ Apply Best Practices
A lot of the points mentioned in the Best Practices chapter will
also positively affect the performance of Doctrine.
See :doc:`Best Practices <reference/best-practices>`
See :doc:`Best Practices </reference/best-practices>`
Change Tracking policies
------------------------
+4 -4
View File
@@ -35,7 +35,7 @@ have to be used.
superclass, since they require the "many" side to hold the foreign
key.
It is, however, possible to use the :doc:`ResolveTargetEntityListener <cookbook/resolve-target-entity-listener>`
It is, however, possible to use the :doc:`ResolveTargetEntityListener </cookbook/resolve-target-entity-listener>`
to replace references to a mapped superclass with an entity class at runtime.
As long as there is only one entity subclass inheriting from the mapped
superclass and all references to the mapped superclass are resolved to that
@@ -45,7 +45,7 @@ have to be used.
.. warning::
At least when using attributes or annotations to specify your mapping,
it _seems_ as if you could inherit from a base class that is neither
it *seems* as if you could inherit from a base class that is neither
an entity nor a mapped superclass, but has properties with mapping configuration
on them that would also be used in the inheriting class.
@@ -60,7 +60,7 @@ have to be used.
You may be tempted to use traits to mix mapped fields or relationships
into your entity classes to circumvent some of the limitations of
mapped superclasses. Before doing that, please read the section on traits
in the :doc:`Limitations and Known Issues <reference/limitations-and-known-issues>` chapter.
in the :doc:`Limitations and Known Issues </reference/limitations-and-known-issues>` chapter.
Example:
@@ -380,7 +380,7 @@ It is not supported to use overrides in entity inheritance scenarios.
.. note::
When using traits, make sure not to miss the warnings given in the
:doc:`Limitations and Known Issues<reference/limitations-and-known-issues>` chapter.
:doc:`Limitations and Known Issues</reference/limitations-and-known-issues>` chapter.
Association Override
+1 -1
View File
@@ -1,4 +1,4 @@
Installation
============
The installation chapter has moved to :doc:`Installation and Configuration <reference/configuration>`_.
The installation chapter has moved to :doc:`Installation and Configuration </reference/configuration>`.
@@ -145,7 +145,7 @@ more than two years after the initial Doctrine 2 release and the time where
core components were designed.
In fact, this documentation mentions traits only in the context of
:doc:`overriding field association mappings in subclasses <tutorials/override-field-association-mappings-in-subclasses>`.
:doc:`overriding field association mappings in subclasses </tutorials/override-field-association-mappings-in-subclasses>`.
Coverage of traits in test cases is practically nonexistent.
Thus, you should at least be aware that when using traits in your entity and
@@ -162,7 +162,7 @@ that, some precedence and conflict resolution rules apply.
When it comes to loading mapping configuration, the annotation and attribute drivers
rely on PHP reflection to inspect class properties including their docblocks.
As long as the results are consistent with what a solution _without_ traits would
As long as the results are consistent with what a solution *without* traits would
have produced, this is probably fine.
However, to mention known limitations, it is currently not possible to use "class"
+34
View File
@@ -250,6 +250,40 @@ The first parameter is the name of the column in the SQL result set
and the second parameter is the result alias under which the value
of the column will be placed in the transformed Doctrine result.
Special case: DTOs
...................
You can also use ``ResultSetMapping`` to map the results of a native SQL
query to a DTO (Data Transfer Object). This is done by adding scalar
results for each argument of the DTO's constructor, then filling the
``newObjectMappings`` property of the ``ResultSetMapping`` with
information about where to map each scalar result:
.. code-block:: php
<?php
$rsm = new ResultSetMapping();
$rsm->addScalarResult('name', 1, 'string');
$rsm->addScalarResult('email', 2, 'string');
$rsm->addScalarResult('city', 3, 'string');
$rsm->newObjectMappings['name'] = [
'className' => CmsUserDTO::class,
'objIndex' => 0, // a result can contain many DTOs, this is the index of the DTO to map to
'argIndex' => 0, // each scalar result can be mapped to a different argument of the DTO constructor
];
$rsm->newObjectMappings['email'] = [
'className' => CmsUserDTO::class,
'objIndex' => 0,
'argIndex' => 1,
];
$rsm->newObjectMappings['city'] = [
'className' => CmsUserDTO::class,
'objIndex' => 0,
'argIndex' => 2,
];
Meta results
~~~~~~~~~~~~
-2
View File
@@ -578,8 +578,6 @@ of DQL. It takes 3 parameters: ``$dqlPartName``, ``$dqlPart`` and
not (no effect on the ``where`` and ``having`` DQL query parts,
which always override all previously defined items)
-
.. code-block:: php
<?php
+8 -2
View File
@@ -322,7 +322,10 @@ level cache region.
.. code-block:: xml
<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Country">
<cache usage="READ_ONLY" region="my_entity_region" />
<id name="id" type="integer" column="id">
@@ -427,7 +430,10 @@ It caches the primary keys of association and cache each element will be cached
.. code-block:: xml
<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="State">
<cache usage="NONSTRICT_READ_WRITE" />
+43 -7
View File
@@ -286,17 +286,53 @@ as follows:
After an entity has been removed, its in-memory state is the same as
before the removal, except for generated identifiers.
Removing an entity will also automatically delete any existing
records in many-to-many join tables that link this entity. The
action taken depends on the value of the ``@joinColumn`` mapping
attribute "onDelete". Either Doctrine issues a dedicated ``DELETE``
statement for records of each join table or it depends on the
foreign key semantics of onDelete="CASCADE".
During the ``EntityManager#flush()`` operation, the removed entity
will also be removed from all collections in entities currently
loaded into memory.
.. _remove_object_many_to_many_join_tables:
Join-table management when removing from many-to-many collections
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Regarding existing rows in many-to-many join tables that refer to
an entity being removed, the following applies.
When the entity being removed does not declare the many-to-many association
itself (that is, the many-to-many association is unidirectional and
the entity is on the inverse side), the ORM has no reasonable way to
detect associations targeting the entity's class. Thus, no ORM-level handling
of join-table rows is attempted and database-level constraints apply.
In case of database-level ``ON DELETE RESTRICT`` constraints, the
``EntityManager#flush()`` operation may abort and a ``ConstraintViolationException``
may be thrown. No in-memory collections will be modified in this case.
With ``ON DELETE CASCADE``, the RDBMS will take care of removing rows
from join tables.
When the entity being removed is part of bi-directional many-to-many
association, either as the owning or inverse side, the ORM will
delete rows from join tables before removing the entity itself. That means
database-level ``ON DELETE RESTRICT`` constraints on join tables are not
effective, since the join table rows are removed first. Removal of join table
rows happens through specialized methods in entity and collection persister
classes and take one query per entity and join table. In case the association
uses a ``@JoinColumn`` configuration with ``onDelete="CASCADE"``, instead
of using a dedicated ``DELETE`` query the database-level operation will be
relied upon.
.. note::
In case you rely on database-level ``ON DELETE RESTRICT`` constraints,
be aware that by making many-to-many associations bidirectional the
assumed protection may be lost.
Performance of different deletion strategies
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Deleting an object with all its associated objects can be achieved
in multiple ways with very different performance impacts.
1. If an association is marked as ``CASCADE=REMOVE`` Doctrine ORM
will fetch this association. If its a Single association it will
pass this entity to
+6 -6
View File
@@ -16,9 +16,9 @@ setup for the latest code in trunk.
.. code-block:: xml
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
...
@@ -102,9 +102,9 @@ of several common elements:
// Doctrine.Tests.ORM.Mapping.User.dcm.xml
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Doctrine\Tests\ORM\Mapping\User" table="cms_users">
@@ -769,9 +769,9 @@ entity relationship. You can define this in XML with the "association-key" attri
.. code-block:: xml
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Application\Model\ArticleAttribute">
-86
View File
@@ -1,86 +0,0 @@
Welcome to Doctrine 2 ORM's documentation!
==========================================
Tutorials
---------
.. toctree::
:maxdepth: 1
tutorials/getting-started
tutorials/getting-started-database
tutorials/getting-started-models
tutorials/working-with-indexed-associations
tutorials/extra-lazy-associations
tutorials/composite-primary-keys
tutorials/ordered-associations
tutorials/override-field-association-mappings-in-subclasses
tutorials/pagination.rst
tutorials/embeddables.rst
Reference Guide
---------------
.. toctree::
:maxdepth: 1
:numbered:
reference/architecture
reference/configuration.rst
reference/faq
reference/basic-mapping
reference/association-mapping
reference/inheritance-mapping
reference/working-with-objects
reference/working-with-associations
reference/events
reference/unitofwork
reference/unitofwork-associations
reference/transactions-and-concurrency
reference/batch-processing
reference/dql-doctrine-query-language
reference/query-builder
reference/native-sql
reference/change-tracking-policies
reference/partial-objects
reference/annotations-reference
reference/attributes-reference
reference/xml-mapping
reference/yaml-mapping
reference/php-mapping
reference/caching
reference/improving-performance
reference/tools
reference/metadata-drivers
reference/best-practices
reference/limitations-and-known-issues
tutorials/pagination
reference/filters
reference/namingstrategy
reference/advanced-configuration
reference/second-level-cache
reference/security
Cookbook
--------
.. toctree::
:maxdepth: 1
cookbook/aggregate-fields
cookbook/custom-mapping-types
cookbook/decorator-pattern
cookbook/dql-custom-walkers
cookbook/dql-user-defined-functions
cookbook/implementing-arrayaccess-for-domain-objects
cookbook/implementing-the-notify-changetracking-policy
cookbook/resolve-target-entity-listener
cookbook/sql-table-prefixes
cookbook/strategy-cookbook-introduction
cookbook/validation-of-entities
cookbook/working-with-datetime
cookbook/mysql-enums
cookbook/advanced-field-value-conversion-using-custom-mapping-types
cookbook/entities-in-session
+4 -4
View File
@@ -85,9 +85,9 @@ and year of production as primary keys:
.. code-block:: xml
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="VehicleCatalogue\Model\Car">
@@ -267,9 +267,9 @@ We keep up the example of an Article with arbitrary attributes, the mapping look
.. code-block:: xml
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Application\Model\ArticleAttribute">
@@ -85,9 +85,9 @@ switch to extra lazy as shown in these examples:
.. code-block:: xml
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Doctrine\Tests\Models\CMS\CmsGroup">
+16 -18
View File
@@ -102,8 +102,7 @@ Install Doctrine using the Composer Dependency Management tool, by calling:
This will install the packages Doctrine Common, Doctrine DBAL, Doctrine ORM,
into the ``vendor`` directory.
Add the following directories:
::
Add the following directories::
doctrine2-tutorial
|-- config
@@ -558,10 +557,10 @@ methods, but you only need to choose one.
.. code-block:: xml
<!-- config/xml/Product.dcm.xml -->
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Product" table="products">
<id name="id" type="integer">
@@ -1139,10 +1138,10 @@ the ``Product`` before:
.. code-block:: xml
<!-- config/xml/Bug.dcm.xml -->
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Bug" table="bugs">
<id name="id" type="integer">
@@ -1294,10 +1293,10 @@ Finally, we'll add metadata mappings for the ``User`` entity.
.. code-block:: xml
<!-- config/xml/User.dcm.xml -->
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="User" table="users">
<id name="id" type="integer">
@@ -1344,8 +1343,7 @@ means the join details have already been defined on the owning
side. Therefore we only have to specify the property on the Bug
class that holds the owning sides.
Update your database schema by running:
::
Update your database schema by running::
$ php bin/doctrine orm:schema-tool:update --force
@@ -1819,9 +1817,9 @@ we have to adjust the metadata slightly.
.. code-block:: xml
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Bug" table="bugs" repository-class="BugRepository">
@@ -161,9 +161,9 @@ The code and mappings for the Market entity looks like this:
.. code-block:: xml
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Doctrine\Tests\Models\StockExchange\Market">
@@ -278,9 +278,9 @@ here are the code and mappings for it:
.. code-block:: xml
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Doctrine\Tests\Models\StockExchange\Stock">
+2 -2
View File
@@ -208,10 +208,10 @@ class Configuration extends \Doctrine\DBAL\Configuration
}
/**
* @deprecated No replacement planned.
*
* Adds a namespace under a certain alias.
*
* @deprecated No replacement planned.
*
* @param string $alias
* @param string $namespace
*
@@ -313,7 +313,6 @@ class ObjectHydrator extends AbstractHydrator
* that belongs to a particular component/class. Afterwards, all these chunks
* are processed, one after the other. For each chunk of class data only one of the
* following code paths is executed:
*
* Path A: The data chunk belongs to a joined/associated object and the association
* is collection-valued.
* Path B: The data chunk belongs to a joined/associated object and the association
@@ -9,7 +9,9 @@ use Doctrine\DBAL\Platforms\DB2Platform;
use Doctrine\DBAL\Platforms\OraclePlatform;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use function get_class;
use function method_exists;
use function strpos;
use function strtolower;
use function strtoupper;
@@ -26,7 +28,7 @@ trait SQLResultCasing
return strtolower($column);
}
if (method_exists(AbstractPlatform::class, 'getSQLResultCasing')) {
if (strpos(get_class($platform), 'Doctrine\\DBAL\\Platforms\\') !== 0 && method_exists(AbstractPlatform::class, 'getSQLResultCasing')) {
return $platform->getSQLResultCasing($column);
}
@@ -7,6 +7,9 @@ namespace Doctrine\ORM\Mapping;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Platforms;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Platforms\SQLServerPlatform;
use Doctrine\Deprecations\Deprecation;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
@@ -621,9 +624,11 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
case ClassMetadata::GENERATOR_TYPE_IDENTITY:
$sequenceName = null;
$fieldName = $class->identifier ? $class->getSingleIdentifierFieldName() : null;
$platform = $this->getTargetPlatform();
// Platforms that do not have native IDENTITY support need a sequence to emulate this behaviour.
if ($this->getTargetPlatform()->usesSequenceEmulatedIdentityColumns()) {
/** @psalm-suppress UndefinedClass, InvalidClass */
if (! $platform instanceof MySQLPlatform && ! $platform instanceof SqlitePlatform && ! $platform instanceof SQLServerPlatform && $platform->usesSequenceEmulatedIdentityColumns()) {
Deprecation::trigger(
'doctrine/orm',
'https://github.com/doctrine/orm/issues/8850',
@@ -23,7 +23,6 @@ use function class_exists;
use function constant;
use function defined;
use function get_class;
use function sprintf;
use const PHP_VERSION_ID;
@@ -56,10 +55,10 @@ class AttributeDriver extends CompatibilityAnnotationDriver
public function __construct(array $paths)
{
if (PHP_VERSION_ID < 80000) {
throw new LogicException(sprintf(
throw new LogicException(
'The attribute metadata driver cannot be enabled on PHP 7. Please upgrade to PHP 8 or choose a different'
. ' metadata driver.'
));
);
}
$this->reader = new AttributeReader();
@@ -196,7 +196,7 @@ class DatabaseDriver implements MappingDriver
Deprecation::trigger(
'doctrine/orm',
'https://github.com/doctrine/orm/pull/249',
'Passing an instance of %s to %s is deprecated, please pass a ClassMetadata instance instead.',
'Passing an instance of %s to %s is deprecated, please pass a %s instance instead.',
get_class($metadata),
__METHOD__,
ClassMetadata::class
+8 -32
View File
@@ -50,27 +50,25 @@ class XmlDriver extends FileDriver
public function __construct($locator, $fileExtension = self::DEFAULT_FILE_EXTENSION, bool $isXsdValidationEnabled = false)
{
if (! extension_loaded('simplexml')) {
throw new LogicException(sprintf(
throw new LogicException(
'The XML metadata driver cannot be enabled because the SimpleXML PHP extension is missing.'
. ' Please configure PHP with SimpleXML or choose a different metadata driver.'
));
);
}
if (! $isXsdValidationEnabled) {
Deprecation::trigger(
'doctrine/orm',
'https://github.com/doctrine/orm/pull/6728',
sprintf(
'Using XML mapping driver with XSD validation disabled is deprecated'
. ' and will not be supported in Doctrine ORM 3.0.'
)
'Using XML mapping driver with XSD validation disabled is deprecated'
. ' and will not be supported in Doctrine ORM 3.0.'
);
}
if ($isXsdValidationEnabled && ! extension_loaded('dom')) {
throw new LogicException(sprintf(
throw new LogicException(
'XSD validation cannot be enabled because the DOM extension is missing.'
));
);
}
$this->isXsdValidationEnabled = $isXsdValidationEnabled;
@@ -378,30 +376,8 @@ class XmlDriver extends FileDriver
continue;
}
$mapping = [
'id' => true,
'fieldName' => (string) $idElement['name'],
];
if (isset($idElement['type'])) {
$mapping['type'] = (string) $idElement['type'];
}
if (isset($idElement['length'])) {
$mapping['length'] = (int) $idElement['length'];
}
if (isset($idElement['column'])) {
$mapping['columnName'] = (string) $idElement['column'];
}
if (isset($idElement['column-definition'])) {
$mapping['columnDefinition'] = (string) $idElement['column-definition'];
}
if (isset($idElement->options)) {
$mapping['options'] = $this->parseOptions($idElement->options->children());
}
$mapping = $this->columnToArray($idElement);
$mapping['id'] = true;
$metadata->mapField($mapping);
@@ -48,11 +48,11 @@ class YamlDriver extends FileDriver
);
if (! class_exists(Yaml::class)) {
throw new LogicException(sprintf(
throw new LogicException(
'The YAML metadata driver cannot be enabled because the "symfony/yaml" library'
. ' is not installed. Please run "composer require symfony/yaml" or choose a different'
. ' metadata driver.'
));
);
}
parent::__construct($locator, $fileExtension);
+2 -3
View File
@@ -24,7 +24,6 @@ use function apcu_enabled;
use function class_exists;
use function extension_loaded;
use function md5;
use function sprintf;
use function sys_get_temp_dir;
final class ORMSetup
@@ -72,11 +71,11 @@ final class ORMSetup
__METHOD__
);
if (! class_exists(AnnotationReader::class)) {
throw new LogicException(sprintf(
throw new LogicException(
'The annotation metadata driver cannot be enabled because the "doctrine/annotations" library'
. ' is not installed. Please run "composer require doctrine/annotations" or choose a different'
. ' metadata driver.'
));
);
}
$reader = new AnnotationReader();
@@ -16,6 +16,7 @@ use function array_reverse;
use function array_values;
use function assert;
use function implode;
use function is_int;
use function is_string;
/**
@@ -174,16 +175,22 @@ class OneToManyPersister extends AbstractCollectionPersister
$targetClass = $this->em->getClassMetadata($mapping['targetEntity']);
$columns = [];
$parameters = [];
$types = [];
foreach ($targetClass->associationMappings[$mapping['mappedBy']]['joinColumns'] as $joinColumn) {
$columns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform);
$parameters[] = $identifier[$sourceClass->getFieldForColumn($joinColumn['referencedColumnName'])];
$types[] = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $sourceClass, $this->em);
}
$statement = 'DELETE FROM ' . $this->quoteStrategy->getTableName($targetClass, $this->platform)
. ' WHERE ' . implode(' = ? AND ', $columns) . ' = ?';
return $this->conn->executeStatement($statement, $parameters);
$numAffected = $this->conn->executeStatement($statement, $parameters, $types);
assert(is_int($numAffected));
return $numAffected;
}
/**
@@ -247,6 +254,8 @@ class OneToManyPersister extends AbstractCollectionPersister
$this->conn->executeStatement($statement);
assert(is_int($numDeleted));
return $numDeleted;
}
}
@@ -273,10 +273,6 @@ class BasicEntityPersister implements EntityPersister
$paramIndex = 1;
foreach ($insertData[$tableName] as $column => $value) {
if ($value instanceof BackedEnum) {
$value = $value->value;
}
$stmt->bindValue($paramIndex++, $value, $this->columnTypes[$column]);
}
}
@@ -542,7 +538,7 @@ class BasicEntityPersister implements EntityPersister
protected function deleteJoinTableRecords(array $identifier, array $types): void
{
foreach ($this->class->associationMappings as $mapping) {
if ($mapping['type'] !== ClassMetadata::MANY_TO_MANY) {
if ($mapping['type'] !== ClassMetadata::MANY_TO_MANY || isset($mapping['isOnDeleteCascade'])) {
continue;
}
@@ -578,10 +574,6 @@ class BasicEntityPersister implements EntityPersister
$otherKeys[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform);
}
if (isset($mapping['isOnDeleteCascade'])) {
continue;
}
$joinTableName = $this->quoteStrategy->getJoinTableName($association, $this->class, $this->platform);
$this->conn->delete($joinTableName, array_combine($keys, $identifier), $types);
+47 -26
View File
@@ -21,6 +21,7 @@ use Doctrine\Persistence\Proxy;
use ReflectionProperty;
use Symfony\Component\VarExporter\ProxyHelper;
use Symfony\Component\VarExporter\VarExporter;
use Throwable;
use function array_flip;
use function str_replace;
@@ -47,13 +48,12 @@ class <proxyShortClassName> extends \<className> implements \<baseProxyInterface
{
<useLazyGhostTrait>
/**
* @internal
*/
public bool $__isCloning = false;
public function __construct(?\Closure $initializer = null)
public function __construct(?\Closure $initializer = null, ?\Closure $cloner = null)
{
if ($cloner !== null) {
return;
}
self::createLazyGhost($initializer, <skippedProperties>, $this);
}
@@ -62,17 +62,6 @@ class <proxyShortClassName> extends \<className> implements \<baseProxyInterface
return isset($this->lazyObjectState) && $this->isLazyObjectInitialized();
}
public function __clone()
{
$this->__isCloning = true;
try {
$this->__doClone();
} finally {
$this->__isCloning = false;
}
}
public function __serialize(): array
{
<serializeImpl>
@@ -97,6 +86,9 @@ EOPHP;
*/
private $identifierFlattener;
/** @var ProxyDefinition[] */
private $definitions = [];
/**
* Initializes a new instance of the <tt>ProxyFactory</tt> class that is
* connected to the given <tt>EntityManager</tt>.
@@ -130,6 +122,26 @@ EOPHP;
$this->identifierFlattener = new IdentifierFlattener($this->uow, $em->getMetadataFactory());
}
/**
* {@inheritDoc}
*/
public function getProxy($className, array $identifier)
{
$proxy = parent::getProxy($className, $identifier);
if (! $this->em->getConfiguration()->isLazyGhostObjectEnabled()) {
return $proxy;
}
$initializer = $this->definitions[$className]->initializer;
$proxy->__construct(static function (Proxy $object) use ($initializer, $proxy): void {
$initializer($object, $proxy);
});
return $proxy;
}
/**
* {@inheritDoc}
*/
@@ -157,7 +169,7 @@ EOPHP;
$cloner = $this->createCloner($classMetadata, $entityPersister);
}
return new ProxyDefinition(
return $this->definitions[$className] = new ProxyDefinition(
ClassUtils::generateProxyClassName($className, $this->proxyNs),
$classMetadata->getIdentifierFieldNames(),
$classMetadata->getReflectionProperties(),
@@ -204,7 +216,17 @@ EOPHP;
$identifier = $classMetadata->getIdentifierValues($proxy);
if ($entityPersister->loadById($identifier, $proxy) === null) {
try {
$entity = $entityPersister->loadById($identifier, $proxy);
} catch (Throwable $exception) {
$proxy->__setInitializer($initializer);
$proxy->__setCloner($cloner);
$proxy->__setInitialized(false);
throw $exception;
}
if ($entity === null) {
$proxy->__setInitializer($initializer);
$proxy->__setCloner($cloner);
$proxy->__setInitialized(false);
@@ -220,15 +242,15 @@ EOPHP;
/**
* Creates a closure capable of initializing a proxy
*
* @return Closure(Proxy):void
* @return Closure(Proxy, Proxy):void
*
* @throws EntityNotFoundException
*/
private function createLazyInitializer(ClassMetadata $classMetadata, EntityPersister $entityPersister): Closure
{
return function (Proxy $proxy) use ($entityPersister, $classMetadata): void {
$identifier = $classMetadata->getIdentifierValues($proxy);
$entity = $entityPersister->loadById($identifier, $proxy->__isCloning ? null : $proxy);
return function (Proxy $proxy, Proxy $original) use ($entityPersister, $classMetadata): void {
$identifier = $classMetadata->getIdentifierValues($original);
$entity = $entityPersister->loadById($identifier, $original);
if ($entity === null) {
throw EntityNotFoundException::fromClassNameAndIdentifier(
@@ -237,7 +259,7 @@ EOPHP;
);
}
if (! $proxy->__isCloning) {
if ($proxy === $original) {
return;
}
@@ -304,7 +326,6 @@ EOPHP;
isLazyObjectInitialized as private;
createLazyGhost as private;
resetLazyObject as private;
__clone as private __doClone;
}'), $code);
return $code;
@@ -312,7 +333,7 @@ EOPHP;
private function generateSkippedProperties(ClassMetadata $class): string
{
$skippedProperties = ['__isCloning' => true];
$skippedProperties = [];
$identifiers = array_flip($class->getIdentifierFieldNames());
$filter = ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED | ReflectionProperty::IS_PRIVATE;
$reflector = $class->getReflectionClass();
@@ -53,10 +53,9 @@ abstract class AbstractSqlExecutor
/**
* Executes all sql statements.
*
* @param Connection $conn The database connection that is used to execute the queries.
* @psalm-param list<mixed>|array<string, mixed> $params The parameters.
* @psalm-param array<int, int|string|Type|null>|
* array<string, int|string|Type|null> $types The parameter types.
* @param Connection $conn The database connection that is used to execute the queries.
* @param list<mixed>|array<string, mixed> $params The parameters.
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types The parameter types.
*
* @return Result|int
*/
+2 -2
View File
@@ -2566,7 +2566,7 @@ class Parser
* EmptyCollectionComparisonExpression | CollectionMemberExpression |
* InstanceOfExpression
*
* @return AST\BetweenExpression|
* @return (AST\BetweenExpression|
* AST\CollectionMemberExpression|
* AST\ComparisonExpression|
* AST\EmptyCollectionComparisonExpression|
@@ -2574,7 +2574,7 @@ class Parser
* AST\InExpression|
* AST\InstanceOfExpression|
* AST\LikeExpression|
* AST\NullComparisonExpression
* AST\NullComparisonExpression)
*/
public function SimpleConditionalExpression()
{
+6 -1
View File
@@ -809,7 +809,12 @@ class QueryBuilder
*/
public function distinct($flag = true)
{
$this->dqlParts['distinct'] = (bool) $flag;
$flag = (bool) $flag;
if ($this->dqlParts['distinct'] !== $flag) {
$this->dqlParts['distinct'] = $flag;
$this->state = self::STATE_DIRTY;
}
return $this;
}
@@ -56,7 +56,5 @@ class AttachEntityListenersListener
$metadata->addEntityListener($listener['event'], $listener['class'], $listener['method']);
}
}
unset($this->entityListeners[$metadata->name]);
}
}
@@ -33,7 +33,7 @@ abstract class AbstractEntityManagerCommand extends Command
'doctrine/orm',
'https://github.com/doctrine/orm/issues/8327',
'Not passing EntityManagerProvider as a dependency to command class "%s" is deprecated',
$this->getName()
static::class
);
$helper = $this->getHelper('em');
@@ -17,6 +17,7 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use function assert;
use function get_debug_type;
use function sprintf;
@@ -63,32 +64,46 @@ EOT
{
$ui = (new SymfonyStyle($input, $output))->getErrorStyle();
$em = $this->getEntityManager($input);
$cache = $em->getConfiguration()->getQueryCache();
$cacheDriver = $em->getConfiguration()->getQueryCacheImpl();
$em = $this->getEntityManager($input);
$cache = $em->getConfiguration()->getQueryCache();
if (! $cacheDriver) {
throw new InvalidArgumentException('No Query cache driver is configured on given EntityManager.');
}
if ($cacheDriver instanceof ApcCache || $cache instanceof ApcuAdapter) {
if ($cache instanceof ApcuAdapter) {
throw new LogicException('Cannot clear APCu Cache from Console, it\'s shared in the Webserver memory and not accessible from the CLI.');
}
if ($cacheDriver instanceof XcacheCache) {
throw new LogicException('Cannot clear XCache Cache from Console, it\'s shared in the Webserver memory and not accessible from the CLI.');
}
$cacheDriver = null;
if (! $cache) {
$cacheDriver = $em->getConfiguration()->getQueryCacheImpl();
if (! ($cacheDriver instanceof ClearableCache)) {
throw new LogicException(sprintf(
'Can only clear cache when ClearableCache interface is implemented, %s does not implement.',
get_debug_type($cacheDriver)
));
if (! $cacheDriver) {
throw new InvalidArgumentException('No Query cache driver is configured on given EntityManager.');
}
if ($cacheDriver instanceof ApcCache) {
throw new LogicException('Cannot clear APCu Cache from Console, it\'s shared in the Webserver memory and not accessible from the CLI.');
}
if ($cacheDriver instanceof XcacheCache) {
throw new LogicException('Cannot clear XCache Cache from Console, it\'s shared in the Webserver memory and not accessible from the CLI.');
}
if (! ($cacheDriver instanceof ClearableCache)) {
throw new LogicException(sprintf(
'Can only clear cache when ClearableCache interface is implemented, %s does not implement.',
get_debug_type($cacheDriver)
));
}
}
$ui->comment('Clearing <info>all</info> Query cache entries');
$result = $cache ? $cache->clear() : $cacheDriver->deleteAll();
if ($cache) {
$result = $cache->clear();
} else {
assert($cacheDriver !== null);
$result = $cacheDriver->deleteAll();
}
$message = $result ? 'Successfully deleted cache entries.' : 'No cache entries were deleted.';
if ($input->getOption('flush') === true && ! $cache) {
@@ -73,7 +73,13 @@ in Doctrine 2 and can be used as runtime mapping for the ORM.
by the ORM, you can use a DBAL functionality to filter the tables and sequences down
on a global level:
$config->setFilterSchemaAssetsExpression($regexp);
$config->setSchemaAssetsFilter(function (string|AbstractAsset $assetName): bool {
if ($assetName instanceof AbstractAsset) {
$assetName = $assetName->getName();
}
return !str_starts_with($assetName, 'audit_');
});
EOT
);
}
@@ -33,7 +33,13 @@ Processes the schema and either create it directly on EntityManager Storage Conn
by the ORM, you can use a DBAL functionality to filter the tables and sequences down
on a global level:
$config->setFilterSchemaAssetsExpression($regexp);
$config->setSchemaAssetsFilter(function (string|AbstractAsset $assetName): bool {
if ($assetName instanceof AbstractAsset) {
$assetName = $assetName->getName();
}
return !str_starts_with($assetName, 'audit_');
});
EOT
);
}
@@ -37,7 +37,13 @@ Beware that the complete database is dropped by this command, even tables that a
by the ORM, you can use a DBAL functionality to filter the tables and sequences down
on a global level:
$config->setFilterSchemaAssetsExpression($regexp);
$config->setSchemaAssetsFilter(function (string|AbstractAsset $assetName): bool {
if ($assetName instanceof AbstractAsset) {
$assetName = $assetName->getName();
}
return !str_starts_with($assetName, 'audit_');
});
EOT
);
}
@@ -61,7 +61,13 @@ described by any metadata. Not passing that option is deprecated.
by the ORM, you can use a DBAL functionality to filter the tables and sequences down
on a global level:
$config->setFilterSchemaAssetsExpression($regexp);
$config->setSchemaAssetsFilter(function (string|AbstractAsset $assetName): bool {
if ($assetName instanceof AbstractAsset) {
$assetName = $assetName->getName();
}
return !str_starts_with($assetName, 'audit_');
});
EOT
);
}
+11 -4
View File
@@ -12,6 +12,7 @@ use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\Schema\Comparator;
use Doctrine\DBAL\Schema\Index;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\Sequence;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\Visitor\RemoveNamespacedAssets;
use Doctrine\Deprecations\Deprecation;
@@ -406,8 +407,14 @@ class SchemaTool
}
}
if (! $this->platform->supportsSchemas() && ! $this->platform->canEmulateSchemas()) {
$schema->visit(new RemoveNamespacedAssets());
if (! $this->platform->supportsSchemas()) {
$filter = /** @param Sequence|Table $asset */ static function ($asset) use ($schema): bool {
return ! $asset->isInDefaultNamespace($schema->getName());
};
if (array_filter($schema->getSequences() + $schema->getTables(), $filter) && ! $this->platform->canEmulateSchemas()) {
$schema->visit(new RemoveNamespacedAssets());
}
}
if ($eventManager->hasListeners(ToolEvents::postGenerateSchema)) {
@@ -814,8 +821,8 @@ class SchemaTool
return [];
}
$options = array_intersect_key($mappingOptions, array_flip(self::KNOWN_COLUMN_OPTIONS));
$options['customSchemaOptions'] = array_diff_key($mappingOptions, $options);
$options = array_intersect_key($mappingOptions, array_flip(self::KNOWN_COLUMN_OPTIONS));
$options['platformOptions'] = array_diff_key($mappingOptions, $options);
return $options;
}
+92 -45
View File
@@ -240,6 +240,17 @@ class UnitOfWork implements PropertyChangedListener
*/
private $visitedCollections = [];
/**
* List of collections visited during the changeset calculation that contain to-be-removed
* entities and need to have keys removed post commit.
*
* Indexed by Collection object ID, which also serves as the key in self::$visitedCollections;
* values are the key names that need to be removed.
*
* @psalm-var array<int, array<array-key, true>>
*/
private $pendingCollectionElementRemovals = [];
/**
* The EntityManager that "owns" this UnitOfWork instance.
*
@@ -474,8 +485,15 @@ class UnitOfWork implements PropertyChangedListener
$this->afterTransactionComplete();
// Take new snapshots from visited collections
foreach ($this->visitedCollections as $coll) {
// Unset removed entities from collections, and take new snapshots from
// all visited collections.
foreach ($this->visitedCollections as $coid => $coll) {
if (isset($this->pendingCollectionElementRemovals[$coid])) {
foreach ($this->pendingCollectionElementRemovals[$coid] as $key => $valueIgnored) {
unset($coll[$key]);
}
}
$coll->takeSnapshot();
}
@@ -487,15 +505,16 @@ class UnitOfWork implements PropertyChangedListener
/** @param object|object[]|null $entity */
private function postCommitCleanup($entity): void
{
$this->entityInsertions =
$this->entityUpdates =
$this->entityDeletions =
$this->extraUpdates =
$this->collectionUpdates =
$this->nonCascadedNewDetectedEntities =
$this->collectionDeletions =
$this->visitedCollections =
$this->orphanRemovals = [];
$this->entityInsertions =
$this->entityUpdates =
$this->entityDeletions =
$this->extraUpdates =
$this->collectionUpdates =
$this->nonCascadedNewDetectedEntities =
$this->collectionDeletions =
$this->pendingCollectionElementRemovals =
$this->visitedCollections =
$this->orphanRemovals = [];
if ($entity === null) {
$this->entityChangeSets = $this->scheduledForSynchronization = [];
@@ -916,6 +935,14 @@ class UnitOfWork implements PropertyChangedListener
return;
}
// If this collection is dirty, schedule it for updates
if ($value instanceof PersistentCollection && $value->isDirty()) {
$coid = spl_object_id($value);
$this->collectionUpdates[$coid] = $value;
$this->visitedCollections[$coid] = $value;
}
// Look through the entities, and in any of their associations,
// for transient (new) entities, recursively. ("Persistence by reachability")
// Unwrap. Uninitialized collections will simply be empty.
@@ -960,10 +987,18 @@ class UnitOfWork implements PropertyChangedListener
case self::STATE_REMOVED:
// Consume the $value as array (it's either an array or an ArrayAccess)
// and remove the element from Collection.
if ($assoc['type'] & ClassMetadata::TO_MANY) {
unset($value[$key]);
if (! ($assoc['type'] & ClassMetadata::TO_MANY)) {
break;
}
$coid = spl_object_id($value);
$this->visitedCollections[$coid] = $value;
if (! isset($this->pendingCollectionElementRemovals[$coid])) {
$this->pendingCollectionElementRemovals[$coid] = [];
}
$this->pendingCollectionElementRemovals[$coid][$key] = true;
break;
case self::STATE_DETACHED:
@@ -976,13 +1011,6 @@ class UnitOfWork implements PropertyChangedListener
// during changeset calculation anyway, since they are in the identity map.
}
}
if ($value instanceof PersistentCollection && $value->isDirty()) {
$coid = spl_object_id($value);
$this->collectionUpdates[$coid] = $value;
$this->visitedCollections[$coid] = $value;
}
}
/**
@@ -1096,6 +1124,20 @@ class UnitOfWork implements PropertyChangedListener
foreach ($actualData as $propName => $actualValue) {
$orgValue = $originalData[$propName] ?? null;
if (isset($class->fieldMappings[$propName]['enumType'])) {
if (is_array($orgValue)) {
foreach ($orgValue as $id => $val) {
if ($val instanceof BackedEnum) {
$orgValue[$id] = $val->value;
}
}
} else {
if ($orgValue instanceof BackedEnum) {
$orgValue = $orgValue->value;
}
}
}
if ($orgValue !== $actualValue) {
$changeSet[$propName] = [$orgValue, $actualValue];
}
@@ -2627,23 +2669,24 @@ class UnitOfWork implements PropertyChangedListener
public function clear($entityName = null)
{
if ($entityName === null) {
$this->identityMap =
$this->entityIdentifiers =
$this->originalEntityData =
$this->entityChangeSets =
$this->entityStates =
$this->scheduledForSynchronization =
$this->entityInsertions =
$this->entityUpdates =
$this->entityDeletions =
$this->nonCascadedNewDetectedEntities =
$this->collectionDeletions =
$this->collectionUpdates =
$this->extraUpdates =
$this->readOnlyObjects =
$this->visitedCollections =
$this->eagerLoadingEntities =
$this->orphanRemovals = [];
$this->identityMap =
$this->entityIdentifiers =
$this->originalEntityData =
$this->entityChangeSets =
$this->entityStates =
$this->scheduledForSynchronization =
$this->entityInsertions =
$this->entityUpdates =
$this->entityDeletions =
$this->nonCascadedNewDetectedEntities =
$this->collectionDeletions =
$this->collectionUpdates =
$this->extraUpdates =
$this->readOnlyObjects =
$this->pendingCollectionElementRemovals =
$this->visitedCollections =
$this->eagerLoadingEntities =
$this->orphanRemovals = [];
} else {
Deprecation::triggerIfCalledFromOutside(
'doctrine/orm',
@@ -3640,14 +3683,18 @@ class UnitOfWork implements PropertyChangedListener
$targetClass = $this->em->getClassMetadata($assoc2['targetEntity']);
$relatedId = $targetClass->getIdentifierValues($other);
if ($targetClass->subClasses) {
$other = $this->em->find($targetClass->name, $relatedId);
} else {
$other = $this->em->getProxyFactory()->getProxy(
$assoc2['targetEntity'],
$relatedId
);
$this->registerManaged($other, $relatedId, []);
$other = $this->tryGetById($relatedId, $targetClass->name);
if (! $other) {
if ($targetClass->subClasses) {
$other = $this->em->find($targetClass->name, $relatedId);
} else {
$other = $this->em->getProxyFactory()->getProxy(
$assoc2['targetEntity'],
$relatedId
);
$this->registerManaged($other, $relatedId, []);
}
}
}
+6 -16
View File
@@ -225,6 +225,11 @@ parameters:
count: 1
path: lib/Doctrine/ORM/Mapping/Driver/AttributeDriver.php
-
message: "#^Parameter \\#4 \\.\\.\\.\\$args of static method Doctrine\\\\Deprecations\\\\Deprecation\\:\\:trigger\\(\\) expects float\\|int\\|string, false given\\.$#"
count: 1
path: lib/Doctrine/ORM/Mapping/Driver/DatabaseDriver.php
-
message: "#^Empty array passed to foreach\\.$#"
count: 1
@@ -281,7 +286,7 @@ parameters:
path: lib/Doctrine/ORM/Proxy/ProxyFactory.php
-
message: "#^Access to an undefined property Doctrine\\\\Persistence\\\\Proxy\\:\\:\\$__isCloning\\.$#"
message: "#^Call to an undefined method Doctrine\\\\Common\\\\Proxy\\\\Proxy\\:\\:__construct\\(\\)\\.$#"
count: 1
path: lib/Doctrine/ORM/Proxy/ProxyFactory.php
@@ -390,21 +395,6 @@ parameters:
count: 1
path: lib/Doctrine/ORM/Query/Parser.php
-
message: """
#^PHPDoc tag @return has invalid value \\(AST\\\\BetweenExpression\\|
AST\\\\CollectionMemberExpression\\|
AST\\\\ComparisonExpression\\|
AST\\\\EmptyCollectionComparisonExpression\\|
AST\\\\ExistsExpression\\|
AST\\\\InExpression\\|
AST\\\\InstanceOfExpression\\|
AST\\\\LikeExpression\\|
AST\\\\NullComparisonExpression\\)\\: Unexpected token "\\\\n \\* ", expected type at offset 344$#
"""
count: 1
path: lib/Doctrine/ORM/Query/Parser.php
-
message: "#^Parameter \\#2 \\$stringPattern of class Doctrine\\\\ORM\\\\Query\\\\AST\\\\LikeExpression constructor expects Doctrine\\\\ORM\\\\Query\\\\AST\\\\Functions\\\\FunctionNode\\|Doctrine\\\\ORM\\\\Query\\\\AST\\\\InputParameter\\|Doctrine\\\\ORM\\\\Query\\\\AST\\\\Literal\\|Doctrine\\\\ORM\\\\Query\\\\AST\\\\PathExpression, Doctrine\\\\ORM\\\\Query\\\\AST\\\\Node given\\.$#"
count: 1
+3
View File
@@ -10,6 +10,9 @@ parameters:
- '/Call to an undefined method Doctrine\\DBAL\\Connection::createSchemaManager\(\)\./'
# Class name will change in DBAL 3.
- '/^Class Doctrine\\DBAL\\Platforms\\PostgreSQLPlatform not found\.$/'
-
message: '/Doctrine\\DBAL\\Platforms\\MyS(ql|QL)Platform/'
path: lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php
# Forward compatibility for DBAL 3.5
- '/^Call to an undefined method Doctrine\\DBAL\\Platforms\\AbstractPlatform::getAlterSchemaSQL\(\).$/'
+10 -19
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="5.11.0@c9b192ab8400fdaf04b2b13d110575adc879aa90">
<files psalm-version="5.13.1@086b94371304750d1c673315321a55d15fc59015">
<file src="lib/Doctrine/ORM/AbstractQuery.php">
<DeprecatedClass>
<code>IterableResult</code>
@@ -437,6 +437,9 @@
<ReferenceReusedFromConfusingScope>
<code>$baseElement</code>
</ReferenceReusedFromConfusingScope>
<UnsupportedPropertyReferenceUsage>
<code><![CDATA[$baseElement =& $this->resultPointers[$parent]]]></code>
</UnsupportedPropertyReferenceUsage>
<UnsupportedReferenceUsage>
<code><![CDATA[$baseElement =& $this->resultPointers[$parent][key($first)]]]></code>
<code><![CDATA[$this->resultPointers[$dqlAlias] =& $coll[key($coll)]]]></code>
@@ -1236,14 +1239,6 @@
$mapping['indexBy'] => $index,
]]]></code>
</InvalidArrayOffset>
<InvalidReturnStatement>
<code>$numDeleted</code>
<code><![CDATA[$this->conn->executeStatement($statement, $parameters)]]></code>
</InvalidReturnStatement>
<InvalidReturnType>
<code>int</code>
<code>int</code>
</InvalidReturnType>
<PossiblyNullArgument>
<code><![CDATA[$collection->getOwner()]]></code>
<code><![CDATA[$collection->getOwner()]]></code>
@@ -1397,6 +1392,11 @@
<code>$classMetadata</code>
<code>$classMetadata</code>
</ArgumentTypeCoercion>
<DirectConstructorCall>
<code><![CDATA[$proxy->__construct(static function (Proxy $object) use ($initializer, $proxy): void {
$initializer($object, $proxy);
})]]></code>
</DirectConstructorCall>
<InvalidArgument>
<code><![CDATA[$classMetadata->getReflectionProperties()]]></code>
<code><![CDATA[$em->getMetadataFactory()]]></code>
@@ -1405,7 +1405,6 @@
<NoInterfaceProperties>
<code><![CDATA[$metadata->isEmbeddedClass]]></code>
<code><![CDATA[$metadata->isMappedSuperclass]]></code>
<code><![CDATA[$proxy->__isCloning]]></code>
</NoInterfaceProperties>
<PossiblyNullPropertyFetch>
<code><![CDATA[$property->name]]></code>
@@ -1416,6 +1415,7 @@
<code>setAccessible</code>
</PossiblyNullReference>
<UndefinedInterfaceMethod>
<code>__construct</code>
<code>__wakeup</code>
</UndefinedInterfaceMethod>
</file>
@@ -2013,19 +2013,10 @@
<code>$factors[0]</code>
<code>$primary</code>
<code>$terms[0]</code>
<code><![CDATA[$this->CollectionMemberExpression()]]></code>
<code><![CDATA[$this->ComparisonExpression()]]></code>
<code><![CDATA[$this->EmptyCollectionComparisonExpression()]]></code>
<code><![CDATA[$this->ExistsExpression()]]></code>
<code><![CDATA[$this->InExpression()]]></code>
<code><![CDATA[$this->InstanceOfExpression()]]></code>
<code><![CDATA[$this->LikeExpression()]]></code>
<code><![CDATA[$this->NullComparisonExpression()]]></code>
</InvalidReturnStatement>
<InvalidReturnType>
<code>AST\ArithmeticFactor</code>
<code>AST\ArithmeticTerm</code>
<code>AST\BetweenExpression|</code>
<code>AST\SimpleArithmeticExpression|AST\ArithmeticTerm</code>
</InvalidReturnType>
<InvalidStringClass>
-1
View File
@@ -82,7 +82,6 @@
<referencedMethod name="Doctrine\DBAL\Platforms\AbstractPlatform::getGuidExpression"/>
<referencedMethod name="Doctrine\DBAL\Platforms\AbstractPlatform::supportsForeignKeyConstraints"/>
<!-- Remove on 3.0.x -->
<referencedMethod name="Doctrine\Common\Lexer\Token::offsetGet"/>
<referencedMethod name="Doctrine\DBAL\Connection::getEventManager"/>
<referencedMethod name="Doctrine\DBAL\Schema\Schema::visit"/>
<referencedMethod name="Doctrine\DBAL\Schema\SchemaDiff::toSaveSql"/>
@@ -260,6 +260,78 @@ class EnumTest extends OrmFunctionalTestCase
self::assertEqualsCanonicalizing([Unit::Gram, Unit::Meter], $result[0]->supportedUnits);
}
public function testEnumSingleEntityChangeSetsSimpleObjectHydrator(): void
{
$this->setUpEntitySchema([Card::class]);
$card = new Card();
$card->suit = Suit::Clubs;
$this->_em->persist($card);
$this->_em->flush();
$this->_em->clear();
$result = $this->_em->find(Card::class, $card->id);
$this->_em->getUnitOfWork()->recomputeSingleEntityChangeSet(
$this->_em->getClassMetadata(Card::class),
$result
);
self::assertFalse($this->_em->getUnitOfWork()->isScheduledForUpdate($result));
$result->suit = Suit::Hearts;
$this->_em->getUnitOfWork()->recomputeSingleEntityChangeSet(
$this->_em->getClassMetadata(Card::class),
$result
);
self::assertTrue($this->_em->getUnitOfWork()->isScheduledForUpdate($result));
}
public function testEnumSingleEntityChangeSetsObjectHydrator(): void
{
$this->setUpEntitySchema([Card::class]);
$card = new Card();
$card->suit = Suit::Clubs;
$this->_em->persist($card);
$this->_em->flush();
$this->_em->clear();
$result = $this->_em->find(Card::class, $card->id);
$this->_em->getUnitOfWork()->recomputeSingleEntityChangeSet(
$this->_em->getClassMetadata(Card::class),
$result
);
self::assertFalse($this->_em->getUnitOfWork()->isScheduledForUpdate($result));
}
public function testEnumArraySingleEntityChangeSets(): void
{
$this->setUpEntitySchema([Scale::class]);
$scale = new Scale();
$scale->supportedUnits = [Unit::Gram];
$this->_em->persist($scale);
$this->_em->flush();
$this->_em->clear();
$result = $this->_em->find(Scale::class, $scale->id);
$this->_em->getUnitOfWork()->recomputeSingleEntityChangeSet(
$this->_em->getClassMetadata(Scale::class),
$result
);
self::assertFalse($this->_em->getUnitOfWork()->isScheduledForUpdate($result));
}
public function testEnumChangeSetsSimpleObjectHydrator(): void
{
$this->setUpEntitySchema([Card::class]);
@@ -101,6 +101,9 @@ class ManyToManyBasicAssociationTest extends OrmFunctionalTestCase
//$user->getGroups()->remove(0);
$this->_em->flush();
self::assertFalse($user->getGroups()->isDirty());
$this->_em->clear();
// Reload same user
@@ -141,8 +144,13 @@ class ManyToManyBasicAssociationTest extends OrmFunctionalTestCase
$user->groups->clear();
$this->getQueryLog()->reset()->enable();
$this->_em->flush();
// Deletions of entire collections happen in a single query
$this->removeTransactionCommandsFromQueryLog();
self::assertQueryCount(1);
// Check that the links in the association table have been deleted
$this->assertGblancoGroupCountIs(0);
}
@@ -212,12 +220,20 @@ class ManyToManyBasicAssociationTest extends OrmFunctionalTestCase
/** @group DDC-130 */
public function testRemoveUserWithManyGroups(): void
{
$user = $this->addCmsUserGblancoWithGroups(2);
$user = $this->addCmsUserGblancoWithGroups(10);
$userId = $user->getId();
$this->_em->remove($user);
$this->getQueryLog()->reset()->enable();
$this->_em->flush();
// This takes three queries: One to delete all user -> group join table rows for the user,
// one to delete all user -> tags join table rows for the user, and a final one to delete the user itself.
$this->removeTransactionCommandsFromQueryLog();
self::assertQueryCount(3);
$newUser = $this->_em->find(get_class($user), $userId);
self::assertNull($newUser);
}
@@ -225,15 +241,40 @@ class ManyToManyBasicAssociationTest extends OrmFunctionalTestCase
/** @group DDC-130 */
public function testRemoveGroupWithUser(): void
{
$user = $this->addCmsUserGblancoWithGroups(2);
$user = $this->addCmsUserGblancoWithGroups(5);
$anotherUser = new CmsUser();
$anotherUser->username = 'joe_doe';
$anotherUser->name = 'Joe Doe';
$anotherUser->status = 'QA Engineer';
foreach ($user->getGroups() as $group) {
$anotherUser->addGroup($group);
}
$this->_em->persist($anotherUser);
$this->_em->flush();
foreach ($user->getGroups() as $group) {
$this->_em->remove($group);
}
$this->getQueryLog()->reset()->enable();
$this->_em->flush();
// This takes 5 * 2 queries for each group to be removed, one to remove all join table rows
// for the CmsGroup -> CmsUser inverse side association (for both users at once),
// and one for the group itself.
$this->removeTransactionCommandsFromQueryLog();
self::assertQueryCount(10);
// Changes to in-memory collection have been made and flushed
self::assertCount(0, $user->getGroups());
self::assertFalse($user->getGroups()->isDirty());
$this->_em->clear();
// Changes have been made to the database
$newUser = $this->_em->find(get_class($user), $user->getId());
self::assertCount(0, $newUser->getGroups());
}
@@ -243,7 +284,13 @@ class ManyToManyBasicAssociationTest extends OrmFunctionalTestCase
$user = $this->addCmsUserGblancoWithGroups(2);
$user->groups = null;
$this->getQueryLog()->reset()->enable();
$this->_em->flush();
// It takes one query to remove all join table rows for the user at once
$this->removeTransactionCommandsFromQueryLog();
self::assertQueryCount(1);
$this->_em->clear();
$newUser = $this->_em->find(get_class($user), $user->getId());
@@ -528,4 +575,15 @@ class ManyToManyBasicAssociationTest extends OrmFunctionalTestCase
self::assertFalse($user->groups->isInitialized(), 'Post-condition: matching does not initialize collection');
}
private function removeTransactionCommandsFromQueryLog(): void
{
$log = $this->getQueryLog();
foreach ($log->queries as $key => $entry) {
if ($entry['sql'] === '"START TRANSACTION"' || $entry['sql'] === '"COMMIT"') {
unset($log->queries[$key]);
}
}
}
}
@@ -109,8 +109,7 @@ class ManyToManyBidirectionalAssociationTest extends AbstractManyToManyAssociati
/** @psalm-return list<ECommerceProduct> */
protected function findProducts(): array
{
$query = $this->_em->createQuery('SELECT p, c FROM Doctrine\Tests\Models\ECommerce\ECommerceProduct p LEFT JOIN p.categories c ORDER BY p.id, c.id');
//$query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true);
$query = $this->_em->createQuery('SELECT p, c FROM Doctrine\Tests\Models\ECommerce\ECommerceProduct p LEFT JOIN p.categories c ORDER BY p.id, c.id');
$result = $query->getResult();
self::assertCount(2, $result);
$cats1 = $result[0]->getCategories();
@@ -126,8 +125,7 @@ class ManyToManyBidirectionalAssociationTest extends AbstractManyToManyAssociati
/** @psalm-return list<ECommerceCategory> */
protected function findCategories(): array
{
$query = $this->_em->createQuery('SELECT c, p FROM Doctrine\Tests\Models\ECommerce\ECommerceCategory c LEFT JOIN c.products p ORDER BY c.id, p.id');
//$query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true);
$query = $this->_em->createQuery('SELECT c, p FROM Doctrine\Tests\Models\ECommerce\ECommerceCategory c LEFT JOIN c.products p ORDER BY c.id, p.id');
$result = $query->getResult();
self::assertCount(2, $result);
self::assertInstanceOf(ECommerceCategory::class, $result[0]);
@@ -30,21 +30,22 @@ class ManyToManyEventTest extends OrmFunctionalTestCase
public function testListenerShouldBeNotifiedWhenNewCollectionEntryAdded(): void
{
$user = $this->createNewValidUser();
$user = $this->createNewValidUser();
$group = new CmsGroup();
$group->name = 'admins';
$this->_em->persist($user);
$this->_em->persist($group);
$this->_em->flush();
self::assertFalse($this->listener->wasNotified);
$group = new CmsGroup();
$group->name = 'admins';
$user->addGroup($group);
$this->_em->persist($user);
$this->_em->flush();
self::assertTrue($this->listener->wasNotified);
}
public function testListenerShouldBeNotifiedWhenNewCollectionEntryRemoved(): void
public function testListenerShouldBeNotifiedWhenCollectionEntryRemoved(): void
{
$user = $this->createNewValidUser();
$group = new CmsGroup();
@@ -52,10 +53,11 @@ class ManyToManyEventTest extends OrmFunctionalTestCase
$user->addGroup($group);
$this->_em->persist($user);
$this->_em->persist($group);
$this->_em->flush();
self::assertFalse($this->listener->wasNotified);
$this->_em->remove($group);
$user->getGroups()->removeElement($group);
$this->_em->flush();
self::assertTrue($this->listener->wasNotified);
@@ -19,6 +19,7 @@ use Doctrine\Tests\Models\CMS\CmsAddress;
use Doctrine\Tests\Models\CMS\CmsEmail;
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
use Doctrine\Tests\Models\CMS\CmsUser;
use Doctrine\Tests\Models\CMS\CmsUserDTO;
use Doctrine\Tests\Models\Company\CompanyContract;
use Doctrine\Tests\Models\Company\CompanyEmployee;
use Doctrine\Tests\Models\Company\CompanyFixContract;
@@ -155,6 +156,77 @@ class NativeQueryTest extends OrmFunctionalTestCase
self::assertSame($phones[0]->getUser(), $users[0]);
}
public function testMappingAsDto(): void
{
$user = new CmsUser();
$user->name = 'Roman';
$user->username = 'romanb';
$user->status = 'dev';
$phone = new CmsPhonenumber();
$phone->phonenumber = 424242;
$user->addPhonenumber($phone);
$email = new CmsEmail();
$email->email = 'fabio.bat.silva@gmail.com';
$user->setEmail($email);
$addr = new CmsAddress();
$addr->country = 'germany';
$addr->zip = 10827;
$addr->city = 'Berlin';
$user->setAddress($addr);
$this->_em->persist($user);
$this->_em->flush();
$this->_em->clear();
$rsm = new ResultSetMapping();
$rsm->addScalarResult('name', 1, 'string');
$rsm->addScalarResult('email', 2, 'string');
$rsm->addScalarResult('city', 3, 'string');
$rsm->newObjectMappings['name'] = [
'className' => CmsUserDTO::class,
'objIndex' => 0,
'argIndex' => 0,
];
$rsm->newObjectMappings['email'] = [
'className' => CmsUserDTO::class,
'objIndex' => 0,
'argIndex' => 1,
];
$rsm->newObjectMappings['city'] = [
'className' => CmsUserDTO::class,
'objIndex' => 0,
'argIndex' => 2,
];
$query = $this->_em->createNativeQuery(
<<<'SQL'
SELECT u.name, e.email, a.city
FROM cms_users u
INNER JOIN cms_phonenumbers p ON u.id = p.user_id
INNER JOIN cms_emails e ON e.id = u.email_id
INNER JOIN cms_addresses a ON u.id = a.user_id
WHERE username = ?
SQL
,
$rsm
);
$query->setParameter(1, 'romanb');
$users = $query->getResult();
self::assertCount(1, $users);
$user = $users[0];
self::assertInstanceOf(CmsUserDTO::class, $user);
self::assertEquals('Roman', $user->name);
self::assertEquals('fabio.bat.silva@gmail.com', $user->email);
self::assertEquals('Berlin', $user->address);
}
public function testJoinedOneToOneNativeQuery(): void
{
$user = new CmsUser();
@@ -13,6 +13,7 @@ use Generator;
use ReflectionMethod;
use function file_get_contents;
use function rtrim;
use function serialize;
use function unserialize;
@@ -56,8 +57,8 @@ class ParserResultSerializationTest extends OrmFunctionalTestCase
/** @return Generator<string, array{string}> */
public static function provideSerializedSingleSelectResults(): Generator
{
yield '2.14.3' => [file_get_contents(__DIR__ . '/ParserResults/single_select_2_14_3.txt')];
yield '2.15.0' => [file_get_contents(__DIR__ . '/ParserResults/single_select_2_15_0.txt')];
yield '2.14.3' => [rtrim(file_get_contents(__DIR__ . '/ParserResults/single_select_2_14_3.txt'), "\n")];
yield '2.15.0' => [rtrim(file_get_contents(__DIR__ . '/ParserResults/single_select_2_15_0.txt'), "\n")];
}
private static function parseQuery(Query $query): ParserResult
@@ -0,0 +1,195 @@
<?php
declare(strict_types=1);
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\Type as DBALType;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\Table;
use Doctrine\Tests\DbalTypes\CustomIdObject;
use Doctrine\Tests\OrmFunctionalTestCase;
use function method_exists;
use function str_replace;
/**
* Functional tests for asserting that orphaned children in a OneToMany relationship get removed with a custom identifier
*
* @group GH10747
*/
final class GH10747Test extends OrmFunctionalTestCase
{
protected function setUp(): void
{
parent::setUp();
if (! DBALType::hasType(GH10747CustomIdObjectHashType::class)) {
DBALType::addType(GH10747CustomIdObjectHashType::class, GH10747CustomIdObjectHashType::class);
}
$this->setUpEntitySchema([GH10747Article::class, GH10747Credit::class]);
}
public function testOrphanedOneToManyDeletesCollection(): void
{
$object = new GH10747Article(
new CustomIdObject('article')
);
$creditOne = new GH10747Credit(
$object,
'credit1'
);
$creditTwo = new GH10747Credit(
$object,
'credit2'
);
$object->setCredits(new ArrayCollection([$creditOne, $creditTwo]));
$this->_em->persist($object);
$this->_em->persist($creditOne);
$this->_em->persist($creditTwo);
$this->_em->flush();
$id = $object->id;
$object2 = $this->_em->find(GH10747Article::class, $id);
$creditThree = new GH10747Credit(
$object2,
'credit3'
);
$object2->setCredits(new ArrayCollection([$creditThree]));
$this->_em->persist($object2);
$this->_em->persist($creditThree);
$this->_em->flush();
$currentDatabaseCredits = $this->_em->createQueryBuilder()
->select('c.id')
->from(GH10747Credit::class, 'c')
->getQuery()
->execute();
self::assertCount(1, $currentDatabaseCredits);
}
}
/**
* @Entity
* @Table
*/
class GH10747Article
{
/**
* @Id
* @Column(type="Doctrine\Tests\ORM\Functional\Ticket\GH10747CustomIdObjectHashType")
* @var CustomIdObject
*/
public $id;
/**
* @ORM\OneToMany(targetEntity="GH10747Credit", mappedBy="article", orphanRemoval=true)
*
* @var Collection<int, GH10747Credit>
*/
public $credits;
public function __construct(CustomIdObject $id)
{
$this->id = $id;
$this->credits = new ArrayCollection();
}
public function setCredits(Collection $credits): void
{
$this->credits = $credits;
}
/** @return Collection<int, GH10747Credit> */
public function getCredits(): Collection
{
return $this->credits;
}
}
/**
* @Entity
* @Table
*/
class GH10747Credit
{
/**
* @ORM\Column(type="integer")
* @ORM\GeneratedValue()
*
* @Id()
* @var int|null
*/
public $id = null;
/** @var string */
public $name;
/**
* @ORM\ManyToOne(targetEntity="GH10747Article", inversedBy="credits")
*
* @var GH10747Article
*/
public $article;
public function __construct(GH10747Article $article, string $name)
{
$this->article = $article;
$this->name = $name;
}
}
class GH10747CustomIdObjectHashType extends DBALType
{
/**
* {@inheritDoc}
*/
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
return $value->id . '_test';
}
/**
* {@inheritDoc}
*/
public function convertToPHPValue($value, AbstractPlatform $platform)
{
return new CustomIdObject(str_replace('_test', '', $value));
}
/**
* {@inheritDoc}
*/
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
if (method_exists($platform, 'getStringTypeDeclarationSQL')) {
return $platform->getStringTypeDeclarationSQL($fieldDeclaration);
}
return $platform->getVarcharTypeDeclarationSQL($fieldDeclaration);
}
/**
* {@inheritDoc}
*/
public function getName()
{
return self::class;
}
}
@@ -0,0 +1,125 @@
<?php
declare(strict_types=1);
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Tests\OrmFunctionalTestCase;
/**
* @group GH10752
*/
class GH10752Test extends OrmFunctionalTestCase
{
protected function setUp(): void
{
parent::setUp();
$this->setUpEntitySchema([
GH10752Order::class,
GH10752Promotion::class,
]);
}
public function testThrowExceptionWhenRemovingPromotionThatIsInUse(): void
{
if (! $this->_em->getConnection()->getDatabasePlatform()->supportsForeignKeyConstraints()) {
self::markTestSkipped('Platform does not support foreign keys.');
}
$order = new GH10752Order();
$promotion = new GH10752Promotion();
$order->addPromotion($promotion);
$this->_em->persist($order);
$this->_em->persist($promotion);
$this->_em->flush();
$this->_em->remove($promotion);
$this->expectException(ForeignKeyConstraintViolationException::class);
$this->_em->flush();
}
public function testThrowExceptionWhenRemovingPromotionThatIsInUseAndOrderIsNotInMemory(): void
{
if (! $this->_em->getConnection()->getDatabasePlatform()->supportsForeignKeyConstraints()) {
self::markTestSkipped('Platform does not support foreign keys.');
}
$order = new GH10752Order();
$promotion = new GH10752Promotion();
$order->addPromotion($promotion);
$this->_em->persist($order);
$this->_em->persist($promotion);
$this->_em->flush();
$this->_em->clear();
$promotion = $this->_em->find(GH10752Promotion::class, $promotion->id);
$this->_em->remove($promotion);
$this->expectException(ForeignKeyConstraintViolationException::class);
$this->_em->flush();
}
}
/**
* @ORM\Entity
*/
class GH10752Order
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*
* @var int
*/
private $id = null;
/**
* @ORM\ManyToMany(targetEntity="GH10752Promotion", cascade={"persist"})
* @ORM\JoinTable(name="order_promotion",
* joinColumns={@ORM\JoinColumn(name="order_id", referencedColumnName="id", onDelete="CASCADE")},
* inverseJoinColumns={@ORM\JoinColumn(name="promotion_id", referencedColumnName="id")}
* )
*
* @var Collection
*/
private $promotions;
public function __construct()
{
$this->promotions = new ArrayCollection();
}
public function addPromotion(GH10752Promotion $promotion): void
{
if (! $this->promotions->contains($promotion)) {
$this->promotions->add($promotion);
}
}
}
/**
* @ORM\Entity
*/
class GH10752Promotion
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*
* @var int
*/
public $id = null;
}
@@ -103,7 +103,7 @@ class GH5804Article
* @Id
* @Column(type="GH5804Type", length=255)
* @GeneratedValue(strategy="CUSTOM")
* @CustomIdGenerator(class=\Doctrine\Tests\ORM\Functional\Ticket\GH5804Generator::class)
* @CustomIdGenerator(class=GH5804Generator::class)
*/
public $id;
@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace Doctrine\Tests\ORM\Functional;
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\Type as DBALType;
@@ -106,7 +106,7 @@ abstract class GH5988CustomIdObjectTypeParent
{
/**
* @Id
* @Column(type="Doctrine\Tests\ORM\Functional\GH5988CustomIdObjectHashType", length=255)
* @Column(type="Doctrine\Tests\ORM\Functional\Ticket\GH5988CustomIdObjectHashType", length=255)
* @var CustomIdObject
*/
public $id;
@@ -15,7 +15,6 @@ use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\InheritanceType;
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\ORM\Mapping\OneToMany;
use Doctrine\ORM\Query;
use Doctrine\ORM\Query\ResultSetMapping;
use Doctrine\Tests\Mocks\ArrayResultFactory;
use Doctrine\Tests\OrmFunctionalTestCase;
@@ -79,7 +78,7 @@ final class GH6362Test extends OrmFunctionalTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->_em);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertInstanceOf(GH6362Start::class, $result[0]['base']);
self::assertInstanceOf(GH6362Child::class, $result[1][0]);
@@ -0,0 +1,88 @@
<?php
declare(strict_types=1);
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\ORM\UnitOfWork;
use Doctrine\Tests\Models\CMS\CmsArticle;
use Doctrine\Tests\Models\CMS\CmsUser;
use Doctrine\Tests\OrmFunctionalTestCase;
use ReflectionClass;
use function spl_object_id;
class GH7407Test extends OrmFunctionalTestCase
{
protected function setUp(): void
{
$this->useModelSet('cms');
parent::setUp();
}
public function testMergingEntitiesDoesNotCreateUnmanagedProxyReferences(): void
{
// 1. Create an article with a user; persist, flush and clear the entity manager
$user = new CmsUser();
$user->username = 'Test';
$user->name = 'Test';
$this->_em->persist($user);
$article = new CmsArticle();
$article->topic = 'Test';
$article->text = 'Test';
$article->setAuthor($user);
$this->_em->persist($article);
$this->_em->flush();
$this->_em->clear();
// 2. Merge the user object back in:
// We get a new (different) entity object that represents the user instance
// which is now (through this object instance) managed by the EM/UoW
$mergedUser = $this->_em->merge($user);
$mergedUserOid = spl_object_id($mergedUser);
// 3. Merge the article object back in,
// the returned entity object is the article instance as it is managed by the EM/UoW
$mergedArticle = $this->_em->merge($article);
$mergedArticleOid = spl_object_id($mergedArticle);
self::assertSame($mergedUser, $mergedArticle->user, 'The $mergedArticle\'s #user property should hold the $mergedUser we obtained previously, since that\'s the only legitimate object instance representing the user from the UoW\'s point of view.');
// Inspect internal UoW state
$uow = $this->_em->getUnitOfWork();
$entityIdentifiers = $this->grabProperty('entityIdentifiers', $uow);
$identityMap = $this->grabProperty('identityMap', $uow);
$entityStates = $this->grabProperty('entityStates', $uow);
self::assertCount(2, $entityIdentifiers, 'UoW#entityIdentifiers contains exactly two OID -> ID value mapping entries one for the article, one for the user object');
self::assertArrayHasKey($mergedArticleOid, $entityIdentifiers);
self::assertArrayHasKey($mergedUserOid, $entityIdentifiers);
self::assertSame([
$mergedUserOid => UnitOfWork::STATE_MANAGED,
$mergedArticleOid => UnitOfWork::STATE_MANAGED,
], $entityStates, 'UoW#entityStates contains two OID -> state entries, one for the article, one for the user object');
self::assertCount(2, $entityIdentifiers);
self::assertArrayHasKey($mergedArticleOid, $entityIdentifiers);
self::assertArrayHasKey($mergedUserOid, $entityIdentifiers);
self::assertSame([
CmsUser::class => [$user->id => $mergedUser],
CmsArticle::class => [$article->id => $mergedArticle],
], $identityMap, 'The identity map contains exactly two objects, the article and the user.');
}
/** @return mixed */
private function grabProperty(string $name, UnitOfWork $uow)
{
$reflection = new ReflectionClass($uow);
$property = $reflection->getProperty($name);
$property->setAccessible(true);
return $property->getValue($uow);
}
}
@@ -8,7 +8,6 @@ use Doctrine\ORM\Internal\Hydration\ObjectHydrator;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\PersistentCollection;
use Doctrine\ORM\Proxy\ProxyFactory;
use Doctrine\ORM\Query;
use Doctrine\ORM\Query\ResultSetMapping;
use Doctrine\Tests\Mocks\ArrayResultFactory;
use Doctrine\Tests\Models\CMS\CmsAddress;
@@ -65,7 +64,7 @@ class ObjectHydratorTest extends HydrationTestCase
}
/**
* SELECT PARTIAL u.{id,name}
* SELECT u
* FROM Doctrine\Tests\Models\CMS\CmsUser u
*/
public function testSimpleEntityQuery(): void
@@ -89,7 +88,7 @@ class ObjectHydratorTest extends HydrationTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->entityManager);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(2, count($result));
@@ -104,7 +103,7 @@ class ObjectHydratorTest extends HydrationTestCase
}
/**
* SELECT PARTIAL u.{id,name} AS user
* SELECT u AS user
* FROM Doctrine\Tests\Models\CMS\CmsUser u
*/
public function testSimpleEntityQueryWithAliasedUserEntity(): void
@@ -128,7 +127,7 @@ class ObjectHydratorTest extends HydrationTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->entityManager);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(2, count($result));
@@ -146,7 +145,7 @@ class ObjectHydratorTest extends HydrationTestCase
}
/**
* SELECT PARTIAL u.{id, name}, PARTIAL a.{id, topic}
* SELECT u, a
* FROM Doctrine\Tests\Models\CMS\CmsUser u, Doctrine\Tests\Models\CMS\CmsArticle a
*/
public function testSimpleMultipleRootEntityQuery(): void
@@ -177,7 +176,7 @@ class ObjectHydratorTest extends HydrationTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->entityManager);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(4, count($result));
@@ -200,7 +199,7 @@ class ObjectHydratorTest extends HydrationTestCase
}
/**
* SELECT PARTIAL u.{id, name} AS user, PARTIAL a.{id, topic}
* SELECT u AS user, a
* FROM Doctrine\Tests\Models\CMS\CmsUser u, Doctrine\Tests\Models\CMS\CmsArticle a
*/
public function testSimpleMultipleRootEntityQueryWithAliasedUserEntity(): void
@@ -231,7 +230,7 @@ class ObjectHydratorTest extends HydrationTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->entityManager);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(4, count($result));
@@ -261,7 +260,7 @@ class ObjectHydratorTest extends HydrationTestCase
}
/**
* SELECT PARTIAL u.{id, name}, PARTIAL a.{id, topic} AS article
* SELECT u, a AS article
* FROM Doctrine\Tests\Models\CMS\CmsUser u, Doctrine\Tests\Models\CMS\CmsArticle a
*/
public function testSimpleMultipleRootEntityQueryWithAliasedArticleEntity(): void
@@ -292,7 +291,7 @@ class ObjectHydratorTest extends HydrationTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->entityManager);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(4, count($result));
@@ -322,7 +321,7 @@ class ObjectHydratorTest extends HydrationTestCase
}
/**
* SELECT PARTIAL u.{id, name} AS user, PARTIAL a.{id, topic} AS article
* SELECT u AS user, a AS article
* FROM Doctrine\Tests\Models\CMS\CmsUser u, Doctrine\Tests\Models\CMS\CmsArticle a
*/
public function testSimpleMultipleRootEntityQueryWithAliasedEntities(): void
@@ -353,7 +352,7 @@ class ObjectHydratorTest extends HydrationTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->entityManager);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(4, count($result));
@@ -383,7 +382,7 @@ class ObjectHydratorTest extends HydrationTestCase
}
/**
* SELECT PARTIAL u.{id, status}, COUNT(p.phonenumber) numPhones
* SELECT u, COUNT(p.phonenumber) numPhones
* FROM User u
* JOIN u.phonenumbers p
* GROUP BY u.id
@@ -415,7 +414,7 @@ class ObjectHydratorTest extends HydrationTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->entityManager);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(2, count($result));
@@ -433,7 +432,7 @@ class ObjectHydratorTest extends HydrationTestCase
}
/**
* SELECT PARTIAL u.{id, status}, PARTIAL p.{phonenumber}, UPPER(u.name) nameUpper
* SELECT u, p, UPPER(u.name) nameUpper
* FROM Doctrine\Tests\Models\CMS\CmsUser u
* JOIN u.phonenumbers p
*
@@ -479,7 +478,7 @@ class ObjectHydratorTest extends HydrationTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->entityManager);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(2, count($result));
@@ -559,7 +558,7 @@ class ObjectHydratorTest extends HydrationTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->entityManager);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(2, count($result));
@@ -673,7 +672,7 @@ class ObjectHydratorTest extends HydrationTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->entityManager);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(2, count($result));
@@ -803,7 +802,7 @@ class ObjectHydratorTest extends HydrationTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->entityManager);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(2, count($result));
@@ -916,7 +915,7 @@ class ObjectHydratorTest extends HydrationTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->entityManager);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(2, count($result));
@@ -936,7 +935,7 @@ class ObjectHydratorTest extends HydrationTestCase
}
/**
* SELECT PARTIAL u.{id,name}
* SELECT u
* FROM Doctrine\Tests\Models\CMS\CmsUser u
*
* @group DDC-644
@@ -959,7 +958,7 @@ class ObjectHydratorTest extends HydrationTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->entityManager);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(1, count($result));
self::assertInstanceOf(CmsUser::class, $result[0]);
@@ -992,7 +991,7 @@ class ObjectHydratorTest extends HydrationTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->entityManager);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(2, count($result));
@@ -1104,7 +1103,7 @@ class ObjectHydratorTest extends HydrationTestCase
}
/**
* SELECT PARTIAL u.{id, status}, PARTIAL a.{id, topic}, PARTIAL c.{id, topic}
* SELECT u, a, c
* FROM Doctrine\Tests\Models\CMS\CmsUser u
* LEFT JOIN u.articles a
* LEFT JOIN a.comments c
@@ -1155,7 +1154,7 @@ class ObjectHydratorTest extends HydrationTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->entityManager);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(2, count($result));
@@ -1167,7 +1166,7 @@ class ObjectHydratorTest extends HydrationTestCase
}
/**
* SELECT PARTIAL u.{id, status} AS user, PARTIAL a.{id, topic}, PARTIAL c.{id, topic}
* SELECT u AS user, a, c
* FROM Doctrine\Tests\Models\CMS\CmsUser u
* LEFT JOIN u.articles a
* LEFT JOIN a.comments c
@@ -1218,7 +1217,7 @@ class ObjectHydratorTest extends HydrationTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->entityManager);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(2, count($result));
@@ -1233,7 +1232,7 @@ class ObjectHydratorTest extends HydrationTestCase
}
/**
* SELECT PARTIAL u.{id, name}
* SELECT u
* FROM Doctrine\Tests\Models\CMS\CmsUser u
*/
public function testResultIteration(): void
@@ -1259,8 +1258,7 @@ class ObjectHydratorTest extends HydrationTestCase
$iterableResult = $hydrator->iterate(
ArrayResultFactory::createFromArray($resultSet),
$rsm,
[Query::HINT_FORCE_PARTIAL_LOAD => true]
$rsm
);
$rowNum = 0;
@@ -1283,8 +1281,7 @@ class ObjectHydratorTest extends HydrationTestCase
$iterableResult = $hydrator->toIterable(
ArrayResultFactory::createFromArray($resultSet),
$rsm,
[Query::HINT_FORCE_PARTIAL_LOAD => true]
$rsm
);
$rowNum = 0;
@@ -1308,7 +1305,7 @@ class ObjectHydratorTest extends HydrationTestCase
}
/**
* SELECT PARTIAL u.{id, name}
* SELECT u
* FROM Doctrine\Tests\Models\CMS\CmsUser u
*/
public function testResultIterationWithAliasedUserEntity(): void
@@ -1334,8 +1331,7 @@ class ObjectHydratorTest extends HydrationTestCase
$rowNum = 0;
$iterableResult = $hydrator->iterate(
ArrayResultFactory::createFromArray($resultSet),
$rsm,
[Query::HINT_FORCE_PARTIAL_LOAD => true]
$rsm
);
while (($row = $iterableResult->next()) !== false) {
@@ -1360,8 +1356,7 @@ class ObjectHydratorTest extends HydrationTestCase
$rowNum = 0;
$iterableResult = $hydrator->toIterable(
ArrayResultFactory::createFromArray($resultSet),
$rsm,
[Query::HINT_FORCE_PARTIAL_LOAD => true]
$rsm
);
foreach ($iterableResult as $row) {
@@ -1388,7 +1383,7 @@ class ObjectHydratorTest extends HydrationTestCase
/**
* Checks if multiple joined multiple-valued collections is hydrated correctly.
*
* SELECT PARTIAL u.{id, status}, PARTIAL g.{id, name}, PARTIAL p.{phonenumber}
* SELECT u, g, p
* FROM Doctrine\Tests\Models\CMS\CmsUser u
*
* @group DDC-809
@@ -1495,7 +1490,7 @@ class ObjectHydratorTest extends HydrationTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->entityManager);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(2, count($result));
@@ -1511,7 +1506,7 @@ class ObjectHydratorTest extends HydrationTestCase
/**
* Checks if multiple joined multiple-valued collections is hydrated correctly.
*
* SELECT PARTIAL u.{id, status} As user, PARTIAL g.{id, name}, PARTIAL p.{phonenumber}
* SELECT u As user, g, p
* FROM Doctrine\Tests\Models\CMS\CmsUser u
*
* @group DDC-809
@@ -1618,7 +1613,7 @@ class ObjectHydratorTest extends HydrationTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->entityManager);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(2, count($result));
@@ -1635,7 +1630,7 @@ class ObjectHydratorTest extends HydrationTestCase
}
/**
* SELECT PARTIAL u.{id, status}, UPPER(u.name) as nameUpper
* SELECT u, UPPER(u.name) as nameUpper
* FROM Doctrine\Tests\Models\CMS\CmsUser u
*
* @group DDC-1358
@@ -1676,7 +1671,7 @@ class ObjectHydratorTest extends HydrationTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->entityManager);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(4, count($result), 'Should hydrate four results.');
@@ -1693,7 +1688,7 @@ class ObjectHydratorTest extends HydrationTestCase
}
/**
* SELECT PARTIAL u.{id, status}, PARTIAL p.{phonenumber}, UPPER(u.name) AS nameUpper
* SELECT u, p, UPPER(u.name) AS nameUpper
* FROM Doctrine\Tests\Models\CMS\CmsUser u
* LEFT JOIN u.phonenumbers u
*
@@ -1746,7 +1741,7 @@ class ObjectHydratorTest extends HydrationTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->entityManager);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(2, count($result));
@@ -1755,7 +1750,7 @@ class ObjectHydratorTest extends HydrationTestCase
}
/**
* SELECT PARTIAL u.{id, status}, PARTIAL a.{id, city}, UPPER(u.name) AS nameUpper
* SELECT u, a, UPPER(u.name) AS nameUpper
* FROM Doctrine\Tests\Models\CMS\CmsUser u
* JOIN u.address a
*
@@ -1800,7 +1795,7 @@ class ObjectHydratorTest extends HydrationTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->entityManager);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(2, count($result));
@@ -1809,7 +1804,7 @@ class ObjectHydratorTest extends HydrationTestCase
}
/**
* SELECT PARTIAL u.{id, status}, UPPER(u.name) AS nameUpper
* SELECT u, UPPER(u.name) AS nameUpper
* FROM Doctrine\Tests\Models\CMS\CmsUser u
* INDEX BY u.id
*
@@ -1842,7 +1837,7 @@ class ObjectHydratorTest extends HydrationTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->entityManager);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(2, count($result));
@@ -1876,7 +1871,7 @@ class ObjectHydratorTest extends HydrationTestCase
$stmt = ArrayResultFactory::createFromArray($resultSet);
$hydrator = new ObjectHydrator($this->entityManager);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$result = $hydrator->hydrateAll($stmt, $rsm);
self::assertEquals(
[
@@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Doctrine\Tests\ORM\Proxy;
use Doctrine\Common\EventManager;
use Doctrine\Common\Proxy\Proxy as CommonProxy;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\ORM\EntityNotFoundException;
@@ -21,6 +20,7 @@ use Doctrine\Tests\Models\Company\CompanyPerson;
use Doctrine\Tests\Models\ECommerce\ECommerceFeature;
use Doctrine\Tests\OrmTestCase;
use Doctrine\Tests\PHPUnitCompatibility\MockBuilderCompatibilityTools;
use Exception;
use ReflectionProperty;
use stdClass;
@@ -145,6 +145,33 @@ class ProxyFactoryTest extends OrmTestCase
self::assertFalse($proxy->__isInitialized());
}
public function testExceptionOnProxyLoadingDoesNotMarkTheProxyAsInitialized(): void
{
$persister = $this
->getMockBuilderWithOnlyMethods(BasicEntityPersister::class, ['load', 'getClassMetadata'])
->disableOriginalConstructor()
->getMock();
$this->uowMock->setEntityPersister(ECommerceFeature::class, $persister);
$proxy = $this->proxyFactory->getProxy(ECommerceFeature::class, ['id' => 42]);
assert($proxy instanceof Proxy);
$exception = new Exception('Literally any kind of connection exception');
$persister
->expects(self::atLeastOnce())
->method('load')
->will(self::throwException($exception));
try {
$proxy->getDescription();
self::fail('An exception was expected to be raised');
} catch (Exception $exception) {
}
self::assertFalse($proxy->__isInitialized(), 'The proxy should not be initialized');
}
/** @group DDC-2432 */
public function testFailedProxyCloningDoesNotMarkTheProxyAsInitialized(): void
{
@@ -199,21 +226,12 @@ class ProxyFactoryTest extends OrmTestCase
->expects(self::atLeastOnce())
->method('loadById');
if ($proxy instanceof CommonProxy) {
$loadByIdMock->willReturn($companyEmployee);
$loadByIdMock->willReturn($companyEmployee);
$persister
->expects(self::atLeastOnce())
->method('getClassMetadata')
->willReturn($classMetaData);
} else {
$loadByIdMock->willReturnCallback(static function (array $id, CompanyEmployee $companyEmployee) {
$companyEmployee->setSalary(1000); // A property on the CompanyEmployee
$companyEmployee->setName('Bob'); // A property on the parent class, CompanyPerson
return $companyEmployee;
});
}
$persister
->expects(self::atLeastOnce())
->method('getClassMetadata')
->willReturn($classMetaData);
$cloned = clone $proxy;
assert($cloned instanceof CompanyEmployee);
@@ -42,7 +42,6 @@ class LanguageRecognitionTest extends OrmTestCase
public function parseDql(string $dql, array $hints = []): ParserResult
{
$query = $this->entityManager->createQuery($dql);
$query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true);
$query->setDQL($dql);
foreach ($hints as $key => $value) {
@@ -32,7 +32,6 @@ use Exception;
use function class_exists;
use function get_class;
use function sprintf;
// DBAL 2 compatibility
class_exists('Doctrine\DBAL\Platforms\MySqlPlatform');
@@ -63,8 +62,7 @@ class SelectSqlGenerationTest extends OrmTestCase
$query->setParameter($name, $value);
}
$query->setHint(ORMQuery::HINT_FORCE_PARTIAL_LOAD, true)
->useQueryCache(false);
$query->useQueryCache(false);
foreach ($queryHints as $name => $value) {
$query->setHint($name, $value);
@@ -74,8 +72,7 @@ class SelectSqlGenerationTest extends OrmTestCase
parent::assertEquals(
$sqlToBeConfirmed,
$sqlGenerated,
sprintf('"%s" is not equal to "%s"', $sqlGenerated, $sqlToBeConfirmed)
$sqlGenerated
);
$query->free();
@@ -98,8 +95,7 @@ class SelectSqlGenerationTest extends OrmTestCase
$query->setParameter($name, $value);
}
$query->setHint(ORMQuery::HINT_FORCE_PARTIAL_LOAD, true)
->useQueryCache(false);
$query->useQueryCache(false);
foreach ($queryHints as $name => $value) {
$query->setHint($name, $value);
@@ -117,8 +113,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT c.id FROM Doctrine\Tests\Models\Company\CompanyPerson c JOIN Doctrine\Tests\Models\Company\CompanyPerson r WHERE c.spouse = r AND r.id = 42',
'SELECT c0_.id AS id_0 FROM company_persons c0_ INNER JOIN company_persons c1_ WHERE c0_.spouse_id = c1_.id AND c1_.id = 42',
[ORMQuery::HINT_FORCE_PARTIAL_LOAD => true]
'SELECT c0_.id AS id_0 FROM company_persons c0_ LEFT JOIN company_managers c1_ ON c0_.id = c1_.id LEFT JOIN company_employees c2_ ON c0_.id = c2_.id INNER JOIN company_persons c3_ LEFT JOIN company_managers c4_ ON c3_.id = c4_.id LEFT JOIN company_employees c5_ ON c3_.id = c5_.id WHERE c0_.spouse_id = c3_.id AND c3_.id = 42'
);
}
@@ -132,8 +127,7 @@ class SelectSqlGenerationTest extends OrmTestCase
*/
$this->assertSqlGeneration(
'SELECT c.id FROM Doctrine\Tests\Models\Company\CompanyPerson c JOIN Doctrine\Tests\Models\Company\CompanyPerson r WHERE c.spouse = r AND r.id = 42',
'SELECT c0_.id AS id_0 FROM company_persons c0_ LEFT JOIN company_managers c1_ ON c0_.id = c1_.id LEFT JOIN company_employees c2_ ON c0_.id = c2_.id INNER JOIN company_persons c3_ LEFT JOIN company_managers c4_ ON c3_.id = c4_.id LEFT JOIN company_employees c5_ ON c3_.id = c5_.id WHERE c0_.spouse_id = c3_.id AND c3_.id = 42',
[ORMQuery::HINT_FORCE_PARTIAL_LOAD => false]
'SELECT c0_.id AS id_0 FROM company_persons c0_ LEFT JOIN company_managers c1_ ON c0_.id = c1_.id LEFT JOIN company_employees c2_ ON c0_.id = c2_.id INNER JOIN company_persons c3_ LEFT JOIN company_managers c4_ ON c3_.id = c4_.id LEFT JOIN company_employees c5_ ON c3_.id = c5_.id WHERE c0_.spouse_id = c3_.id AND c3_.id = 42'
);
}
@@ -141,7 +135,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_'
);
}
@@ -165,7 +159,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT a FROM Doctrine\Tests\Models\CMS\CmsArticle a JOIN a.user u ORDER BY u.name ASC',
'SELECT c0_.id AS id_0, c0_.topic AS topic_1, c0_.text AS text_2, c0_.version AS version_3 FROM cms_articles c0_ INNER JOIN cms_users c1_ ON c0_.user_id = c1_.id ORDER BY c1_.name ASC'
'SELECT c0_.id AS id_0, c0_.topic AS topic_1, c0_.text AS text_2, c0_.version AS version_3, c0_.user_id AS user_id_4 FROM cms_articles c0_ INNER JOIN cms_users c1_ ON c0_.user_id = c1_.id ORDER BY c1_.name ASC'
);
}
@@ -173,7 +167,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE NOT EXISTS (SELECT p.phonenumber FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p WHERE p.phonenumber = 1234)',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE NOT EXISTS (SELECT c1_.phonenumber FROM cms_phonenumbers c1_ WHERE c1_.phonenumber = 1234)'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE NOT EXISTS (SELECT c1_.phonenumber FROM cms_phonenumbers c1_ WHERE c1_.phonenumber = 1234)'
);
}
@@ -189,7 +183,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u, p FROM Doctrine\Tests\Models\CMS\CmsUser u, Doctrine\Tests\Models\CMS\CmsPhonenumber p WHERE u = p.user',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c1_.phonenumber AS phonenumber_4 FROM cms_users c0_, cms_phonenumbers c1_ WHERE c0_.id = c1_.user_id'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c1_.phonenumber AS phonenumber_4, c0_.email_id AS email_id_5, c1_.user_id AS user_id_6 FROM cms_users c0_, cms_phonenumbers c1_ WHERE c0_.id = c1_.user_id'
);
}
@@ -197,7 +191,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u, p FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN Doctrine\Tests\Models\CMS\CmsPhonenumber p WITH u = p.user',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c1_.phonenumber AS phonenumber_4 FROM cms_users c0_ INNER JOIN cms_phonenumbers c1_ ON (c0_.id = c1_.user_id)'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c1_.phonenumber AS phonenumber_4, c0_.email_id AS email_id_5, c1_.user_id AS user_id_6 FROM cms_users c0_ INNER JOIN cms_phonenumbers c1_ ON (c0_.id = c1_.user_id)'
);
}
@@ -205,17 +199,17 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT e FROM Doctrine\Tests\Models\Company\CompanyEmployee e JOIN Doctrine\Tests\Models\Company\CompanyManager m WITH e.id = m.id',
'SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.salary AS salary_2, c1_.department AS department_3, c1_.startDate AS startDate_4, c0_.discr AS discr_5 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id INNER JOIN (company_managers c2_ INNER JOIN company_employees c4_ ON c2_.id = c4_.id INNER JOIN company_persons c3_ ON c2_.id = c3_.id) ON (c0_.id = c3_.id)'
'SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.salary AS salary_2, c1_.department AS department_3, c1_.startDate AS startDate_4, c2_.title AS title_5, c0_.discr AS discr_6, c0_.spouse_id AS spouse_id_7, c2_.car_id AS car_id_8 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id LEFT JOIN company_managers c2_ ON c1_.id = c2_.id INNER JOIN (company_managers c3_ INNER JOIN company_employees c5_ ON c3_.id = c5_.id INNER JOIN company_persons c4_ ON c3_.id = c4_.id) ON (c0_.id = c4_.id)'
);
$this->assertSqlGeneration(
'SELECT e FROM Doctrine\Tests\Models\Company\CompanyEmployee e LEFT JOIN Doctrine\Tests\Models\Company\CompanyManager m WITH e.id = m.id',
'SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.salary AS salary_2, c1_.department AS department_3, c1_.startDate AS startDate_4, c0_.discr AS discr_5 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id LEFT JOIN (company_managers c2_ INNER JOIN company_employees c4_ ON c2_.id = c4_.id INNER JOIN company_persons c3_ ON c2_.id = c3_.id) ON (c0_.id = c3_.id)'
'SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.salary AS salary_2, c1_.department AS department_3, c1_.startDate AS startDate_4, c2_.title AS title_5, c0_.discr AS discr_6, c0_.spouse_id AS spouse_id_7, c2_.car_id AS car_id_8 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id LEFT JOIN company_managers c2_ ON c1_.id = c2_.id LEFT JOIN (company_managers c3_ INNER JOIN company_employees c5_ ON c3_.id = c5_.id INNER JOIN company_persons c4_ ON c3_.id = c4_.id) ON (c0_.id = c4_.id)'
);
$this->assertSqlGeneration(
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c JOIN c.salesPerson s LEFT JOIN Doctrine\Tests\Models\Company\CompanyEvent e WITH s.id = e.id',
'SELECT c0_.id AS id_0, c0_.completed AS completed_1, c0_.fixPrice AS fixPrice_2, c0_.hoursWorked AS hoursWorked_3, c0_.pricePerHour AS pricePerHour_4, c0_.maxPrice AS maxPrice_5, c0_.discr AS discr_6 FROM company_contracts c0_ INNER JOIN company_employees c1_ ON c0_.salesPerson_id = c1_.id LEFT JOIN company_persons c2_ ON c1_.id = c2_.id LEFT JOIN company_events c3_ ON (c2_.id = c3_.id) WHERE c0_.discr IN (\'fix\', \'flexible\', \'flexultra\')'
"SELECT c0_.id AS id_0, c0_.completed AS completed_1, c0_.fixPrice AS fixPrice_2, c0_.hoursWorked AS hoursWorked_3, c0_.pricePerHour AS pricePerHour_4, c0_.maxPrice AS maxPrice_5, c0_.discr AS discr_6, c0_.salesPerson_id AS salesPerson_id_7 FROM company_contracts c0_ INNER JOIN company_employees c1_ ON c0_.salesPerson_id = c1_.id LEFT JOIN company_persons c2_ ON c1_.id = c2_.id LEFT JOIN company_managers c3_ ON c1_.id = c3_.id LEFT JOIN (company_events c4_ LEFT JOIN company_auctions c5_ ON c4_.id = c5_.id LEFT JOIN company_raffles c6_ ON c4_.id = c6_.id) ON (c2_.id = c4_.id) WHERE c0_.discr IN ('fix', 'flexible', 'flexultra')"
);
}
@@ -223,7 +217,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u, p FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.phonenumbers p',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c1_.phonenumber AS phonenumber_4 FROM cms_users c0_ INNER JOIN cms_phonenumbers c1_ ON c0_.id = c1_.user_id'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c1_.phonenumber AS phonenumber_4, c0_.email_id AS email_id_5, c1_.user_id AS user_id_6 FROM cms_users c0_ INNER JOIN cms_phonenumbers c1_ ON c0_.id = c1_.user_id'
);
}
@@ -231,7 +225,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u, a FROM Doctrine\Tests\Models\Forum\ForumUser u JOIN u.avatar a',
'SELECT f0_.id AS id_0, f0_.username AS username_1, f1_.id AS id_2 FROM forum_users f0_ INNER JOIN forum_avatars f1_ ON f0_.avatar_id = f1_.id'
'SELECT f0_.id AS id_0, f0_.username AS username_1, f1_.id AS id_2, f0_.avatar_id AS avatar_id_3 FROM forum_users f0_ INNER JOIN forum_avatars f1_ ON f0_.avatar_id = f1_.id'
);
}
@@ -275,7 +269,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\Forum\ForumUser u ORDER BY u.id',
'SELECT f0_.id AS id_0, f0_.username AS username_1 FROM forum_users f0_ ORDER BY f0_.id ASC'
'SELECT f0_.id AS id_0, f0_.username AS username_1, f0_.avatar_id AS avatar_id_2 FROM forum_users f0_ ORDER BY f0_.id ASC'
);
}
@@ -283,7 +277,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\Forum\ForumUser u ORDER BY u.id asc',
'SELECT f0_.id AS id_0, f0_.username AS username_1 FROM forum_users f0_ ORDER BY f0_.id ASC'
'SELECT f0_.id AS id_0, f0_.username AS username_1, f0_.avatar_id AS avatar_id_2 FROM forum_users f0_ ORDER BY f0_.id ASC'
);
}
@@ -291,7 +285,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\Forum\ForumUser u ORDER BY u.id desc',
'SELECT f0_.id AS id_0, f0_.username AS username_1 FROM forum_users f0_ ORDER BY f0_.id DESC'
'SELECT f0_.id AS id_0, f0_.username AS username_1, f0_.avatar_id AS avatar_id_2 FROM forum_users f0_ ORDER BY f0_.id DESC'
);
}
@@ -299,7 +293,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\Forum\ForumUser u ORDER BY LENGTH(u.username) + LENGTH(u.username) asc',
'SELECT f0_.id AS id_0, f0_.username AS username_1 FROM forum_users f0_ ORDER BY LENGTH(f0_.username) + LENGTH(f0_.username) ASC'
'SELECT f0_.id AS id_0, f0_.username AS username_1, f0_.avatar_id AS avatar_id_2 FROM forum_users f0_ ORDER BY LENGTH(f0_.username) + LENGTH(f0_.username) ASC'
);
}
@@ -347,7 +341,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'select u from Doctrine\Tests\Models\Forum\ForumUser u where u.id = ?1',
'SELECT f0_.id AS id_0, f0_.username AS username_1 FROM forum_users f0_ WHERE f0_.id = ?'
'SELECT f0_.id AS id_0, f0_.username AS username_1, f0_.avatar_id AS avatar_id_2 FROM forum_users f0_ WHERE f0_.id = ?'
);
}
@@ -355,7 +349,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'select u from Doctrine\Tests\Models\Forum\ForumUser u where u.username = :name',
'SELECT f0_.id AS id_0, f0_.username AS username_1 FROM forum_users f0_ WHERE f0_.username = ?'
'SELECT f0_.id AS id_0, f0_.username AS username_1, f0_.avatar_id AS avatar_id_2 FROM forum_users f0_ WHERE f0_.username = ?'
);
}
@@ -363,7 +357,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'select u from Doctrine\Tests\Models\Forum\ForumUser u where u.username = :name and u.username = :name2',
'SELECT f0_.id AS id_0, f0_.username AS username_1 FROM forum_users f0_ WHERE f0_.username = ? AND f0_.username = ?'
'SELECT f0_.id AS id_0, f0_.username AS username_1, f0_.avatar_id AS avatar_id_2 FROM forum_users f0_ WHERE f0_.username = ? AND f0_.username = ?'
);
}
@@ -371,7 +365,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'select u from Doctrine\Tests\Models\Forum\ForumUser u where (u.username = :name OR u.username = :name2) AND u.id = :id',
'SELECT f0_.id AS id_0, f0_.username AS username_1 FROM forum_users f0_ WHERE (f0_.username = ? OR f0_.username = ?) AND f0_.id = ?'
'SELECT f0_.id AS id_0, f0_.username AS username_1, f0_.avatar_id AS avatar_id_2 FROM forum_users f0_ WHERE (f0_.username = ? OR f0_.username = ?) AND f0_.id = ?'
);
}
@@ -396,7 +390,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE ((u.id + 5000) * u.id + 3) < 10000000',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE ((c0_.id + 5000) * c0_.id + 3) < 10000000'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE ((c0_.id + 5000) * c0_.id + 3) < 10000000'
);
}
@@ -404,7 +398,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u, a FROM Doctrine\Tests\Models\CMS\CmsUser u, Doctrine\Tests\Models\CMS\CmsArticle a JOIN a.user u2 WHERE u.id = u2.id',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c1_.id AS id_4, c1_.topic AS topic_5, c1_.text AS text_6, c1_.version AS version_7 FROM cms_users c0_, cms_articles c1_ INNER JOIN cms_users c2_ ON c1_.user_id = c2_.id WHERE c0_.id = c2_.id'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c1_.id AS id_4, c1_.topic AS topic_5, c1_.text AS text_6, c1_.version AS version_7, c0_.email_id AS email_id_8, c1_.user_id AS user_id_9 FROM cms_users c0_, cms_articles c1_ INNER JOIN cms_users c2_ ON c1_.user_id = c2_.id WHERE c0_.id = c2_.id'
);
}
@@ -412,7 +406,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u, a FROM Doctrine\Tests\Models\CMS\CmsUser u, Doctrine\Tests\Models\CMS\CmsArticle a WHERE u.id = a.user',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c1_.id AS id_4, c1_.topic AS topic_5, c1_.text AS text_6, c1_.version AS version_7 FROM cms_users c0_, cms_articles c1_ WHERE c0_.id = c1_.user_id'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c1_.id AS id_4, c1_.topic AS topic_5, c1_.text AS text_6, c1_.version AS version_7, c0_.email_id AS email_id_8, c1_.user_id AS user_id_9 FROM cms_users c0_, cms_articles c1_ WHERE c0_.id = c1_.user_id'
);
}
@@ -433,11 +427,11 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u LEFT JOIN u.articles a WITH a.topic LIKE '%foo%'",
"SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ LEFT JOIN cms_articles c1_ ON c0_.id = c1_.user_id AND (c1_.topic LIKE '%foo%')"
"SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ LEFT JOIN cms_articles c1_ ON c0_.id = c1_.user_id AND (c1_.topic LIKE '%foo%')"
);
$this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u INNER JOIN u.articles a WITH a.topic LIKE '%foo%'",
"SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ INNER JOIN cms_articles c1_ ON c0_.id = c1_.user_id AND (c1_.topic LIKE '%foo%')"
"SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ INNER JOIN cms_articles c1_ ON c0_.id = c1_.user_id AND (c1_.topic LIKE '%foo%')"
);
}
@@ -511,7 +505,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF Doctrine\Tests\Models\Company\CompanyEmployee',
"SELECT c0_.id AS id_0, c0_.name AS name_1, c0_.discr AS discr_2 FROM company_persons c0_ WHERE c0_.discr IN ('manager', 'employee')"
"SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.title AS title_2, c2_.salary AS salary_3, c2_.department AS department_4, c2_.startDate AS startDate_5, c0_.discr AS discr_6, c0_.spouse_id AS spouse_id_7, c1_.car_id AS car_id_8 FROM company_persons c0_ LEFT JOIN company_managers c1_ ON c0_.id = c1_.id LEFT JOIN company_employees c2_ ON c0_.id = c2_.id WHERE c0_.discr IN ('manager', 'employee')"
);
}
@@ -520,7 +514,7 @@ class SelectSqlGenerationTest extends OrmTestCase
// This also uses FQCNs starting with or without a backslash in the INSTANCE OF parameter
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF (Doctrine\Tests\Models\Company\CompanyEmployee, \Doctrine\Tests\Models\Company\CompanyManager)',
"SELECT c0_.id AS id_0, c0_.name AS name_1, c0_.discr AS discr_2 FROM company_persons c0_ WHERE c0_.discr IN ('manager', 'employee')"
"SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.title AS title_2, c2_.salary AS salary_3, c2_.department AS department_4, c2_.startDate AS startDate_5, c0_.discr AS discr_6, c0_.spouse_id AS spouse_id_7, c1_.car_id AS car_id_8 FROM company_persons c0_ LEFT JOIN company_managers c1_ ON c0_.id = c1_.id LEFT JOIN company_employees c2_ ON c0_.id = c2_.id WHERE c0_.discr IN ('manager', 'employee')"
);
}
@@ -529,7 +523,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF \Doctrine\Tests\Models\Company\CompanyEmployee',
"SELECT c0_.id AS id_0, c0_.name AS name_1, c0_.discr AS discr_2 FROM company_persons c0_ WHERE c0_.discr IN ('manager', 'employee')"
"SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.title AS title_2, c2_.salary AS salary_3, c2_.department AS department_4, c2_.startDate AS startDate_5, c0_.discr AS discr_6, c0_.spouse_id AS spouse_id_7, c1_.car_id AS car_id_8 FROM company_persons c0_ LEFT JOIN company_managers c1_ ON c0_.id = c1_.id LEFT JOIN company_employees c2_ ON c0_.id = c2_.id WHERE c0_.discr IN ('manager', 'employee')"
);
}
@@ -546,7 +540,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\Company\CompanyEmployee u WHERE u INSTANCE OF Doctrine\Tests\Models\Company\CompanyManager',
"SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.salary AS salary_2, c1_.department AS department_3, c1_.startDate AS startDate_4, c0_.discr AS discr_5 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id WHERE c0_.discr IN ('manager')"
"SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.salary AS salary_2, c1_.department AS department_3, c1_.startDate AS startDate_4, c2_.title AS title_5, c0_.discr AS discr_6, c0_.spouse_id AS spouse_id_7, c2_.car_id AS car_id_8 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id LEFT JOIN company_managers c2_ ON c1_.id = c2_.id WHERE c0_.discr IN ('manager')"
);
}
@@ -554,7 +548,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\Company\CompanyManager u WHERE u INSTANCE OF Doctrine\Tests\Models\Company\CompanyManager',
"SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.salary AS salary_2, c1_.department AS department_3, c1_.startDate AS startDate_4, c2_.title AS title_5, c0_.discr AS discr_6 FROM company_managers c2_ INNER JOIN company_employees c1_ ON c2_.id = c1_.id INNER JOIN company_persons c0_ ON c2_.id = c0_.id WHERE c0_.discr IN ('manager')"
"SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.salary AS salary_2, c1_.department AS department_3, c1_.startDate AS startDate_4, c2_.title AS title_5, c0_.discr AS discr_6, c0_.spouse_id AS spouse_id_7, c2_.car_id AS car_id_8 FROM company_managers c2_ INNER JOIN company_employees c1_ ON c2_.id = c1_.id INNER JOIN company_persons c0_ ON c2_.id = c0_.id WHERE c0_.discr IN ('manager')"
);
}
@@ -562,7 +556,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF ?1',
'SELECT c0_.id AS id_0, c0_.name AS name_1, c0_.discr AS discr_2 FROM company_persons c0_ WHERE c0_.discr IN (?)',
'SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.title AS title_2, c2_.salary AS salary_3, c2_.department AS department_4, c2_.startDate AS startDate_5, c0_.discr AS discr_6, c0_.spouse_id AS spouse_id_7, c1_.car_id AS car_id_8 FROM company_persons c0_ LEFT JOIN company_managers c1_ ON c0_.id = c1_.id LEFT JOIN company_employees c2_ ON c0_.id = c2_.id WHERE c0_.discr IN (?)',
[],
[1 => $this->entityManager->getClassMetadata(CompanyEmployee::class)]
);
@@ -581,7 +575,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id IN (1, 2)',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE c0_.id IN (1, 2)'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE c0_.id IN (1, 2)'
);
}
@@ -589,7 +583,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE :id NOT IN (1)',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE ? NOT IN (1)'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE ? NOT IN (1)'
);
}
@@ -606,7 +600,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\Forum\ForumUser u WHERE u.avatar IN (?1, ?2)',
'SELECT f0_.id AS id_0, f0_.username AS username_1 FROM forum_users f0_ WHERE f0_.avatar_id IN (?, ?)'
'SELECT f0_.id AS id_0, f0_.username AS username_1, f0_.avatar_id AS avatar_id_2 FROM forum_users f0_ WHERE f0_.avatar_id IN (?, ?)'
);
}
@@ -625,11 +619,11 @@ class SelectSqlGenerationTest extends OrmTestCase
$this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\Forum\ForumUser u WHERE u.username IN (FOO('Lo'), 'Lo', :name)",
"SELECT f0_.id AS id_0, f0_.username AS username_1 FROM forum_users f0_ WHERE f0_.username IN (ABS('Lo'), 'Lo', ?)"
"SELECT f0_.id AS id_0, f0_.username AS username_1, f0_.avatar_id AS avatar_id_2 FROM forum_users f0_ WHERE f0_.username IN (ABS('Lo'), 'Lo', ?)"
);
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\Forum\ForumUser u WHERE u.id IN (1 + 1)',
'SELECT f0_.id AS id_0, f0_.username AS username_1 FROM forum_users f0_ WHERE f0_.id IN (1 + 1)'
'SELECT f0_.id AS id_0, f0_.username AS username_1, f0_.avatar_id AS avatar_id_2 FROM forum_users f0_ WHERE f0_.id IN (1 + 1)'
);
}
@@ -674,7 +668,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE (u.id >= (SELECT u2.id FROM Doctrine\Tests\Models\CMS\CmsUser u2 WHERE u2.name = :name)) AND (u.id <= (SELECT u3.id FROM Doctrine\Tests\Models\CMS\CmsUser u3 WHERE u3.name = :name))',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE (c0_.id >= (SELECT c1_.id FROM cms_users c1_ WHERE c1_.name = ?)) AND (c0_.id <= (SELECT c2_.id FROM cms_users c2_ WHERE c2_.name = ?))'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE (c0_.id >= (SELECT c1_.id FROM cms_users c1_ WHERE c1_.name = ?)) AND (c0_.id <= (SELECT c2_.id FROM cms_users c2_ WHERE c2_.name = ?))'
);
}
@@ -682,7 +676,6 @@ class SelectSqlGenerationTest extends OrmTestCase
{
// "Get all users who have $phone as a phonenumber." (*cough* doesnt really make sense...)
$q = $this->entityManager->createQuery('SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE :param MEMBER OF u.phonenumbers');
$q->setHint(ORMQuery::HINT_FORCE_PARTIAL_LOAD, true);
$phone = new CmsPhonenumber();
$phone->phonenumber = 101;
@@ -698,7 +691,6 @@ class SelectSqlGenerationTest extends OrmTestCase
{
// "Get all users who are members of $group."
$q = $this->entityManager->createQuery('SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE :param MEMBER OF u.groups');
$q->setHint(ORMQuery::HINT_FORCE_PARTIAL_LOAD, true);
$group = new CmsGroup();
$group->id = 101;
@@ -713,7 +705,6 @@ class SelectSqlGenerationTest extends OrmTestCase
public function testSupportsMemberOfExpressionManyToManyParameterArray(): void
{
$q = $this->entityManager->createQuery('SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE :param MEMBER OF u.groups');
$q->setHint(ORMQuery::HINT_FORCE_PARTIAL_LOAD, true);
$group = new CmsGroup();
$group->id = 101;
@@ -766,21 +757,18 @@ class SelectSqlGenerationTest extends OrmTestCase
public function testSupportsCurrentDateFunction(): void
{
$q = $this->entityManager->createQuery('SELECT d.id FROM Doctrine\Tests\Models\Generic\DateTimeModel d WHERE d.datetime > current_date()');
$q->setHint(ORMQuery::HINT_FORCE_PARTIAL_LOAD, true);
self::assertEquals('SELECT d0_.id AS id_0 FROM date_time_model d0_ WHERE d0_.col_datetime > CURRENT_DATE', $q->getSql());
}
public function testSupportsCurrentTimeFunction(): void
{
$q = $this->entityManager->createQuery('SELECT d.id FROM Doctrine\Tests\Models\Generic\DateTimeModel d WHERE d.time > current_time()');
$q->setHint(ORMQuery::HINT_FORCE_PARTIAL_LOAD, true);
self::assertEquals('SELECT d0_.id AS id_0 FROM date_time_model d0_ WHERE d0_.col_time > CURRENT_TIME', $q->getSql());
}
public function testSupportsCurrentTimestampFunction(): void
{
$q = $this->entityManager->createQuery('SELECT d.id FROM Doctrine\Tests\Models\Generic\DateTimeModel d WHERE d.datetime > current_timestamp()');
$q->setHint(ORMQuery::HINT_FORCE_PARTIAL_LOAD, true);
self::assertEquals('SELECT d0_.id AS id_0 FROM date_time_model d0_ WHERE d0_.col_datetime > CURRENT_TIMESTAMP', $q->getSql());
}
@@ -795,10 +783,7 @@ class SelectSqlGenerationTest extends OrmTestCase
FROM Doctrine\Tests\Models\CMS\CmsEmployee spouseEmp
WHERE spouseEmp = emp.spouse)',
// SQL
'SELECT DISTINCT c0_.id AS id_0, c0_.name AS name_1 FROM cms_employees c0_'
. ' WHERE EXISTS ('
. 'SELECT c1_.id FROM cms_employees c1_ WHERE c1_.id = c0_.spouse_id'
. ')'
'SELECT DISTINCT c0_.id AS id_0, c0_.name AS name_1, c0_.spouse_id AS spouse_id_2 FROM cms_employees c0_ WHERE EXISTS (SELECT c1_.id FROM cms_employees c1_ WHERE c1_.id = c0_.spouse_id)'
);
}
@@ -813,10 +798,7 @@ class SelectSqlGenerationTest extends OrmTestCase
FROM Doctrine\Tests\Models\CMS\CmsEmployee spouseEmp
WHERE spouseEmp = emp.spouse)',
// SQL
'SELECT DISTINCT c0_.id AS id_0, c0_.name AS name_1 FROM cms_employees c0_'
. ' WHERE EXISTS ('
. 'SELECT 1 AS sclr_2 FROM cms_employees c1_ WHERE c1_.id = c0_.spouse_id'
. ')'
'SELECT DISTINCT c0_.id AS id_0, c0_.name AS name_1, c0_.spouse_id AS spouse_id_2 FROM cms_employees c0_ WHERE EXISTS (SELECT 1 AS sclr_3 FROM cms_employees c1_ WHERE c1_.id = c0_.spouse_id)'
);
}
@@ -850,7 +832,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE SIZE(u.phonenumbers) > 1',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE (SELECT COUNT(*) FROM cms_phonenumbers c1_ WHERE c1_.user_id = c0_.id) > 1'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE (SELECT COUNT(*) FROM cms_phonenumbers c1_ WHERE c1_.user_id = c0_.id) > 1'
);
}
@@ -858,7 +840,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE SIZE(u.groups) > 1',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE (SELECT COUNT(*) FROM cms_users_groups c1_ WHERE c1_.user_id = c0_.id) > 1'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE (SELECT COUNT(*) FROM cms_users_groups c1_ WHERE c1_.user_id = c0_.id) > 1'
);
}
@@ -866,11 +848,11 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.phonenumbers IS EMPTY',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE (SELECT COUNT(*) FROM cms_phonenumbers c1_ WHERE c1_.user_id = c0_.id) = 0'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE (SELECT COUNT(*) FROM cms_phonenumbers c1_ WHERE c1_.user_id = c0_.id) = 0'
);
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.phonenumbers IS NOT EMPTY',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE (SELECT COUNT(*) FROM cms_phonenumbers c1_ WHERE c1_.user_id = c0_.id) > 0'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE (SELECT COUNT(*) FROM cms_phonenumbers c1_ WHERE c1_.user_id = c0_.id) > 0'
);
}
@@ -878,7 +860,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'select u from Doctrine\Tests\Models\CMS\CmsUser u where u.id > 10 and u.id < 42 and ((u.id * 2) > 5)',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE c0_.id > 10 AND c0_.id < 42 AND ((c0_.id * 2) > 5)'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE c0_.id > 10 AND c0_.id < 42 AND ((c0_.id * 2) > 5)'
);
}
@@ -886,7 +868,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'select u from Doctrine\Tests\Models\CMS\CmsUser u where (u.id > 10) and (u.id < 42 and ((u.id * 2) > 5)) or u.id <> 42',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE (c0_.id > 10) AND (c0_.id < 42 AND ((c0_.id * 2) > 5)) OR c0_.id <> 42'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE (c0_.id > 10) AND (c0_.id < 42 AND ((c0_.id * 2) > 5)) OR c0_.id <> 42'
);
}
@@ -894,7 +876,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'select u from Doctrine\Tests\Models\CMS\CmsUser u where (u.id > 10) and (u.id between 1 and 10 or u.id in (1, 2, 3, 4, 5))',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE (c0_.id > 10) AND (c0_.id BETWEEN 1 AND 10 OR c0_.id IN (1, 2, 3, 4, 5))'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE (c0_.id > 10) AND (c0_.id BETWEEN 1 AND 10 OR c0_.id IN (1, 2, 3, 4, 5))'
);
}
@@ -902,7 +884,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'select u, size(u.articles) as numArticles from Doctrine\Tests\Models\CMS\CmsUser u order by numArticles',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, (SELECT COUNT(*) FROM cms_articles c1_ WHERE c1_.user_id = c0_.id) AS sclr_4 FROM cms_users c0_ ORDER BY sclr_4 ASC'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, (SELECT COUNT(*) FROM cms_articles c1_ WHERE c1_.user_id = c0_.id) AS sclr_4, c0_.email_id AS email_id_5 FROM cms_users c0_ ORDER BY sclr_4 ASC'
);
}
@@ -910,7 +892,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'select a from Doctrine\Tests\Models\CMS\CmsArticle a order by a.user',
'SELECT c0_.id AS id_0, c0_.topic AS topic_1, c0_.text AS text_2, c0_.version AS version_3 FROM cms_articles c0_ ORDER BY c0_.user_id ASC'
'SELECT c0_.id AS id_0, c0_.topic AS topic_1, c0_.text AS text_2, c0_.version AS version_3, c0_.user_id AS user_id_4 FROM cms_articles c0_ ORDER BY c0_.user_id ASC'
);
}
@@ -961,7 +943,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT p FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p WHERE p.user = ?1',
'SELECT c0_.phonenumber AS phonenumber_0 FROM cms_phonenumbers c0_ WHERE c0_.user_id = ?'
'SELECT c0_.phonenumber AS phonenumber_0, c0_.user_id AS user_id_1 FROM cms_phonenumbers c0_ WHERE c0_.user_id = ?'
);
}
@@ -969,7 +951,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT a FROM Doctrine\Tests\Models\CMS\CmsAddress a WHERE a.user IS NULL',
'SELECT c0_.id AS id_0, c0_.country AS country_1, c0_.zip AS zip_2, c0_.city AS city_3 FROM cms_addresses c0_ WHERE c0_.user_id IS NULL'
'SELECT c0_.id AS id_0, c0_.country AS country_1, c0_.zip AS zip_2, c0_.city AS city_3, c0_.user_id AS user_id_4 FROM cms_addresses c0_ WHERE c0_.user_id IS NULL'
);
}
@@ -982,7 +964,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u LEFT JOIN u.address a WHERE a.id IS NULL',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ LEFT JOIN cms_addresses c1_ ON c0_.id = c1_.user_id WHERE c1_.id IS NULL'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ LEFT JOIN cms_addresses c1_ ON c0_.id = c1_.user_id WHERE c1_.id IS NULL'
);
}
@@ -1016,7 +998,7 @@ class SelectSqlGenerationTest extends OrmTestCase
);
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u LEFT JOIN u.articles a WITH a.topic LIKE u.name',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ LEFT JOIN cms_articles c1_ ON c0_.id = c1_.user_id AND (c1_.topic LIKE c0_.name)'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ LEFT JOIN cms_articles c1_ ON c0_.id = c1_.user_id AND (c1_.topic LIKE c0_.name)'
);
}
@@ -1034,7 +1016,7 @@ class SelectSqlGenerationTest extends OrmTestCase
);
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u LEFT JOIN u.articles a WITH a.topic NOT LIKE u.name',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ LEFT JOIN cms_articles c1_ ON c0_.id = c1_.user_id AND (c1_.topic NOT LIKE c0_.name)'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ LEFT JOIN cms_articles c1_ ON c0_.id = c1_.user_id AND (c1_.topic NOT LIKE c0_.name)'
);
}
@@ -1043,8 +1025,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT r, l FROM Doctrine\Tests\Models\Routing\RoutingRoute r JOIN r.legs l',
'SELECT r0_.id AS id_0, r1_.id AS id_1, r1_.departureDate AS departureDate_2, r1_.arrivalDate AS arrivalDate_3 FROM RoutingRoute r0_ INNER JOIN RoutingRouteLegs r2_ ON r0_.id = r2_.route_id INNER JOIN RoutingLeg r1_ ON r1_.id = r2_.leg_id ' .
'ORDER BY r1_.departureDate ASC'
'SELECT r0_.id AS id_0, r1_.id AS id_1, r1_.departureDate AS departureDate_2, r1_.arrivalDate AS arrivalDate_3, r1_.from_id AS from_id_4, r1_.to_id AS to_id_5 FROM RoutingRoute r0_ INNER JOIN RoutingRouteLegs r2_ ON r0_.id = r2_.route_id INNER JOIN RoutingLeg r1_ ON r1_.id = r2_.leg_id ORDER BY r1_.departureDate ASC'
);
}
@@ -1068,8 +1049,7 @@ class SelectSqlGenerationTest extends OrmTestCase
$this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.username = 'gblanco'",
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 ' .
"FROM cms_users c0_ WHERE c0_.username = 'gblanco' FOR UPDATE",
"SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE c0_.username = 'gblanco' FOR UPDATE",
[ORMQuery::HINT_LOCK_MODE => LockMode::PESSIMISTIC_WRITE]
);
}
@@ -1084,8 +1064,7 @@ class SelectSqlGenerationTest extends OrmTestCase
$this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.username = 'gblanco'",
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 ' .
"FROM cms_users c0_ WHERE c0_.username = 'gblanco' FOR SHARE",
"SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE c0_.username = 'gblanco' FOR SHARE",
[ORMQuery::HINT_LOCK_MODE => LockMode::PESSIMISTIC_READ]
);
}
@@ -1098,8 +1077,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.username = 'gblanco'",
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 ' .
"FROM cms_users c0_ WHERE c0_.username = 'gblanco'",
"SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE c0_.username = 'gblanco'",
[ORMQuery::HINT_LOCK_MODE => LockMode::NONE]
);
}
@@ -1109,7 +1087,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = ?1 OR u.id = ?2 OR u.id = ?3 OR u.id = ?4 OR u.id = ?5 OR u.id = ?6 OR u.id = ?7 OR u.id = ?8 OR u.id = ?9 OR u.id = ?10 OR u.id = ?11',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ?'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ?'
);
}
@@ -1123,8 +1101,7 @@ class SelectSqlGenerationTest extends OrmTestCase
$this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.username = 'gblanco'",
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 ' .
"FROM cms_users c0_ WHERE c0_.username = 'gblanco' LOCK IN SHARE MODE",
"SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE c0_.username = 'gblanco' LOCK IN SHARE MODE",
[ORMQuery::HINT_LOCK_MODE => LockMode::PESSIMISTIC_READ]
);
}
@@ -1139,8 +1116,7 @@ class SelectSqlGenerationTest extends OrmTestCase
$this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.username = 'gblanco'",
'SELECT c0_.id AS ID_0, c0_.status AS STATUS_1, c0_.username AS USERNAME_2, c0_.name AS NAME_3 ' .
"FROM cms_users c0_ WHERE c0_.username = 'gblanco' FOR UPDATE",
"SELECT c0_.id AS ID_0, c0_.status AS STATUS_1, c0_.username AS USERNAME_2, c0_.name AS NAME_3, c0_.email_id AS EMAIL_ID_4 FROM cms_users c0_ WHERE c0_.username = 'gblanco' FOR UPDATE",
[ORMQuery::HINT_LOCK_MODE => LockMode::PESSIMISTIC_READ]
);
}
@@ -1164,7 +1140,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT f FROM Doctrine\Tests\Models\DirectoryTree\File f JOIN f.parentDirectory d WHERE f.id = ?1',
'SELECT f0_.id AS id_0, f0_.extension AS extension_1, f0_.name AS name_2 FROM "file" f0_ INNER JOIN Directory d1_ ON f0_.parentDirectory_id = d1_.id WHERE f0_.id = ?'
'SELECT f0_.id AS id_0, f0_.extension AS extension_1, f0_.name AS name_2, f0_.parentDirectory_id AS parentDirectory_id_3 FROM "file" f0_ INNER JOIN Directory d1_ ON f0_.parentDirectory_id = d1_.id WHERE f0_.id = ?'
);
}
@@ -1232,7 +1208,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT uo, (SELECT ui.name FROM Doctrine\Tests\Models\CMS\CmsUser ui WHERE ui.id = uo.id) AS bar FROM Doctrine\Tests\Models\CMS\CmsUser uo',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, (SELECT c1_.name FROM cms_users c1_ WHERE c1_.id = c0_.id) AS sclr_4 FROM cms_users c0_'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, (SELECT c1_.name FROM cms_users c1_ WHERE c1_.id = c0_.id) AS sclr_4, c0_.email_id AS email_id_5 FROM cms_users c0_'
);
}
@@ -1240,7 +1216,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT uo, (SELECT ui.name FROM Doctrine\Tests\Models\CMS\CmsUser ui WHERE ui.id = uo.id AND ui.name IN (SELECT uii.name FROM Doctrine\Tests\Models\CMS\CmsUser uii)) AS bar FROM Doctrine\Tests\Models\CMS\CmsUser uo',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, (SELECT c1_.name FROM cms_users c1_ WHERE c1_.id = c0_.id AND c1_.name IN (SELECT c2_.name FROM cms_users c2_)) AS sclr_4 FROM cms_users c0_'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, (SELECT c1_.name FROM cms_users c1_ WHERE c1_.id = c0_.id AND c1_.name IN (SELECT c2_.name FROM cms_users c2_)) AS sclr_4, c0_.email_id AS email_id_5 FROM cms_users c0_'
);
}
@@ -1248,7 +1224,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT uo, (SELECT ui.name FROM Doctrine\Tests\Models\CMS\CmsUser ui WHERE ui.id = uo.id) AS bar FROM Doctrine\Tests\Models\CMS\CmsUser uo WHERE bar = ?0',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, (SELECT c1_.name FROM cms_users c1_ WHERE c1_.id = c0_.id) AS sclr_4 FROM cms_users c0_ WHERE sclr_4 = ?'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, (SELECT c1_.name FROM cms_users c1_ WHERE c1_.id = c0_.id) AS sclr_4, c0_.email_id AS email_id_5 FROM cms_users c0_ WHERE sclr_4 = ?'
);
}
@@ -1414,13 +1390,13 @@ class SelectSqlGenerationTest extends OrmTestCase
//relation is in the subclass (CompanyManager) we are querying
$this->assertSqlGeneration(
'SELECT m, IDENTITY(m.car) as car_id FROM Doctrine\Tests\Models\Company\CompanyManager m',
'SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.salary AS salary_2, c1_.department AS department_3, c1_.startDate AS startDate_4, c2_.title AS title_5, c2_.car_id AS sclr_6, c0_.discr AS discr_7 FROM company_managers c2_ INNER JOIN company_employees c1_ ON c2_.id = c1_.id INNER JOIN company_persons c0_ ON c2_.id = c0_.id'
'SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.salary AS salary_2, c1_.department AS department_3, c1_.startDate AS startDate_4, c2_.title AS title_5, c2_.car_id AS sclr_6, c0_.discr AS discr_7, c0_.spouse_id AS spouse_id_8, c2_.car_id AS car_id_9 FROM company_managers c2_ INNER JOIN company_employees c1_ ON c2_.id = c1_.id INNER JOIN company_persons c0_ ON c2_.id = c0_.id'
);
//relation is in the base class (CompanyPerson).
$this->assertSqlGeneration(
'SELECT m, IDENTITY(m.spouse) as spouse_id FROM Doctrine\Tests\Models\Company\CompanyManager m',
'SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.salary AS salary_2, c1_.department AS department_3, c1_.startDate AS startDate_4, c2_.title AS title_5, c0_.spouse_id AS sclr_6, c0_.discr AS discr_7 FROM company_managers c2_ INNER JOIN company_employees c1_ ON c2_.id = c1_.id INNER JOIN company_persons c0_ ON c2_.id = c0_.id'
'SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.salary AS salary_2, c1_.department AS department_3, c1_.startDate AS startDate_4, c2_.title AS title_5, c0_.spouse_id AS sclr_6, c0_.discr AS discr_7, c0_.spouse_id AS spouse_id_8, c2_.car_id AS car_id_9 FROM company_managers c2_ INNER JOIN company_employees c1_ ON c2_.id = c1_.id INNER JOIN company_persons c0_ ON c2_.id = c0_.id'
);
}
@@ -1558,8 +1534,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT p, pp FROM Doctrine\Tests\Models\Company\CompanyPerson p JOIN p.spouse pp',
'SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.title AS title_2, c2_.salary AS salary_3, c2_.department AS department_4, c2_.startDate AS startDate_5, c3_.id AS id_6, c3_.name AS name_7, c4_.title AS title_8, c5_.salary AS salary_9, c5_.department AS department_10, c5_.startDate AS startDate_11, c0_.discr AS discr_12, c0_.spouse_id AS spouse_id_13, c1_.car_id AS car_id_14, c3_.discr AS discr_15, c3_.spouse_id AS spouse_id_16, c4_.car_id AS car_id_17 FROM company_persons c0_ LEFT JOIN company_managers c1_ ON c0_.id = c1_.id LEFT JOIN company_employees c2_ ON c0_.id = c2_.id INNER JOIN company_persons c3_ ON c0_.spouse_id = c3_.id LEFT JOIN company_managers c4_ ON c3_.id = c4_.id LEFT JOIN company_employees c5_ ON c3_.id = c5_.id',
[ORMQuery::HINT_FORCE_PARTIAL_LOAD => false]
'SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.title AS title_2, c2_.salary AS salary_3, c2_.department AS department_4, c2_.startDate AS startDate_5, c3_.id AS id_6, c3_.name AS name_7, c4_.title AS title_8, c5_.salary AS salary_9, c5_.department AS department_10, c5_.startDate AS startDate_11, c0_.discr AS discr_12, c0_.spouse_id AS spouse_id_13, c1_.car_id AS car_id_14, c3_.discr AS discr_15, c3_.spouse_id AS spouse_id_16, c4_.car_id AS car_id_17 FROM company_persons c0_ LEFT JOIN company_managers c1_ ON c0_.id = c1_.id LEFT JOIN company_employees c2_ ON c0_.id = c2_.id INNER JOIN company_persons c3_ ON c0_.spouse_id = c3_.id LEFT JOIN company_managers c4_ ON c3_.id = c4_.id LEFT JOIN company_employees c5_ ON c3_.id = c5_.id'
);
}
@@ -1580,7 +1555,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT e.name FROM Doctrine\Tests\Models\Company\CompanyEmployee e',
'SELECT c0_.name AS name_0 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id'
'SELECT c0_.name AS name_0 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id LEFT JOIN company_managers c2_ ON c1_.id = c2_.id'
);
}
@@ -1612,12 +1587,12 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u GROUP BY u',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ GROUP BY c0_.id, c0_.status, c0_.username, c0_.name, c0_.email_id'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ GROUP BY c0_.id, c0_.status, c0_.username, c0_.name, c0_.email_id'
);
$this->assertSqlGeneration(
'SELECT e FROM Doctrine\Tests\Models\CMS\CmsEmployee e GROUP BY e',
'SELECT c0_.id AS id_0, c0_.name AS name_1 FROM cms_employees c0_ GROUP BY c0_.id, c0_.name, c0_.spouse_id'
'SELECT c0_.id AS id_0, c0_.name AS name_1, c0_.spouse_id AS spouse_id_2 FROM cms_employees c0_ GROUP BY c0_.id, c0_.name, c0_.spouse_id'
);
}
@@ -1626,7 +1601,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u, u.status AS st FROM Doctrine\Tests\Models\CMS\CmsUser u GROUP BY st',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.status AS status_4 FROM cms_users c0_ GROUP BY c0_.status'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.status AS status_4, c0_.email_id AS email_id_5 FROM cms_users c0_ GROUP BY c0_.status'
);
}
@@ -1635,7 +1610,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u AS user FROM Doctrine\Tests\Models\CMS\CmsUser u GROUP BY user',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ GROUP BY id_0, status_1, username_2, name_3'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ GROUP BY id_0, status_1, username_2, name_3'
);
}
@@ -1644,7 +1619,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT BIT_OR(4,2), BIT_AND(4,2), u FROM Doctrine\Tests\Models\CMS\CmsUser u',
'SELECT (4 | 2) AS sclr_0, (4 & 2) AS sclr_1, c0_.id AS id_2, c0_.status AS status_3, c0_.username AS username_4, c0_.name AS name_5 FROM cms_users c0_'
'SELECT (4 | 2) AS sclr_0, (4 & 2) AS sclr_1, c0_.id AS id_2, c0_.status AS status_3, c0_.username AS username_4, c0_.name AS name_5, c0_.email_id AS email_id_6 FROM cms_users c0_'
);
$this->assertSqlGeneration(
'SELECT BIT_OR(u.id,2), BIT_AND(u.id,2) FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE BIT_OR(u.id,2) > 0',
@@ -1665,15 +1640,15 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u where ( (u.id + u.id) * u.id ) > 100',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE ((c0_.id + c0_.id) * c0_.id) > 100'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE ((c0_.id + c0_.id) * c0_.id) > 100'
);
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u where (u.id + u.id) * u.id > 100',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE (c0_.id + c0_.id) * c0_.id > 100'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE (c0_.id + c0_.id) * c0_.id > 100'
);
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u where 100 < (u.id + u.id) * u.id ',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE 100 < (c0_.id + c0_.id) * c0_.id'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE 100 < (c0_.id + c0_.id) * c0_.id'
);
}
@@ -1690,27 +1665,27 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u1 FROM Doctrine\Tests\Models\CMS\CmsUser u1 WHERE u1.name IN ( SELECT TRIM(u2.name) FROM Doctrine\Tests\Models\CMS\CmsUser u2 )',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE c0_.name IN (SELECT TRIM(c1_.name) AS sclr_4 FROM cms_users c1_)'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE c0_.name IN (SELECT TRIM(c1_.name) AS sclr_5 FROM cms_users c1_)'
);
$this->assertSqlGeneration(
'SELECT u1 FROM Doctrine\Tests\Models\CMS\CmsUser u1 WHERE u1.name IN ( SELECT TRIM(u2.name) FROM Doctrine\Tests\Models\CMS\CmsUser u2 WHERE LOWER(u2.name) LIKE \'%fabio%\')',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE c0_.name IN (SELECT TRIM(c1_.name) AS sclr_4 FROM cms_users c1_ WHERE LOWER(c1_.name) LIKE \'%fabio%\')'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE c0_.name IN (SELECT TRIM(c1_.name) AS sclr_5 FROM cms_users c1_ WHERE LOWER(c1_.name) LIKE \'%fabio%\')'
);
$this->assertSqlGeneration(
'SELECT u1 FROM Doctrine\Tests\Models\CMS\CmsUser u1 WHERE u1.email IN ( SELECT TRIM(IDENTITY(u2.email)) FROM Doctrine\Tests\Models\CMS\CmsUser u2 )',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE c0_.email_id IN (SELECT TRIM(c1_.email_id) AS sclr_4 FROM cms_users c1_)'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE c0_.email_id IN (SELECT TRIM(c1_.email_id) AS sclr_5 FROM cms_users c1_)'
);
$this->assertSqlGeneration(
'SELECT u1 FROM Doctrine\Tests\Models\CMS\CmsUser u1 WHERE u1.email IN ( SELECT IDENTITY(u2.email) FROM Doctrine\Tests\Models\CMS\CmsUser u2 )',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE c0_.email_id IN (SELECT c1_.email_id AS sclr_4 FROM cms_users c1_)'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE c0_.email_id IN (SELECT c1_.email_id AS sclr_5 FROM cms_users c1_)'
);
$this->assertSqlGeneration(
'SELECT u1 FROM Doctrine\Tests\Models\CMS\CmsUser u1 WHERE COUNT(u1.id) = ( SELECT SUM(u2.id) FROM Doctrine\Tests\Models\CMS\CmsUser u2 )',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE COUNT(c0_.id) = (SELECT SUM(c1_.id) AS sclr_4 FROM cms_users c1_)'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE COUNT(c0_.id) = (SELECT SUM(c1_.id) AS sclr_5 FROM cms_users c1_)'
);
$this->assertSqlGeneration(
'SELECT u1 FROM Doctrine\Tests\Models\CMS\CmsUser u1 WHERE COUNT(u1.id) <= ( SELECT SUM(u2.id) + COUNT(u2.email) FROM Doctrine\Tests\Models\CMS\CmsUser u2 )',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE COUNT(c0_.id) <= (SELECT SUM(c1_.id) + COUNT(c1_.email_id) AS sclr_4 FROM cms_users c1_)'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE COUNT(c0_.id) <= (SELECT SUM(c1_.id) + COUNT(c1_.email_id) AS sclr_5 FROM cms_users c1_)'
);
}
@@ -1753,37 +1728,37 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE IDENTITY(u.email) IS NULL',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE c0_.email_id IS NULL'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE c0_.email_id IS NULL'
);
$this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE NULLIF(u.name, 'FabioBatSilva') IS NULL AND IDENTITY(u.email) IS NOT NULL",
"SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE NULLIF(c0_.name, 'FabioBatSilva') IS NULL AND c0_.email_id IS NOT NULL"
"SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE NULLIF(c0_.name, 'FabioBatSilva') IS NULL AND c0_.email_id IS NOT NULL"
);
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE IDENTITY(u.email) IS NOT NULL',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE c0_.email_id IS NOT NULL'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE c0_.email_id IS NOT NULL'
);
$this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE NULLIF(u.name, 'FabioBatSilva') IS NOT NULL",
"SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE NULLIF(c0_.name, 'FabioBatSilva') IS NOT NULL"
"SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE NULLIF(c0_.name, 'FabioBatSilva') IS NOT NULL"
);
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE COALESCE(u.name, u.id) IS NOT NULL',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE COALESCE(c0_.name, c0_.id) IS NOT NULL'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE COALESCE(c0_.name, c0_.id) IS NOT NULL'
);
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE COALESCE(u.id, IDENTITY(u.email)) IS NOT NULL',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE COALESCE(c0_.id, c0_.email_id) IS NOT NULL'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE COALESCE(c0_.id, c0_.email_id) IS NOT NULL'
);
$this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE COALESCE(IDENTITY(u.email), NULLIF(u.name, 'FabioBatSilva')) IS NOT NULL",
"SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ WHERE COALESCE(c0_.email_id, NULLIF(c0_.name, 'FabioBatSilva')) IS NOT NULL"
"SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ WHERE COALESCE(c0_.email_id, NULLIF(c0_.name, 'FabioBatSilva')) IS NOT NULL"
);
}
@@ -1825,7 +1800,7 @@ class SelectSqlGenerationTest extends OrmTestCase
$this->assertSqlGeneration(
'SELECT p FROM Doctrine\Tests\Models\CustomType\CustomTypeParent p',
'SELECT c0_.id AS id_0, -(c0_.customInteger) AS customInteger_1 FROM customtype_parents c0_'
'SELECT c0_.id AS id_0, -(c0_.customInteger) AS customInteger_1, c0_.child_id AS child_id_2 FROM customtype_parents c0_'
);
}
@@ -1839,7 +1814,7 @@ class SelectSqlGenerationTest extends OrmTestCase
$this->assertSqlGeneration(
'SELECT partial p.{id, customInteger} FROM Doctrine\Tests\Models\CustomType\CustomTypeParent p',
'SELECT c0_.id AS id_0, -(c0_.customInteger) AS customInteger_1 FROM customtype_parents c0_'
'SELECT c0_.id AS id_0, -(c0_.customInteger) AS customInteger_1, c0_.child_id AS child_id_2 FROM customtype_parents c0_'
);
}
@@ -1848,7 +1823,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT fix, flex FROM Doctrine\Tests\Models\Company\CompanyFixContract fix, Doctrine\Tests\Models\Company\CompanyFlexContract flex',
"SELECT c0_.id AS id_0, c0_.completed AS completed_1, c0_.fixPrice AS fixPrice_2, c1_.id AS id_3, c1_.completed AS completed_4, c1_.hoursWorked AS hoursWorked_5, c1_.pricePerHour AS pricePerHour_6, c1_.maxPrice AS maxPrice_7, c0_.discr AS discr_8, c1_.discr AS discr_9 FROM company_contracts c0_, company_contracts c1_ WHERE (c0_.discr IN ('fix') AND c1_.discr IN ('flexible', 'flexultra'))"
"SELECT c0_.id AS id_0, c0_.completed AS completed_1, c0_.fixPrice AS fixPrice_2, c1_.id AS id_3, c1_.completed AS completed_4, c1_.hoursWorked AS hoursWorked_5, c1_.pricePerHour AS pricePerHour_6, c1_.maxPrice AS maxPrice_7, c0_.discr AS discr_8, c0_.salesPerson_id AS salesPerson_id_9, c1_.discr AS discr_10, c1_.salesPerson_id AS salesPerson_id_11 FROM company_contracts c0_, company_contracts c1_ WHERE (c0_.discr IN ('fix') AND c1_.discr IN ('flexible', 'flexultra'))"
);
}
@@ -1857,15 +1832,15 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u ORDER BY u.id + 1 ',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ ORDER BY c0_.id + 1 ASC'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ ORDER BY c0_.id + 1 ASC'
);
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u ORDER BY ( ( (u.id + 1) * (u.id - 1) ) / 2)',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ ORDER BY (((c0_.id + 1) * (c0_.id - 1)) / 2) ASC'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ ORDER BY (((c0_.id + 1) * (c0_.id - 1)) / 2) ASC'
);
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u ORDER BY ((u.id + 5000) * u.id + 3) ',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ ORDER BY ((c0_.id + 5000) * c0_.id + 3) ASC'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ ORDER BY ((c0_.id + 5000) * c0_.id + 3) ASC'
);
}
@@ -1873,7 +1848,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u ORDER BY CONCAT(u.username, u.name) ',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3 FROM cms_users c0_ ORDER BY c0_.username || c0_.name ASC'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c0_.email_id AS email_id_4 FROM cms_users c0_ ORDER BY c0_.username || c0_.name ASC'
);
}
@@ -1929,32 +1904,34 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u, a FROM Doctrine\Tests\Models\Quote\User u JOIN u.address a',
'SELECT q0_."user-id" AS userid_0, q0_."user-name" AS username_1, q1_."address-id" AS addressid_2, q1_."address-zip" AS addresszip_3, q1_.type AS type_4 FROM "quote-user" q0_ INNER JOIN "quote-address" q1_ ON q0_."user-id" = q1_."user-id" AND q1_.type IN (\'simple\', \'full\')'
<<<'SQL'
SELECT q0_."user-id" AS userid_0, q0_."user-name" AS username_1, q1_."address-id" AS addressid_2, q1_."address-zip" AS addresszip_3, q1_.type AS type_4, q1_."user-id" AS userid_5, q1_."city-id" AS cityid_6 FROM "quote-user" q0_ INNER JOIN "quote-address" q1_ ON q0_."user-id" = q1_."user-id" AND q1_.type IN ('simple', 'full')
SQL
);
$this->assertSqlGeneration(
'SELECT u, p FROM Doctrine\Tests\Models\Quote\User u JOIN u.phones p',
'SELECT q0_."user-id" AS userid_0, q0_."user-name" AS username_1, q1_."phone-number" AS phonenumber_2 FROM "quote-user" q0_ INNER JOIN "quote-phone" q1_ ON q0_."user-id" = q1_."user-id"'
'SELECT q0_."user-id" AS userid_0, q0_."user-name" AS username_1, q1_."phone-number" AS phonenumber_2, q1_."user-id" AS userid_3 FROM "quote-user" q0_ INNER JOIN "quote-phone" q1_ ON q0_."user-id" = q1_."user-id"'
);
$this->assertSqlGeneration(
'SELECT u, g FROM Doctrine\Tests\Models\Quote\User u JOIN u.groups g',
'SELECT q0_."user-id" AS userid_0, q0_."user-name" AS username_1, q1_."group-id" AS groupid_2, q1_."group-name" AS groupname_3 FROM "quote-user" q0_ INNER JOIN "quote-users-groups" q2_ ON q0_."user-id" = q2_."user-id" INNER JOIN "quote-group" q1_ ON q1_."group-id" = q2_."group-id"'
'SELECT q0_."user-id" AS userid_0, q0_."user-name" AS username_1, q1_."group-id" AS groupid_2, q1_."group-name" AS groupname_3, q1_."parent-id" AS parentid_4 FROM "quote-user" q0_ INNER JOIN "quote-users-groups" q2_ ON q0_."user-id" = q2_."user-id" INNER JOIN "quote-group" q1_ ON q1_."group-id" = q2_."group-id"'
);
$this->assertSqlGeneration(
'SELECT a, u FROM Doctrine\Tests\Models\Quote\Address a JOIN a.user u',
'SELECT q0_."address-id" AS addressid_0, q0_."address-zip" AS addresszip_1, q1_."user-id" AS userid_2, q1_."user-name" AS username_3, q0_.type AS type_4 FROM "quote-address" q0_ INNER JOIN "quote-user" q1_ ON q0_."user-id" = q1_."user-id" WHERE q0_.type IN (\'simple\', \'full\')'
'SELECT q0_."address-id" AS addressid_0, q0_."address-zip" AS addresszip_1, q1_."user-id" AS userid_2, q1_."user-name" AS username_3, q0_.type AS type_4, q0_."user-id" AS userid_5, q0_."city-id" AS cityid_6 FROM "quote-address" q0_ INNER JOIN "quote-user" q1_ ON q0_."user-id" = q1_."user-id" WHERE q0_.type IN (\'simple\', \'full\')'
);
$this->assertSqlGeneration(
'SELECT g, u FROM Doctrine\Tests\Models\Quote\Group g JOIN g.users u',
'SELECT q0_."group-id" AS groupid_0, q0_."group-name" AS groupname_1, q1_."user-id" AS userid_2, q1_."user-name" AS username_3 FROM "quote-group" q0_ INNER JOIN "quote-users-groups" q2_ ON q0_."group-id" = q2_."group-id" INNER JOIN "quote-user" q1_ ON q1_."user-id" = q2_."user-id"'
'SELECT q0_."group-id" AS groupid_0, q0_."group-name" AS groupname_1, q1_."user-id" AS userid_2, q1_."user-name" AS username_3, q0_."parent-id" AS parentid_4 FROM "quote-group" q0_ INNER JOIN "quote-users-groups" q2_ ON q0_."group-id" = q2_."group-id" INNER JOIN "quote-user" q1_ ON q1_."user-id" = q2_."user-id"'
);
$this->assertSqlGeneration(
'SELECT g, p FROM Doctrine\Tests\Models\Quote\Group g JOIN g.parent p',
'SELECT q0_."group-id" AS groupid_0, q0_."group-name" AS groupname_1, q1_."group-id" AS groupid_2, q1_."group-name" AS groupname_3 FROM "quote-group" q0_ INNER JOIN "quote-group" q1_ ON q0_."parent-id" = q1_."group-id"'
'SELECT q0_."group-id" AS groupid_0, q0_."group-name" AS groupname_1, q1_."group-id" AS groupid_2, q1_."group-name" AS groupname_3, q0_."parent-id" AS parentid_4, q1_."parent-id" AS parentid_5 FROM "quote-group" q0_ INNER JOIN "quote-group" q1_ ON q0_."parent-id" = q1_."group-id"'
);
}
@@ -1963,17 +1940,17 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT SUM(CASE WHEN e.salary <= :value THEN e.salary - :value WHEN e.salary >= :value THEN :value - e.salary ELSE 0 END) FROM Doctrine\Tests\Models\Company\CompanyEmployee e',
'SELECT SUM(CASE WHEN c0_.salary <= ? THEN c0_.salary - ? WHEN c0_.salary >= ? THEN ? - c0_.salary ELSE 0 END) AS sclr_0 FROM company_employees c0_ INNER JOIN company_persons c1_ ON c0_.id = c1_.id'
'SELECT SUM(CASE WHEN c0_.salary <= ? THEN c0_.salary - ? WHEN c0_.salary >= ? THEN ? - c0_.salary ELSE 0 END) AS sclr_0 FROM company_employees c0_ INNER JOIN company_persons c1_ ON c0_.id = c1_.id LEFT JOIN company_managers c2_ ON c0_.id = c2_.id'
);
$this->assertSqlGeneration(
'SELECT SUM(CASE WHEN e.salary <= :value THEN e.salary - :value WHEN e.salary >= :value THEN :value - e.salary ELSE e.salary + 0 END) FROM Doctrine\Tests\Models\Company\CompanyEmployee e',
'SELECT SUM(CASE WHEN c0_.salary <= ? THEN c0_.salary - ? WHEN c0_.salary >= ? THEN ? - c0_.salary ELSE c0_.salary + 0 END) AS sclr_0 FROM company_employees c0_ INNER JOIN company_persons c1_ ON c0_.id = c1_.id'
'SELECT SUM(CASE WHEN c0_.salary <= ? THEN c0_.salary - ? WHEN c0_.salary >= ? THEN ? - c0_.salary ELSE c0_.salary + 0 END) AS sclr_0 FROM company_employees c0_ INNER JOIN company_persons c1_ ON c0_.id = c1_.id LEFT JOIN company_managers c2_ ON c0_.id = c2_.id'
);
$this->assertSqlGeneration(
'SELECT SUM(CASE WHEN e.salary <= :value THEN (e.salary - :value) WHEN e.salary >= :value THEN (:value - e.salary) ELSE (e.salary + :value) END) FROM Doctrine\Tests\Models\Company\CompanyEmployee e',
'SELECT SUM(CASE WHEN c0_.salary <= ? THEN (c0_.salary - ?) WHEN c0_.salary >= ? THEN (? - c0_.salary) ELSE (c0_.salary + ?) END) AS sclr_0 FROM company_employees c0_ INNER JOIN company_persons c1_ ON c0_.id = c1_.id'
'SELECT SUM(CASE WHEN c0_.salary <= ? THEN (c0_.salary - ?) WHEN c0_.salary >= ? THEN (? - c0_.salary) ELSE (c0_.salary + ?) END) AS sclr_0 FROM company_employees c0_ INNER JOIN company_persons c1_ ON c0_.id = c1_.id LEFT JOIN company_managers c2_ ON c0_.id = c2_.id'
);
}
@@ -2039,12 +2016,12 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT r, b FROM Doctrine\Tests\Models\Routing\RoutingRoute r JOIN r.bookings b',
'SELECT r0_.id AS id_0, r1_.id AS id_1, r1_.passengerName AS passengerName_2 FROM RoutingRoute r0_ INNER JOIN RoutingRouteBooking r1_ ON r0_.id = r1_.route_id ORDER BY r1_.passengerName ASC'
'SELECT r0_.id AS id_0, r1_.id AS id_1, r1_.passengerName AS passengerName_2, r1_.route_id AS route_id_3 FROM RoutingRoute r0_ INNER JOIN RoutingRouteBooking r1_ ON r0_.id = r1_.route_id ORDER BY r1_.passengerName ASC'
);
$this->assertSqlGeneration(
'SELECT r, b FROM Doctrine\Tests\Models\Routing\RoutingRoute r JOIN r.bookings b ORDER BY b.passengerName DESC',
'SELECT r0_.id AS id_0, r1_.id AS id_1, r1_.passengerName AS passengerName_2 FROM RoutingRoute r0_ INNER JOIN RoutingRouteBooking r1_ ON r0_.id = r1_.route_id ORDER BY r1_.passengerName DESC'
'SELECT r0_.id AS id_0, r1_.id AS id_1, r1_.passengerName AS passengerName_2, r1_.route_id AS route_id_3 FROM RoutingRoute r0_ INNER JOIN RoutingRouteBooking r1_ ON r0_.id = r1_.route_id ORDER BY r1_.passengerName DESC'
);
}
@@ -2067,8 +2044,7 @@ class SelectSqlGenerationTest extends 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 id_0 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 = ?)',
[ORMQuery::HINT_FORCE_PARTIAL_LOAD => false]
'SELECT c0_.id AS id_0 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 = ?)'
);
}
@@ -2078,7 +2054,7 @@ class SelectSqlGenerationTest extends OrmTestCase
// Regression test for the bug
$this->assertSqlGeneration(
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyEmployee e LEFT JOIN Doctrine\Tests\Models\Company\CompanyContract c WITH c.salesPerson = e.id',
"SELECT c0_.id AS id_0, c0_.completed AS completed_1, c0_.fixPrice AS fixPrice_2, c0_.hoursWorked AS hoursWorked_3, c0_.pricePerHour AS pricePerHour_4, c0_.maxPrice AS maxPrice_5, c0_.discr AS discr_6 FROM company_employees c1_ INNER JOIN company_persons c2_ ON c1_.id = c2_.id LEFT JOIN company_contracts c0_ ON (c0_.salesPerson_id = c2_.id) AND c0_.discr IN ('fix', 'flexible', 'flexultra')"
"SELECT c0_.id AS id_0, c0_.completed AS completed_1, c0_.fixPrice AS fixPrice_2, c0_.hoursWorked AS hoursWorked_3, c0_.pricePerHour AS pricePerHour_4, c0_.maxPrice AS maxPrice_5, c0_.discr AS discr_6, c0_.salesPerson_id AS salesPerson_id_7 FROM company_employees c1_ INNER JOIN company_persons c2_ ON c1_.id = c2_.id LEFT JOIN company_managers c3_ ON c1_.id = c3_.id LEFT JOIN company_contracts c0_ ON (c0_.salesPerson_id = c2_.id) AND c0_.discr IN ('fix', 'flexible', 'flexultra')"
);
}
@@ -2088,7 +2064,7 @@ class SelectSqlGenerationTest extends OrmTestCase
// Ensure other WHERE predicates are passed through to the main WHERE clause
$this->assertSqlGeneration(
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyEmployee e LEFT JOIN Doctrine\Tests\Models\Company\CompanyContract c WITH c.salesPerson = e.id WHERE e.salary > 1000',
"SELECT c0_.id AS id_0, c0_.completed AS completed_1, c0_.fixPrice AS fixPrice_2, c0_.hoursWorked AS hoursWorked_3, c0_.pricePerHour AS pricePerHour_4, c0_.maxPrice AS maxPrice_5, c0_.discr AS discr_6 FROM company_employees c1_ INNER JOIN company_persons c2_ ON c1_.id = c2_.id LEFT JOIN company_contracts c0_ ON (c0_.salesPerson_id = c2_.id) AND c0_.discr IN ('fix', 'flexible', 'flexultra') WHERE c1_.salary > 1000"
"SELECT c0_.id AS id_0, c0_.completed AS completed_1, c0_.fixPrice AS fixPrice_2, c0_.hoursWorked AS hoursWorked_3, c0_.pricePerHour AS pricePerHour_4, c0_.maxPrice AS maxPrice_5, c0_.discr AS discr_6, c0_.salesPerson_id AS salesPerson_id_7 FROM company_employees c1_ INNER JOIN company_persons c2_ ON c1_.id = c2_.id LEFT JOIN company_managers c3_ ON c1_.id = c3_.id LEFT JOIN company_contracts c0_ ON (c0_.salesPerson_id = c2_.id) AND c0_.discr IN ('fix', 'flexible', 'flexultra') WHERE c1_.salary > 1000"
);
}
@@ -2098,7 +2074,7 @@ class SelectSqlGenerationTest extends OrmTestCase
// Test inner joins too
$this->assertSqlGeneration(
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyEmployee e INNER JOIN Doctrine\Tests\Models\Company\CompanyContract c WITH c.salesPerson = e.id',
"SELECT c0_.id AS id_0, c0_.completed AS completed_1, c0_.fixPrice AS fixPrice_2, c0_.hoursWorked AS hoursWorked_3, c0_.pricePerHour AS pricePerHour_4, c0_.maxPrice AS maxPrice_5, c0_.discr AS discr_6 FROM company_employees c1_ INNER JOIN company_persons c2_ ON c1_.id = c2_.id INNER JOIN company_contracts c0_ ON (c0_.salesPerson_id = c2_.id) AND c0_.discr IN ('fix', 'flexible', 'flexultra')"
"SELECT c0_.id AS id_0, c0_.completed AS completed_1, c0_.fixPrice AS fixPrice_2, c0_.hoursWorked AS hoursWorked_3, c0_.pricePerHour AS pricePerHour_4, c0_.maxPrice AS maxPrice_5, c0_.discr AS discr_6, c0_.salesPerson_id AS salesPerson_id_7 FROM company_employees c1_ INNER JOIN company_persons c2_ ON c1_.id = c2_.id LEFT JOIN company_managers c3_ ON c1_.id = c3_.id INNER JOIN company_contracts c0_ ON (c0_.salesPerson_id = c2_.id) AND c0_.discr IN ('fix', 'flexible', 'flexultra')"
);
}
@@ -2109,7 +2085,7 @@ class SelectSqlGenerationTest extends OrmTestCase
// the where clause when not joining onto that table
$this->assertSqlGeneration(
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c LEFT JOIN Doctrine\Tests\Models\Company\CompanyEmployee e WITH e.id = c.salesPerson WHERE c.completed = true',
"SELECT c0_.id AS id_0, c0_.completed AS completed_1, c0_.fixPrice AS fixPrice_2, c0_.hoursWorked AS hoursWorked_3, c0_.pricePerHour AS pricePerHour_4, c0_.maxPrice AS maxPrice_5, c0_.discr AS discr_6 FROM company_contracts c0_ LEFT JOIN (company_employees c1_ INNER JOIN company_persons c2_ ON c1_.id = c2_.id) ON (c2_.id = c0_.salesPerson_id) WHERE (c0_.completed = 1) AND c0_.discr IN ('fix', 'flexible', 'flexultra')"
"SELECT c0_.id AS id_0, c0_.completed AS completed_1, c0_.fixPrice AS fixPrice_2, c0_.hoursWorked AS hoursWorked_3, c0_.pricePerHour AS pricePerHour_4, c0_.maxPrice AS maxPrice_5, c0_.discr AS discr_6, c0_.salesPerson_id AS salesPerson_id_7 FROM company_contracts c0_ LEFT JOIN (company_employees c1_ INNER JOIN company_persons c2_ ON c1_.id = c2_.id LEFT JOIN company_managers c3_ ON c1_.id = c3_.id) ON (c2_.id = c0_.salesPerson_id) WHERE (c0_.completed = 1) AND c0_.discr IN ('fix', 'flexible', 'flexultra')"
);
}
@@ -2121,7 +2097,7 @@ class SelectSqlGenerationTest extends OrmTestCase
// via a join association
$this->assertSqlGeneration(
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c JOIN c.salesPerson s WHERE c.completed = true',
"SELECT c0_.id AS id_0, c0_.completed AS completed_1, c0_.fixPrice AS fixPrice_2, c0_.hoursWorked AS hoursWorked_3, c0_.pricePerHour AS pricePerHour_4, c0_.maxPrice AS maxPrice_5, c0_.discr AS discr_6 FROM company_contracts c0_ INNER JOIN company_employees c1_ ON c0_.salesPerson_id = c1_.id LEFT JOIN company_persons c2_ ON c1_.id = c2_.id WHERE (c0_.completed = 1) AND c0_.discr IN ('fix', 'flexible', 'flexultra')"
"SELECT c0_.id AS id_0, c0_.completed AS completed_1, c0_.fixPrice AS fixPrice_2, c0_.hoursWorked AS hoursWorked_3, c0_.pricePerHour AS pricePerHour_4, c0_.maxPrice AS maxPrice_5, c0_.discr AS discr_6, c0_.salesPerson_id AS salesPerson_id_7 FROM company_contracts c0_ INNER JOIN company_employees c1_ ON c0_.salesPerson_id = c1_.id LEFT JOIN company_persons c2_ ON c1_.id = c2_.id LEFT JOIN company_managers c3_ ON c1_.id = c3_.id WHERE (c0_.completed = 1) AND c0_.discr IN ('fix', 'flexible', 'flexultra')"
);
}
@@ -2133,7 +2109,7 @@ class SelectSqlGenerationTest extends OrmTestCase
// into the ON clause of the join
$this->assertSqlGeneration(
'SELECT e, COUNT(c) FROM Doctrine\Tests\Models\Company\CompanyEmployee e JOIN e.contracts c WHERE e.department = :department',
"SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.salary AS salary_2, c1_.department AS department_3, c1_.startDate AS startDate_4, COUNT(c2_.id) AS sclr_5, c0_.discr AS discr_6 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id INNER JOIN company_contract_employees c3_ ON c1_.id = c3_.employee_id INNER JOIN company_contracts c2_ ON c2_.id = c3_.contract_id AND c2_.discr IN ('fix', 'flexible', 'flexultra') WHERE c1_.department = ?",
"SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.salary AS salary_2, c1_.department AS department_3, c1_.startDate AS startDate_4, c2_.title AS title_5, COUNT(c3_.id) AS sclr_6, c0_.discr AS discr_7, c0_.spouse_id AS spouse_id_8, c2_.car_id AS car_id_9 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id LEFT JOIN company_managers c2_ ON c1_.id = c2_.id INNER JOIN company_contract_employees c4_ ON c1_.id = c4_.employee_id INNER JOIN company_contracts c3_ ON c3_.id = c4_.contract_id AND c3_.discr IN ('fix', 'flexible', 'flexultra') WHERE c1_.department = ?",
[],
['department' => 'foobar']
);
@@ -2162,7 +2138,7 @@ class SelectSqlGenerationTest extends OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u AS user, SUM(a.id) AS score FROM Doctrine\Tests\Models\CMS\CmsUser u LEFT JOIN Doctrine\Tests\Models\CMS\CmsAddress a WITH a.user = u GROUP BY u HAVING score IS NOT NULL AND score >= 5',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, SUM(c1_.id) AS sclr_4 FROM cms_users c0_ LEFT JOIN cms_addresses c1_ ON (c1_.user_id = c0_.id) GROUP BY c0_.id, c0_.status, c0_.username, c0_.name, c0_.email_id HAVING sclr_4 IS NOT NULL AND sclr_4 >= 5'
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, SUM(c1_.id) AS sclr_4, c0_.email_id AS email_id_5 FROM cms_users c0_ LEFT JOIN cms_addresses c1_ ON (c1_.user_id = c0_.id) GROUP BY c0_.id, c0_.status, c0_.username, c0_.name, c0_.email_id HAVING sclr_4 IS NOT NULL AND sclr_4 >= 5'
);
}
@@ -1087,6 +1087,18 @@ class QueryBuilderTest extends OrmTestCase
self::assertEquals('SELECT DISTINCT u FROM Doctrine\Tests\Models\CMS\CmsUser u', $qb->getDQL());
}
public function testDistinctUpdatesState(): void
{
$qb = $this->entityManager->createQueryBuilder()
->select('u')
->from(CmsUser::class, 'u');
$qb->getDQL();
$qb->distinct();
self::assertEquals('SELECT DISTINCT u FROM Doctrine\Tests\Models\CMS\CmsUser u', $qb->getDQL());
}
/** @group DDC-2192 */
public function testWhereAppend(): void
{
@@ -56,6 +56,17 @@ class AttachEntityListenersListenerTest extends OrmTestCase
self::assertCount(1, $metadata->entityListeners['postLoad']);
self::assertEquals('postLoadHandler', $metadata->entityListeners['postLoad'][0]['method']);
self::assertEquals(AttachEntityListenersListenerTestListener::class, $metadata->entityListeners['postLoad'][0]['class']);
// Can reattach entity listeners even class metadata factory recreated.
$factory2 = new ClassMetadataFactory();
$factory2->setEntityManager($this->em);
$metadata2 = $factory2->getMetadataFor(AttachEntityListenersListenerTestFooEntity::class);
self::assertArrayHasKey('postLoad', $metadata2->entityListeners);
self::assertCount(1, $metadata2->entityListeners['postLoad']);
self::assertEquals('postLoadHandler', $metadata2->entityListeners['postLoad'][0]['method']);
self::assertEquals(AttachEntityListenersListenerTestListener::class, $metadata2->entityListeners['postLoad'][0]['class']);
}
public function testAttachToExistingEntityListeners(): void
@@ -15,6 +15,8 @@ use Doctrine\ORM\Mapping\ClassMetadataFactory;
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
use Doctrine\ORM\Mapping\Driver\XmlDriver;
use Doctrine\ORM\Mapping\Driver\YamlDriver;
use Doctrine\ORM\Mapping\PostPersist;
use Doctrine\ORM\Mapping\PrePersist;
use Doctrine\ORM\Tools\DisconnectedClassMetadataFactory;
use Doctrine\ORM\Tools\EntityGenerator;
use Doctrine\ORM\Tools\Export\ClassMetadataExporter;
@@ -399,26 +401,26 @@ class Group
}
class UserListener
{
/** @\Doctrine\ORM\Mapping\PrePersist */
/** @PrePersist */
public function customPrePersist(): void
{
}
/** @\Doctrine\ORM\Mapping\PostPersist */
/** @PostPersist */
public function customPostPersist(): void
{
}
}
class GroupListener
{
/** @\Doctrine\ORM\Mapping\PrePersist */
/** @PrePersist */
public function prePersist(): void
{
}
}
class AddressListener
{
/** @\Doctrine\ORM\Mapping\PostPersist */
/** @PostPersist */
public function customPostPersist(): void
{
}
@@ -77,7 +77,7 @@ class SchemaToolTest extends OrmTestCase
);
$table = $schema->getTable('TestEntityWithAnnotationOptionsAttribute');
foreach ([$table->getOptions(), $table->getColumn('test')->getCustomSchemaOptions()] as $options) {
foreach ([$table->getOptions(), $table->getColumn('test')->getPlatformOptions()] as $options) {
self::assertArrayHasKey('foo', $options);
self::assertSame('bar', $options['foo']);
self::assertArrayHasKey('baz', $options);
@@ -139,7 +139,7 @@ class SchemaToolTest extends OrmTestCase
self::assertEquals(
['collation' => 'latin1_bin', 'foo' => 'bar'],
$tableBoard->getColumn('category_id')->getCustomSchemaOptions()
$tableBoard->getColumn('category_id')->getPlatformOptions()
);
}
@@ -192,13 +192,13 @@ class SchemaToolTest extends OrmTestCase
$em = $this->getTestEntityManager();
$schemaTool = new SchemaTool($em);
$customSchemaOptions = $schemaTool->getSchemaFromMetadata([$em->getClassMetadata(Card::class)])
$platformOptions = $schemaTool->getSchemaFromMetadata([$em->getClassMetadata(Card::class)])
->getTable('Card')
->getColumn('suit')
->getCustomSchemaOptions();
->getPlatformOptions();
self::assertArrayHasKey('enumType', $customSchemaOptions);
self::assertSame(Suit::class, $customSchemaOptions['enumType']);
self::assertArrayHasKey('enumType', $platformOptions);
self::assertSame(Suit::class, $platformOptions['enumType']);
}
/** @group DDC-3671 */
@@ -384,7 +384,8 @@ class DDC1649Two
{
/**
* @var DDC1649One
* @Id @ManyToOne(targetEntity="DDC1649One")
* @Id
* @ManyToOne(targetEntity="DDC1649One")
*/
public $one;
}