Thanks for the very quick reply! We appreciate it that you took some time
to look into the issue.
We see what you mean by the partial graph in the result, especially in the
example you provided.
However, it is not very clear to us whether his applies to our case as
well. In our test case, we have:
1. one *Offer* (filtered by id in the query)
2. exactly two related *Offerline*s (so the INNER JOIN matches the whole
set)
3. for each Offerline exactly one *Generalassuranceline*
4. for each *Generalassuranceline *exactly one *Possession* (which we
did not include in our query)
Changing our DQL to the following, to eliminate filtering by INNER JOIN,
gave us the same results:
SELECT
offer,
offerline,
generalassuranceline
FROM
Entity\Offer\Offer offer
LEFT JOIN offer.offerlines offerline
LEFT JOIN offerline.generalassuranceline generalassuranceline
WHERE
offer.id = 6749
Experimenting a bit after reading your reply, we tried extending our DQL
with the missing join to see if this would change anything. And indeed, the
full resultset is returned after adding the join:
SELECT
offer,
offerline,
generalassuranceline,
object
FROM
Entity\Offer\Offer offer
INNER JOIN offer.offerlines offerline
INNER JOIN offerline.generalassuranceline generalassuranceline
LEFT JOIN generalassuranceline.object object
WHERE
offer.id = 6749
However, this is not really the behaviour we expected. And this means in
our production software that we would have to extend pretty simple queries
with multiple extra joins just to make sure that the entire resultset is
filled nicely. In the example above, the subentities Offerlines are not
filled completely *unless* we join two more subentities
(generalassuranceline and object).
So, we have no clue why the missing join leads to an incomplete partial
result.
On Friday, December 29, 2017 at 3:48:43 PM UTC+1, Marco Pivetta wrote:
>
> What is happening seems to be incorrect hydration of a partial result.
>
> This is usually a problem with queries like following:
>
> SELECT a, b FROM A a JOIN a.b b WHERE b.something = 123;
>
> This query will select all A records with all its a.b populated, but will
> filter them by a restriction. The problem is that this will hydrate a
> partial graph into your object, and that object will afterwards remain in
> memory, broken until you clear the UnitOfWork.
>
> The fix is to not join in records and filter:
>
> SELECT a, b FROM A a LEFT JOIN a.b b JOIN a.b b2 WHERE b2.something = 123;
>
> In your case, the filtering is subtle because you used a JOIN condition
> twice, and that implicitly acts as restriction.
>
> Marco Pivetta
>
> http://twitter.com/Ocramius
>
> http://ocramius.github.com/
>
> On Fri, Dec 29, 2017 at 3:24 PM, <[email protected] <javascript:>> wrote:
>
>> We have some problems querying an entity with embedded sub entities.
>> First let me sketch the context:
>>
>> - We have a table with *Offer* entities
>> - Each *Offer* consists of *multiple* *Offerlines*
>> - Each *Offerline* has *one* related *Generalassuranceline*
>> - Each *Generalassuranceline* has *one* related *Possession*
>> - This *Possession* has a discriminator column defined to
>> distinguish two possession subtypes: *Vehicle* and *Misc*
>>
>> In the mapping of *Generalassuranceline* the *Possession* is defined as
>> a many-to-one relation (named 'object') to the generic *Possession* type,
>> because at the *Generalassuranceline* level the 'object' can be either a
>> *Vehicle* or a *Misc* entity.
>>
>> The detailed mappings of the entities are listed below.
>>
>>
>> The DQL query we execute is the following:
>>
>> SELECT
>> offer,
>> offerline,
>> generalassuranceline
>> FROM
>> Entity\Offer\Offer offer
>> INNER JOIN offer.offerlines offerline
>> INNER JOIN offerline.generalassuranceline generalassuranceline
>> WHERE
>> offer.id = 6749
>>
>> *Problem: *
>> In the database, the *offer* we query has two *offerlines*. In the
>> following situations, the output is generated by:
>>
>> \Doctrine\Common\Util\Debug::dump($query->getResult(), 3);
>>
>> Situation 1:
>> If we specify the "object" relation in *Generalassuranceline* as type
>> *Possession*, we only get one *offerline* entity in our result.
>> array(1) {
>> [0]=>
>> object(stdClass)#27 (5) {
>> ["__CLASS__"]=>
>> string(18) "Entity\Offer\Offer"
>> ["id"]=>
>> int(6749)
>> ["offernumber"]=>
>> string(8) "98037192"
>> ["description"]=>
>> string(13) "auto 29-KQB-3"
>> ["offerlines"]=>
>> * array*
>>
>>
>> *(1) { [0]=> string(22) "Entity\Offer\Offerline" }*
>> }
>> }
>>
>>
>> Situation 2:
>> If we specify the "object" relation in *Generalassuranceline* as type
>> *Vehicle*, we get both the *offerline* entities as expected.
>> array(1) {
>> [0]=>
>> object(stdClass)#27 (5) {
>> ["__CLASS__"]=>
>> string(18) "Entity\Offer\Offer"
>> ["id"]=>
>> int(6749)
>> ["offernumber"]=>
>> string(8) "98037192"
>> ["description"]=>
>> string(13) "auto 29-KQB-3"
>> ["offerlines"]=>
>> * array*
>>
>>
>>
>>
>> *(2) { [0]=> string(22) "Entity\Offer\Offerline" [1]=>
>> string(22) "Entity\Offer\Offerline" }*
>> }
>> }
>>
>>
>> Can someone explain to us the reason why we get only one *offerline* entity
>> in the *offer* result in situation 1 and what we can change to retrieve
>> more reliable results?
>>
>>
>> *Mappings:*
>>
>> *Offer*
>> <?xml version="1.0" encoding="utf-8"?>
>> <doctrine-mapping
>> xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
>> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>> xsi:schemaLocation="
>> http://doctrine-project.org/schemas/orm/doctrine-mapping
>> http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
>>
>> <entity name="Entity\Offer\Offer" table="accountingoffer">
>>
>> <id name="id" type="integer" column="id">
>> <generator strategy="IDENTITY"/>
>> </id>
>>
>> <field name="offernumber" type="string" column="offernumber" length=
>> "255" nullable="true" />
>> <field name="description" type="string" column="description" length=
>> "255" nullable="true" />
>>
>> <one-to-many field="offerlines" target-entity=
>> "Entity\Offer\Offerline" mapped-by="offer" fetch="LAZY" />
>> </entity>
>> </doctrine-mapping>
>>
>>
>> *Offerline*
>> <?xml version="1.0" encoding="utf-8"?>
>> <doctrine-mapping
>> xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
>> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>> xsi:schemaLocation="
>> http://doctrine-project.org/schemas/orm/doctrine-mapping
>> http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
>>
>> <entity name="Entity\Offer\Offerline" table="accountingofferline">
>>
>> <id name="id" type="integer" column="id">
>> <generator strategy="IDENTITY"/>
>> </id>
>>
>> <field name="offernumber" type="string" column="offernumber" length=
>> "255" nullable="true" />
>>
>> <many-to-one field="offer" target-entity="Entity\Offer\Offer"
>> inversed-by="offerlines">
>> <join-column name="accountingoffer_id" referenced-column-name=
>> "id"/>
>> </many-to-one>
>>
>> <one-to-one field="generalassuranceline" target-entity=
>> "Entity\Offer\Generalassuranceline" mapped-by="offerline" />
>> </entity>
>> </doctrine-mapping>
>>
>>
>> *Generalassuranceline*
>> <?xml version="1.0" encoding="utf-8"?>
>> <doctrine-mapping
>> xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
>> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>> xsi:schemaLocation="
>> http://doctrine-project.org/schemas/orm/doctrine-mapping
>> http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
>>
>> <entity name="Entity\Offer\Generalassuranceline" table=
>> "accountingofferline_generalassurance">
>>
>> <id name="offerlineId" type="integer" column="accountingofferline_id"
>> >
>> <generator strategy="IDENTITY"/>
>> </id>
>>
>> <one-to-one field="offerline" target-entity="Entity\Offer\Offerline"
>> inversed-by="generalassuranceline">
>> <join-column name="accountingofferline_id" referenced-column-name
>> ="id"/>
>> </one-to-one>
>>
>> <many-to-one field="object" target-entity=
>> "Entity\Possession\Possession" fetch="LAZY">
>> <join-column name="crmpossession_id" referenced-column-name="id"
>> />
>> </many-to-one>
>> </entity>
>> </doctrine-mapping>
>>
>>
>> *Possession*
>> <?xml version="1.0" encoding="utf-8"?>
>> <doctrine-mapping
>> xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
>> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>> xsi:schemaLocation="
>> http://doctrine-project.org/schemas/orm/doctrine-mapping
>> http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
>>
>> <entity name="Entity\Possession\Possession" table="crmpossession"
>> inheritance-type="SINGLE_TABLE">
>>
>> <id name="id" type="integer" column="id">
>> <generator strategy="IDENTITY"/>
>> </id>
>>
>> <discriminator-column name="crmpossessiontypecategory_id" type=
>> "integer" />
>> <discriminator-map>
>> <discriminator-mapping value="1" class=
>> "Entity\Possession\Vehicle" />
>> <discriminator-mapping value="2" class="Entity\Possession\Misc"
>> />
>> </discriminator-map>
>>
>> <field name="description" type="string" column="description" length=
>> "255" nullable="true" />
>> </entity>
>> </doctrine-mapping>
>>
>>
>> *Vehicle*
>> <?xml version="1.0" encoding="utf-8"?>
>> <doctrine-mapping
>> xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
>> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>> xsi:schemaLocation="
>> http://doctrine-project.org/schemas/orm/doctrine-mapping
>> http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
>>
>> <entity name="Entity\Possession\Vehicle" />
>>
>> </doctrine-mapping>
>>
>>
>> *Misc*
>> <?xml version="1.0" encoding="utf-8"?>
>> <doctrine-mapping
>> xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
>> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>> xsi:schemaLocation="
>> http://doctrine-project.org/schemas/orm/doctrine-mapping
>> http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
>>
>> <entity name="Entity\Possession\Misc" />
>>
>> </doctrine-mapping>
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "doctrine-user" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected] <javascript:>.
>> To post to this group, send email to [email protected]
>> <javascript:>.
>> Visit this group at https://groups.google.com/group/doctrine-user.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>
--
You received this message because you are subscribed to the Google Groups
"doctrine-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/doctrine-user.
For more options, visit https://groups.google.com/d/optout.