[DDC-3690] PersistentCollection uses private property Created: 14/Apr/15  Updated: 15/Apr/15

Status: Open
Project: Doctrine 2 - ORM
Component/s: Lazy Loading, ORM
Affects Version/s: 2.5
Fix Version/s: 2.5.1
Security Level: All

Type: Bug Priority: Blocker
Reporter: Roel Assignee: Marco Pivetta
Resolution: Unresolved Votes: 0
Labels: collection, persistent-collection, release


 Description   

1. PersistentCollection in Doctrine 2.5 makes uses of the $initialized property defined in the AbstractLazyCollection of doctrine\collection (https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/PersistentCollection.php#L113)
2. Doctrine 2.5 depends on version ~1.2 of doctrine\collection that marks the $initialized property as private https://github.com/doctrine/collections/blob/v1.2/lib/Doctrine/Common/Collections/AbstractLazyCollection.php
3. Hence writing to the initialized variable fails. And thus code related to initialization fails.

A fix is already applied to doctrine\orm https://github.com/doctrine/collections/commit/e2eef4629349fd847c8e080b8f729ab33e81e10f but is not tagged. Possible fix would be to release a new version of doctrine\collection as 1.2.1.



 Comments   
Comment by Roel [ 14/Apr/15 ]

Due to this several tests fail in our code-base.

Comment by Marco Pivetta [ 14/Apr/15 ]

This is a bug caused by the fact that ORM 2.5 should depend on Collections 1.3.0 - I'll look into it ASAP.

Comment by Marco Pivetta [ 15/Apr/15 ]

Collections 1.3.0 was released, but I'll keep this open until ORM 2.5.1 is out.





[DDC-2953] ArrayHydrator: Not all items hydrated while orderBy Created: 05/Feb/14  Updated: 18/Aug/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3.4, 2.4.1
Fix Version/s: None
Security Level: All

Type: Bug Priority: Critical
Reporter: Mariusz Jaskółka Assignee: Guilherme Blanco
Resolution: Unresolved Votes: 0
Labels: array, hydration
Environment:

Linux and Windows, PHP5


Attachments: File ArrayHydrator.php     File Array_Hydrator_4.2.php     File Array_hydrator_4.2_bugfix.php    
Issue Links:
Dependency
depends on DDC-2955 [GH-933] [WIP] DDC-2953 Resolved

 Description   

I will explain the problem using example and pseudo-code:

I have query like that:
SELECT (...) FROM order LEFT JOIN person LEFT JOIN identifier (...) order by (...)

The rows returned by query are following (the order is very important):
order_id|person_id|identifier_id|
12 |21 |33 |
12 |21 |34 |
11 |21 |35 |
11 |21 |33 |
11 |21 |34 |
12 |21 |35 |

After hydration the result is like:
result[0][person][identifier][0][id]=33
result[0][person][identifier][0][id]=34
result[1][person][identifier][0][id]=35
result[1][person][identifier][0][id]=34

But it should be:
result[0][person][identifier][0][id]=33
result[0][person][identifier][0][id]=34
result[0][person][identifier][0][id]=35
result[1][person][identifier][0][id]=35
result[1][person][identifier][0][id]=34
result[1][person][identifier][0][id]=33

The reason is that ArrayHydrator::_identifierMap contains only object id and parents object id. In may example there is difference in parents parent (grandparent) id.



 Comments   
Comment by Marco Pivetta [ 05/Feb/14 ]

I've started work on this at https://github.com/doctrine/doctrine2/pull/933

Comment by Mariusz Jaskółka [ 06/Feb/14 ]

This is how I temporary solved the issue, maybe it can help (attachment).

Comment by Marco Pivetta [ 06/Feb/14 ]

Mariusz Jaskółka can you provide a diff with current master? This seems to be based off 2.3 or previous versions...

Comment by Mariusz Jaskółka [ 06/Feb/14 ]

Version 2.4.2 oryginal file and bugfix

Comment by Mariusz Jaskółka [ 06/Feb/14 ]

Oh sorry it is version 2.4.1 (composer downloaded that version for me).
I hope it will be ok.

Comment by Marco Pivetta [ 06/Feb/14 ]

Mariusz Jaskółka thanks! I'm trying it right now

Comment by Mariusz Jaskółka [ 06/Feb/14 ]

I added one dimention to $this->_identifierMap to be sure that all object's children's keys will be mapped separately.

Comment by Marco Pivetta [ 06/Feb/14 ]

Mariusz Jaskółka, I've applied your hotfix at https://github.com/doctrine/doctrine2/commit/c05921032ff6947daca2d7275031e5cde4700634 and the tests seem to pass on my system and on travis. You may want to check it out and see if it works for your use case.

Comment by Mariusz Jaskółka [ 06/Feb/14 ]

It works for my use case correctly. You apparently forgot to remove/comment line 82 which is not necessary now.

Comment by Marco Pivetta [ 06/Feb/14 ]

Mariusz Jaskółka fixed, thanks!

Comment by Marco Pivetta [ 14/Jul/14 ]

I don't think we'll have a fix for this issue for 2.5, as it will probably require a complete rewrite of the array hydrator

Comment by Guilherme Blanco [ 14/Jul/14 ]

... and introducing BC breaks.

Comment by Doctrine Bot [ 18/Aug/14 ]

A related Github Pull-Request [GH-933] was closed:
https://github.com/doctrine/doctrine2/pull/933





[DDC-3212] Remove ArrayHydrator logic Created: 14/Jul/14  Updated: 13/Oct/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.5
Fix Version/s: 3.0
Security Level: All

Type: Improvement Priority: Critical
Reporter: Marco Pivetta Assignee: Marco Pivetta
Resolution: Unresolved Votes: 0
Labels: hydration, hydrator


 Description   

The Doctrine\ORM\Internal\Hydration\ArrayHydrator ( https://github.com/doctrine/doctrine2/blob/85fbf684363b932a4ebaf543ef059f9ee1e512b0/lib/Doctrine/ORM/Internal/Hydration/ArrayHydrator.php ) is currently very messy and complicated due to the lack of actual Doctrine\ORM\UnitOfWork references when working with it, since we are not dealing with objects.

In order to reduce the amount of bugs and code duplication when working with array hydration, I would simply suggest making use of the Doctrine\ORM\Internal\Hydration\ObjectHydrator ( https://github.com/doctrine/doctrine2/blob/85fbf684363b932a4ebaf543ef059f9ee1e512b0/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php ) and its siblings, and then extracting data coming from the results in it as an array.

This could be a simple reflection-based extraction (pseudo):

class ArrayHydrator
{
    public function hydrateAllData()
    {
        foreach ($this->objectHydrator->hydrateAllData() as $object) {
            yield $this->extractData($object);
        }
    }
}

The point here is that array-based hydration is not the primary focus of the ORM, and users should probably rely on SQL only when they want array hydration.



 Comments   
Comment by Marco Pivetta [ 14/Jul/14 ]

Note: performance is one of our biggest requirements, and array hydration is meant to achieve that. As I stated above, plain SQL is probably better for this sort of operation, so the issue is more about deprecating the ArrayHydrator completely, providing utilities to manipulate SQL resultsets instead.





[DDC-3512] Redesign ClassMetadata API as ValueObject based (for type-safety and self-documentation) Created: 17/Jan/15  Updated: 18/Jan/15

Status: Open
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers, ORM
Affects Version/s: None
Fix Version/s: 3.0
Security Level: All

Type: Improvement Priority: Critical
Reporter: Marco Pivetta Assignee: Marco Pivetta
Resolution: Unresolved Votes: 0
Labels: classmetadatafactory, cleanup, metadata, performance, type-safety

Issue Links:
Reference
relates to DDC-3503 [GH-1257] Resolve target entity also ... Resolved

 Description   

The current ClassMetadata API is based on a lot of array juggling (for performance reasons).

While that was understandable with PHP 5.3, all the array access operations are currently:

  • slowing things down
  • making the code very hard to read/understand

I suggest re-coding the ClassMetadata internals (public properties and such) so that well-described properties are defined.

Additionally, as a bonus, we'd get a performance boost by just moving all the class-alias and type resolution logic from the runtime into the ClassMetadataFactory (or similar) API, saving tons of performance at every run.

In pseudo-logic, what I'd like to achieve with DDC-3512 is:

  • base metadata is loaded from the mapping driver
  • onLoadMetadata event is fired for each loaded metadata instance
  • metadata is completed by the ClassMetadataFactory logic
  • onCompleteMetadata event is fired for each loaded metadata instance

This would make metadata manipulation from events a bit messier (user needs to know which value to change during which event), but would allow using better constrained metadata structures in future, and that would disallow mistakes during event listeners execution as well (internal validation).






[DDC-3441] Unidirectional ManyToOne Not Lazy Loading Created: 09/Dec/14  Updated: 24/Jan/15

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master, 2.4.6
Fix Version/s: None
Security Level: All

Type: Bug Priority: Critical
Reporter: Marcus Fulbright Assignee: Marco Pivetta
Resolution: Unresolved Votes: 0
Labels: lazy-loading, proxy, public-properties, reflection

Issue Links:
Dependency
depends on DDC-3442 [GH-1217] @DDC3441 failing test cases... Open

 Description   

The Unidirectional ManyToOne association described in the docs does not lazy load correctly. The appropriate SQL will get executed, and the returned Proxy does pass type hinting for the correct class. However, the lazy loaded object always has the following properties:

  • _initializer_
  • _cloner_
  • _isInitialized_
  • lazyPropertiesDefaults

Any properties from the class definition do not show up. This is problematic when trying to get reflected properties and their values. Methods are correctly reflected.

Pull request for failing test case



 Comments   
Comment by Marcus Fulbright [ 09/Dec/14 ]

Let me know if anything else is needed.

Comment by Doctrine Bot [ 11/Dec/14 ]

A related Github Pull-Request [GH-1217] was assigned:
https://github.com/doctrine/doctrine2/pull/1217

Comment by Marco Pivetta [ 11/Dec/14 ]

Looks like a current ORM limitation (private properties lazy loading).

Related:

Comment by Doctrine Bot [ 24/Jan/15 ]

A related Github Pull-Request [GH-1217] was labeled:
https://github.com/doctrine/doctrine2/pull/1217

Comment by Doctrine Bot [ 24/Jan/15 ]

A related Github Pull-Request [GH-1217] was labeled:
https://github.com/doctrine/doctrine2/pull/1217





[DDC-3535] Allow binding `Parameter` value object to statements, removing the need for explicit value and type passing Created: 24/Jan/15  Updated: 24/Jan/15

Status: Open
Project: Doctrine 2 - ORM
Component/s: Lazy Loading, ORM
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: Task Priority: Critical
Reporter: Marco Pivetta Assignee: Marco Pivetta
Resolution: Unresolved Votes: 0
Labels: binding, criteria, parameters, persister, repository, type


 Comments   
Comment by Marco Pivetta [ 24/Jan/15 ]

We currently have a lot of locations in the code where we use list($values, $types) = $this->computeParameters(); (pseudo-code).

This leads to a lot of code duplication and complexity.

Maybe a Parameter VO may be used instead, or a ParameterCollection with a fixed $types and a mutable $values, and with minimal internal validation.





[DDC-3083] Persist/Flush silently fails when CTI is applied on an existing table Created: 12/Apr/14  Updated: 13/Apr/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.4.2
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Frank Liepert Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Given an existing table (= parent table) the integration of a new parent-child relationship with Class Table Inheritance (CTI) leads to a update problem.

First of all a child table is created with a foreign key to the parent table. Next, the discriminator column is added to the parent table. The discriminator map will be auto-generated.

The problem arises when trying to perform persist() and flush() on a child entity. Initially the child table is logically empty. However, the UnitOfWork triggers updateTable() which will fail since there is nothing to update. Instead, an upsert should be performed.

Another sneaky thing is that the repository will return the child class with the updated data after calling flush() on the same request. On the next request the child class is returned with the data loaded from the persister. Of course, the updated data is missing.



 Comments   
Comment by Marco Pivetta [ 13/Apr/14 ]

Frank Liepert do I understand this correctly if I say that you are trying to (pseudo) upcast an entity to a more specific subtype? That is unsupported by the ORM. Could you make just an example snippet of what you described in the issue?

Comment by Frank Liepert [ 13/Apr/14 ]

Marco Pivetta: You have understood really well. If you say that's not supported by the ORM then this is the answer. Still I think that upsert could solve solve the "problem" and I know that there are/have been discussions about upsert.

Right now I will continue to manually insert the missing rows in the child table. After this necessary step the ORM works as expected.

Nevertheless the real bug is that after persist() and flush() the entity manager returns the child object with the "persisted" data of the child table although there are in fact no rows in the child table.

$parentRepository = $em->getRepository('Parent');

$child = $parentRepository ->find(1);
$child->setChildPropertyA('foo');

$em->persist($child);
$em->flush();

$child = $parentRepository ->find(1);
var_dump($child->getChildPropertyA());
// string(3) "foo"

// But: There is no 'foo' in the child table!


/** 
 * NEW REQUEST
 */

$parentRepository = $em->getRepository('Parent');

$child = $parentRepository ->find(1);
var_dump($child->getChildPropertyA());
// NULL

Comment by Marco Pivetta [ 13/Apr/14 ]

Frank Liepert why are $child in the first request and $child in the second request different here? Are you manually changing the data at SQL level?

Comment by Frank Liepert [ 13/Apr/14 ]

Marco Pivetta as I have explained the persist() and flush() in the first request trigger an UPDATE command (Because there is already a row in the parent table?). Given that the child table was manually created before there are no rows on that table at that time and therefore nothing can be updated. Nevertheless the ORM triggers no error and $child looks like having been persisted. In the second request you'll notice that there haven't been persisted any of the data belonging to the child table.





[DDC-2983] TCI association not getting hydrated into sql statement Created: 14/Feb/14  Updated: 23/Mar/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.5
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Machete Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: orm
Environment:

MySQL, using DoctrineORMModule (zf2 integration)



 Description   

/**
 * @ORM\Entity
 * @ORM\Table(name="base")
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="discriminator", type="string")
 * @ORM\DiscriminatorMap({
 * "a" = "A",
 * "b" = "B",
 * })
 */
class Base
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;
}

/**
 * @ORM\Entity
**/
class A extends Base {
    /**
     * @ORM\ManyToOne(targetEntity="B", inversedBy="as")
     */
    protected $b;

    /**
     * @ORM\OneToMany(targetEntity="C", cascade={"persist"})
     */
    protected $cs;
}

/**
 * @ORM\Entity
**/
class B Extends Base {
    /**
     * @ORM\OneToMany(targetEntity="A", mappedBy="b")
     */
    protected $as;
}

/**
 * @ORM\Entity
**/
class C {
  // ...
}

Doing this:

$a = new A();
$b = new B();

$a->setB($b);
$b->addA($a);

var_dump($a->getB()); // outputs B (b not null!)
var_dump($b->getAs()) // outputs A (private $_elements => [0] class B)

$em->persist($a);
$em->persist($b);
$em->flush();

Leads to

integrity constraint violation, b_id can not be null

aka

INSERT INTO a (id, b_id), (123, null);

I have no idea why this happens. This works:

$a = new A();
$b = new B();

$a->setB($b);
$b->addA($a);

var_dump($a->getB()); // outputs B (b not null!)
var_dump($b->getAs()) // outputs A (private $_elements => [0] class B)

$em->persist($a);
$em->flush();
$em->persist($b);
$em->flush();


 Comments   
Comment by Benjamin Eberlei [ 23/Mar/14 ]

This most likely happens because the UnitOfWork tries to set the owner and reverse incorrectly due to an ordering issue.





[DDC-2954] Paginator loses items Created: 05/Feb/14  Updated: 12/Feb/14

Status: Awaiting Feedback
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3.4, 2.4.1
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Mariusz Jaskółka Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: Pagination, Paginator
Environment:

Linux and Windows, PHP 5, Oracle(OCI8)


Attachments: File LimitSubqueryOutputWalker.php     File LimitSubqueryOutputWalker_bugfix.php    

 Description   

Sometimes when when I use Paginator (Doctrine\ORM\Tools\Pagination\Paginator)

  • with query contains orderBy
  • with $fetchJoinCollection = true
  • lot of joins with toMany associations

there are too few items in result (no, it is not the end of list). There two situations:
1. I have four items on page 1 and two items on page 2 (pageLimit is 5). It is no so bad
2. I have four items on page 1 and there is no page 2 (while there should be 5 all items). This is very bad because I lose one item.

------------------------------------------------------------------
EDIT:
In function Paginator::getIterator there is variable $ids. In my situation it contains five numbers [34,26,34,15,12]. There is duplicated value 34 but ids of top-level entities should be distinct (as far as we do not use CROSS JOIN, or maybe I am wrong).

The Paginator::count function works correctly, it does not count duplicated values twice.

Statement that gets $ids is like following:
SELECT a.* FROM (SELECT DISTINCT ID2, BEGINTIME70 FROM (...) dctrn_result ORDER BY BEGINTIME70 DESC) a WHERE ROWNUM <= 5

------------------------------------------------------------------
EDIT 2 - Bugfix description:
The result items of the query is not unique because of
"SELECT DISTINCT col_with_id, order_by_column (...) ORDER BY order_by_column".
If we had items like following:
(1,A)
(1,B)
(1,B)
(2,C)

After DISTINCT operation the result would be:
(1,A)
(1,B)
(2,C)

But we want to have unique firs column, not pairs. That's why we should do "ORDER BY" before "DISTINCT" - not in the same time.
Please confirm if the solution is correct.



 Comments   
Comment by Marco Pivetta [ 05/Feb/14 ]

Mariusz Jaskółka this needs more details

Comment by Mariusz Jaskółka [ 06/Feb/14 ]

OK, I will try to find out where the problem is.

Comment by Mariusz Jaskółka [ 06/Feb/14 ]

I have edited description, maybe additional information will help.

Comment by Mariusz Jaskółka [ 07/Feb/14 ]

I send the bugfix in attachment. I will describe it soon.

Comment by Mariusz Jaskółka [ 07/Feb/14 ]

Bugfix version 2 - previously I did not notice that oracle loses order after DISTINCT operation. Thus I used GROUP BY.

Comment by Mariusz Jaskółka [ 11/Feb/14 ]

I do not know if I can change status of this issue from "Awaiting Feedback". I can not see such option





[DDC-2918] get statements from ORM Created: 15/Jan/14  Updated: 15/Jan/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: None
Security Level: All

Type: New Feature Priority: Major
Reporter: Flip Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

When doing `persist()` and then `flush()` the statements are not accessible anymore after the operation is done.

The EntityManager uses an EntityPersister. When looking at the BasicEntityPersister->executeInserts() a new statement is created but it's not saved as part of another object.
https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php#L260

Benefit:
When having access to the statements afterwards, all the following methods would be available:
http://www.php.net/manual/en/class.pdostatement.php

Most interesting are rowCount and error related methods.



 Comments   
Comment by Steve Müller [ 15/Jan/14 ]

Flip AFAIK you can use an SQL Logger for this which has to be set in the connection. The ORM testsuite makes use of this, too. See this example: https://github.com/doctrine/doctrine2/blob/master/tests/Doctrine/Tests/ORM/Functional/OneToOneEagerLoadingTest.php#L155

Comment by Flip [ 15/Jan/14 ]

Yes sure, but using a logger will be a strange way to pipe it back into business logic.

For example it's possible to do remove() on a proxy so you don't know if the row was present or not.

or another situation ..

when dealing with concurrency .. somebody else might have deleted the row already ..





[DDC-2851] Allow set custom collection initializer at runtime Created: 12/Dec/13  Updated: 12/Dec/13

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.4.1
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: Konstantin Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Use case: Company, Category, CompanyCategory entities. We are loading set of companies and should initialize Company.companyCategories collection with joined categories, which ordered by Company.title.

I cann't do it via Criteria API, it doesn't supports joins. + I should return same PersistentCollection instance (Company.companyCategories used in Symfony2 forms).

Current workaround:

    public function loadCompanyCategoriesCollectionForCompany(Company $company)
    {
        $companyCategories = $this->_em->createQueryBuilder()
            ->select('cc')
            ->from('OloloCompaniesBundle:CompanyCategory', 'cc')
            ->join('cc.category', 'c')
            ->addSelect('c')
            ->orderBy('c.title')
            ->where('cc.company = :company')
            ->setParameter('company', $company)
            ->getQuery()
            ->getResult()
        ;

        $coll = $company->getCompanyCategories();
        foreach ($companyCategories as $companyCategory) { /* @var $coll \Doctrine\ORM\PersistentCollection */
            $coll->hydrateAdd($companyCategory);
        }
        $coll->setInitialized(true);
    }

What would be nice: native API for setting custom initializers.






[DDC-2852] Enclose subquery with parenthesis in from clause (QueryBuilder) Created: 12/Dec/13  Updated: 12/Dec/13

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Matthieu Pécro Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: from, orm, parenthesis, querybuilder,, subquery


 Description   

Hi

In QueryBuilder from clause, when argument is a QueryBuilder (not a string like a table), there are not parenthesis enclosure on the subquery.

Ex:
$subqb->select('myfield')->from('mytable');
$qb->from($sub, 'myalias)

DQL is : SELECT myfield FROM SELECT myField FROM mytable myalias. This is not working on MySQL.

It should be : SELECT myfield FROM (SELECT myField FROM mytable) myalias.



 Comments   
Comment by Christophe Coevoet [ 12/Dec/13 ]

I don't understand your statement This is not working on MySQL. after giving a DQL statement. MySQL does not support any DQL. It runs SQL.

And DQL does not support using a subselect in the FROM clause





[DDC-2826] Add support for mapping collections of embeddable objects Created: 28/Nov/13  Updated: 08/Feb/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: New Feature Priority: Major
Reporter: songoko songowan Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: collection, orm, value-objects


 Description   

In Hibernate we can do something like this:

    @Entity
    public class User {
       [...]
       public String getLastname() { ...}
    
       @ElementCollection
       @CollectionTable(name="Addresses", joinColumns=@JoinColumn(name="user_id"))
       @AttributeOverrides({
          @AttributeOverride(name="street1", column=@Column(name="fld_street"))
       })
       public Set<Address> getAddresses() { ... } 
    }
    
    @Embeddable
    public class Address {
       public String getStreet1() {...}
       [...]
    }

Basically a collection of value objects is mapped to a new table. Currently Doctrine2 is on its way to support value objects

However, this implementation won't support mapping a collection of objects to a new table and the only way to circumvent this issue is to treat the address an an entity and use an one-to-many unidirectional relationship through a many-to-many join table



 Comments   
Comment by Doctrine Bot [ 08/Feb/14 ]

A related Github Pull-Request [GH-835] was closed:
https://github.com/doctrine/doctrine2/pull/835





[DDC-2763] Inheritance. CTI & STI. Improve lazy load associated entity, when target entity in association mapping is not last leaf in class hierarchy. Created: 27/Oct/13  Updated: 27/Oct/13

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Artur Eshenbrener Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: inheritance


 Description   

If we look inside documentation, we can see this:

There is a general performance consideration with Class Table Inheritance: If the target-entity of a many-to-one or one-to-one association is a CTI entity, it is preferable for performance reasons that it be a leaf entity in the inheritance hierarchy, (ie. have no subclasses). Otherwise Doctrine CANNOT create proxy instances of this entity and will ALWAYS load the entity eagerly.

I think it can be improved, if we will load only discriminator column value for resolve target class name, instead of loading whole entity. When we perform query from root entity, dicriminator value is already present in fetched database row.
What do you think?



 Comments   
Comment by Marco Pivetta [ 27/Oct/13 ]

Queries to fetch the discriminator column cannot be avoided (that's a limitation we can't workaround as far as I know).

What can be improved is avoiding instantiation of the joined results, and instead keep a proxy and a copy of the data for deferred hydration. That would allow avoiding recursive queries which are seen quite often when referencing the root of a STI/JTI

Comment by Artur Eshenbrener [ 27/Oct/13 ]

Queries to fetch the discriminator column cannot be avoided (that's a limitation we can't workaround as far as I know).

Of course, but fetching the discriminator value will produce less overhead than loading whole entity (with recursive loading joined entities). And, when you querying from root entity (with mapped sicriminator column), discriminator value already present in db result row (no need to extra query for dicriminator value).

What can be improved is avoiding instantiation of the joined results, and instead keep a proxy and a copy of the data for deferred hydration. That would allow avoiding recursive queries which are seen quite often when referencing the root of a STI/JTI

The result of my proposal will ability to get proxy class without loading whole entity.





[DDC-2733] DefaultQuoteStrategy BUG on Oracle Created: 10/Oct/13  Updated: 26/Oct/13

Status: Open
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers, ORM
Affects Version/s: 2.3.4
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Pablo Santiago Sánchez Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Symfony on all platforms (Windows, Linux and Mac)
Oracle 11g



 Description   

There's a bug on the DefaultQuoteStrategy when used with Oracle. The getColumnAlias created an invalid alias.

The name of the column had 31 chars, with _ being the 3rd. Column was 101 on the query. Resulting name of the alias started with _, which is invalid name for Oracle.

Example:
CO_SEQ_NOMEGIGANTEPRAKCTMEUDEUS

Alias formed was
_SEQ_NOMEGIGANTEPRAKCTMEUDEUS101

HOW TO FIX:
replace the regex on line 135:
original:
$columnName = preg_replace('/[^A-Za-z0-9_]/', '', $columnName);
fixed:
$columnName = preg_replace('/[^A-Za-z0-9]/', '', $columnName);



 Comments   
Comment by Rudi Uhrig Neto [ 16/Oct/13 ]

Hi there!

I would like to do a contribuition for this issue! I'm not safe with my sugestion, but someone can be helped!

I'm working with 2.4.0 Doctrine Version and I'm facing the same problem, "invalid character" due the function that make a cut off from the begining from alias.

My sugestion to solve this problem is maintain the separator '_' between alias name, but cutting off from the ending alias and reserv the lenght to the counter.

See bellow my modification code at DefaultQuoteStrategy::getColumnAlias() line 130, just replace all lines from function by these below:

DefaultQuoteStrategy.php
public function getColumnAlias($columnName, $counter, AbstractPlatform $platform, ClassMetadata $class = null)
{
    // 1 ) Trim the column alias to the maximum identifier length of the platform.
    //     If the alias is to long, characters are cut off from the ending subtracting the chars reserved to counter.
    // 2 ) Concatenate column name and counter
    // 3 ) Strip non alphanumeric characters
    // 4 ) Prefix with "_" if the result its numeric
    $columnName = substr($columnName, 0, $platform->getMaxIdentifierLength() - strlen($counter));
    $columnName = $columnName . $counter;
    $columnName = preg_replace('/[^A-Za-z0-9_]/', '', $columnName);
    $columnName = is_numeric($columnName) ? '_' . $columnName : $columnName;
      
    return $platform->getSQLResultCasing($columnName);
}

What do you guys think?

Comment by Pablo Santiago Sánchez [ 16/Oct/13 ]

Rudi, prefixing it with _ would keep the problem on Oracle. Since that name is for aliasing pourposes only, the _ char is useless.

I just remembered another possible situation: fields should not start with numbers!

Comment by Rudi Uhrig Neto [ 16/Oct/13 ]

Pablo,

The changes in my sugestion code don't consider the prefix '_', indepedent of the characteres in alias column name, the function will remove the last characteres from alias... see an example with column name DT_VERIFICACAO_SITUACAO_ACESSO.

The current code create a sql:
DT_VERIFICACAO_SITUACAO_ACESSO AS _VERIFICACAO_SITUACAO_ACESSO23,

My sugestion will produce:
DT_VERIFICACAO_SITUACAO_ACESSO AS DT_VERIFICACAO_SITUACAO_ACES23,

Comment by Pablo Santiago Sánchez [ 18/Oct/13 ]

Oh, sorry, my mistake. Your solution sounds better.

Since there's still no solution from the Doctrine Team, I'm iusing my own QuoteStrategy. Hope this bug gets fixed soon.

Comment by Benjamin Eberlei [ 26/Oct/13 ]

Fabio B. Silva Can you comment on Rudi Uhrig Neto solution? Its easily changed, but I am wondering if this is backwards compatible. I would want to merge the fix back to 2.3 and 2.4. Branch is ready to be committed for me locally.





[DDC-2697] ObjectHydrator::hydrateRowData fails to hydrate first fetch joined entity Created: 20/Sep/13  Updated: 06/Dec/13

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3, 2.4
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Austin Morris Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: orm
Environment:

All



 Description   

Let's say I have accounts, contacts, and contact types. Any given contact can have be any kind of contact type to any account. This is all managed through an account_contacts table with a 3-way composite PK of the contact_id, account_id, and type_id.

All of this translates to 4 entities, the account, contact, type, and accountContact entity. The id of the accountContact entity is the three other entities which is holds.

When I use query builder to retrieve the accountContacts based on some condition, and also fetch join contacts, accounts, and types so that they are eagerly loaded, the ObjectHydrator fails to load the first accountContact returned.

This is because the first time through hydrateRowData, the fetch joined entities are hydrated first. The problem is $this->_rsm->parentAliasMap[$dqlAlias] does not contain an entry for the accountContact (root entity). Not until an accountContact is hydrated does that get set. In the mean time, the other three entities were set to null because there is no parent alias yet (in version 2.4, this is line 405.

Subsequent loops through hydrateRowData work because by this time the parent alias is set. But that first row returned is always an accountContact containing three null objects.



 Comments   
Comment by Benjamin Eberlei [ 26/Oct/13 ]

Austin Morris Can you show the QueryBuilder select clause you are using? Have you tried sorting the accountContacts first?

$qb->select('accountContacts, contact, account, type')

This way it should definately work, and then there is also some attempts to resort this way if you dont have that, but its not always working.

Comment by Austin Morris [ 06/Dec/13 ]

Sorry, I don't have the original select clause. I ended up doing something different and can't seem to find my original code.

Comment by Benjamin Eberlei [ 06/Dec/13 ]

I have another person that reported a simliiar bug with reproducable test case. I hope to investigate this very soon.





[DDC-2659] Notice: Undefined index: sourceToTargetKeyColumns in /doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister .php line 1180 Created: 08/Sep/13  Updated: 08/Sep/13

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Taylor Kaplan Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: orm
Environment:

Symfony2 With PHP 5.5 on Ubuntu 12.04 LTS using Apache 2


Attachments: File Client.php     File ClientFixtures.php     File User.php     File UserFixtures.php    

 Description   

I am getting this error:

 Notice: Undefined index: sourceToTargetKeyColumns

When I try to load my data fixture. There are two ordered fixtures that I'm dealing with: Clients and Users. The client datafixture looks like:

    	/**
    	 * {@inheritDoc}
    	 */
    	 public function load(ObjectManager $manager)
    	 {
    
    		for($index = 0; $index < 224; $index ++)
    		{
    			$client = new Client();
    			$manager->persist($client);
                        $this->addReference($index . 'Client', $client);
    		}
    
    		$manager->flush();
    		$manager->clear();
    	 }
    
    	 public function getOrder()
    	 {
    	 	return 0;
    	 }

While the user data fixture looks like:

     $user = New User();
     $client = $this->getReference($index . 'Client');

     // This line is causing the problem
     $client->setUser($user);

For whatever reason, I don't seem to be having issues with any of my other fixtures. Just this one. I've doubled check the entity relationships which are shown bellow.

My Client.php entity:

    /**
     * @ORM\ OneToOne(targetEntity="User", mappedBy="clientAccount")
     */
    protected $user;

My User.php entity:

    /**
     * @ORM\ OneToOne(targetEntity="Client", inversedBy="user")
     */
    protected $clientAccount;

There seems to be a bug with the return value of getAssociationMapping() for special conditions when implemented in BasicEntityPersister. The files for my fixtures and entities for this project have been attached.






[DDC-2649] Hydration in bidirectional, OneToOne relationship, PK as FK for owning side, is problematic Created: 04/Sep/13  Updated: 04/Sep/13

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3.4
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Jérôme Viveret Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: FK, OneToOne, PK, bidirectional


 Description   

I am referring to this situation https://gist.github.com/anonymous/6435032

The following problem occur:

When using HardCover as the root entity of a query, the ObjectHydrator fails to properly register the first [HardCover of the resultset]'s Book. Only the first. The following HardCover have their Books correctly linked. The inverse situation (using Book as the root entity) works fine.

When some other entity (say WoodenPart) is linked to HardCover via a ManyToOne association, using WoodenPart as a query root results in no WoodenPart have their HardCover registered.






[DDC-2642] GROUP BY with inherited entity (which is also in SELECT clause) does not list columns from inheriting entities Created: 30/Aug/13  Updated: 30/Aug/13

Status: Open
Project: Doctrine 2 - ORM
Component/s: DQL, ORM
Affects Version/s: 2.3.4
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Ondřej Mirtes Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

PostgreSQL



 Description   

The summary pretty much sums it up.

Code example: https://gist.github.com/ondrejmirtes/6388434






[DDC-2631] Replacing object in a OneToOne with OrphanRemoval=true isn't working as expected Created: 23/Aug/13  Updated: 26/Nov/13

Status: Awaiting Feedback
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.4
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Felipe Guaycuru Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: orm
Environment:

PHP 5.4



 Description   

So I have a class defined like this:

class PhoneSettings {
[...]

/**

  • @OneToOne(targetEntity="Medium", cascade= {"persist", "remove"}

    , orphanRemoval=true)

  • @JoinColumn(name="medium_id", referencedColumnName="medium_id", nullable=true, onDelete="SET NULL")
    **/
    protected $medium = null;

[...]
}
And class Medium has no reference to the class Settings.

Now suppose I have a $Settings object that is already persisted and has been correctly loaded. Also suppose that the $Settings object has a $medium (that is, $Settings->medium = $OldMedium)

Now suppose I do:

$Settings->medium = $NewMedium;
Where $NewMedium is a different Medium object.

When I persist $Settings, Doctrine does delete $OldMedium from the DB, but the problem is that it also deletes $NewMedium ...

I have tried removing onDelete="SET NULL", but then I receive a "cannot delete, constraint failed" error...






[DDC-2630] Filters with joined inheritance Created: 22/Aug/13  Updated: 09/Jan/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Florian Vilpoix Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: inheritance, sql-walker, sqlfilter


 Description   

Hello,

I'm trying to use SQLFilter with a Joined Inheritance, and the sql Walker never applies filters on the sub-class, even if I make my SELECT on the sub-class or the root.

In the SqlWalker, the methods 'generateFilterConditionSQL' says :

// The classes in the inheritance will be added to the query one by one,
// but only the root node is getting filtered

I don't understand why, and I would like to know if there is any way to apply filters to subclasses in joined-inheritance.

Thanks a lot



 Comments   
Comment by Menno Holtkamp [ 09/Jan/14 ]

Are you sure you apply the filter on the root Entity? This discussion might be usefull:
https://groups.google.com/forum/#!topic/doctrine-user/e1cPZOorfaQ





[DDC-2590] Class inheritance - left join between child and parent entities Created: 06/Aug/13  Updated: 25/Mar/14

Status: Awaiting Feedback
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3.1, 2.3.2, 2.3.3, 2.3.4
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Tomáš Ďuračka Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: inheritance, joins, orm, sql-walker


 Description   

The piece of code given under creates wrong sql to me.

Module is parent entity for BusinessModule entity. Category is joined with BusinessModule.

Module entity is only left joined to its child entity and that's the problem because it contains a field "name" used for filtering. So even if there is no module having the name, categories are still included.

I need the parent entity to be inner joined to child entity not left joined.

File doctrine2/lib/Doctrine/ORM/Query/SqlWalker.php line 353:

// If this is a joined association we must use left joins to preserve the correct result.
$sql .= isset($this->queryComponents[$dqlAlias]['relation']) ? ' LEFT ' : ' INNER ';
$qb->select('c')
->from('Category', 'c')
->join('c.module', 'm', 'WITH', 'm.name = :moduleName')
->setParameter('moduleName', $moduleName);
SELECT c0_.category_id AS category_id0, c0_.title AS title1, c0_.h1 AS h12, c0_.alias AS alias3,
c0_.insertion_fee AS insertion_fee4, c0_.description AS description5, c0_.parent_category_id AS
parent_category_id6, c0_.module_id AS module_id7 
FROM category c0_ 
INNER JOIN business_module b1_ ON c0_.module_id = b1_.module_id 
LEFT JOIN module m2_ ON b1_.module_id = m2_.module_id AND (m2_.name = ?)


 Comments   
Comment by Marek Štípek [ 06/Nov/13 ]

I am experiencing the same issue. The workarround could be to use LEFT JOIN with IS NOT NULL condition... But it also doesnt work after this commit
https://github.com/doctrine/doctrine2/commit/d9c1782a4f6d46f66e9deb2c375830f9192d4482 (i had to revert to dev-master#13c1efb240dd0af25ad0abe230df98ec895892c7)





[DDC-2595] UoW is not supposed to trigger the post-load event for uninitialized proxies. Created: 06/Aug/13  Updated: 06/Aug/13

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Juti Noppornpitak Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: None


 Description   

When one entity have multiple nested levels and associated to 700+ other entities, the ORM exhausts a large amount of memory and execution time which exceeds either the memory limit or the maximum execution time.

Prerequisite:

1. generate an entity, named "Mr. G", with 4 nested levels of association.
2. ensure that the generated entity associating to 700+ entities.
3. create a post-load event listener which may or may not be restricted to uninitialized proxies.

How to Reproduce:

1. have a code to load the "Mr. G" entity.
X. (Done)

Notes:
The initial investigation indicates that UnitOfWork should not trigger the post-load event for uninitialized proxies.

One thing worth-mentioning is that if the event listener ignores all proxies, we will not have this problem. However, some properties (e.g., ones of type TEXT/BLOB) are not loaded into normal entities but they are loaded into the proxies.






[DDC-2567] auto generated index name cannot be overriden with annotation Created: 23/Jul/13  Updated: 23/Jul/13

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3.4
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Nicolas Ricci Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Hi,

I have an unexpected behaviour when generating SQL from an entity using annotation.

The default indexes name (generated by _generateIdentifierName) are automatically overwriting the name I have specified in my entity.

I have patched the following file https://github.com/doctrine/dbal/blob/master/lib/Doctrine/DBAL/Schema/Table.php

with:
// check for duplicates
foreach ($this->_indexes as $idxKey => $existingIndex) {
if ($indexCandidate->isFullfilledBy($existingIndex))

{ //return $this; // old implementation unset($this->_indexes[$idxKey]); }

}

but I don't think this is the correct way forward.

Let me know if you require more information

Thanks






[DDC-2528] Extracting entities through DQL query resets the previous associations Created: 24/Jun/13  Updated: 25/Jun/13

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Koustubh Sinhal Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Windows 8



 Description   

I have the entities Purchase(owning side) and Product(inverse side) sharing bidirectional many to many relation. Now whatever associations I build between product and purchase entity, those associations are erased if by mistake I happen to run a join query between the products and purchase table. For example look at this code.

$purc = $em->find("\ZC\Entity\Purchase", 1); //Existing purchase entity
//Now this purchase entity is linked to 2 products through the join table
$prod = new \ZC\Entity\Product();
$prod->name= "newly";
$purc->addProduct($prod); //Added a new product to the collection
// print(count($purc->products));
$dql = "SELECT b,c FROM \ZC\Entity\Purchase b join b.products c where      b.id = 1";
$query = $this->entityManager->createQuery($dql);
$purc2 = $query->getResult()[0]; //Now this is same as $purc
print(count($purc->products));   //again prints 2

As you can see, when I have added a new entity $prod to the $purc, the number of products linked to $purc should have increased to 3. It seems the join overrides the previous associations formed. More strange is if I had fetched the products related to $purc from the tables before the join query(the commented code before dql), then the last print statement would have given 3.
I am facing a lot of similar issues.






[DDC-2495] Partial objects not working with STI Created: 10/Jun/13  Updated: 11/Jun/13

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3.4
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Radoslaw Ejsmont Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: STI, dql, orm, partial
Environment:

Symfony2 project, Doctrine ORM with MySQL database backend


Attachments: File CrossVial.php     File Entity.php     File InjectionVial.php     File Stock.php     File StockVial.php     File Vial.php    

 Description   

When I try to create a query retrieving partial objects of a root class in single table inheritance hierarchy, the resulting SQL includes all fields from the whole class hierarchy.

DQL:
SELECT partial v.

{id, setupDate, flipDate}

FROM VIB\FliesBundle\Entity\Vial v WHERE v.id IN (1,2,3,4,5,6,7,8,9,10)

SQL:
SELECT v0_.setupDate AS setupDate0, v0_.flipDate AS flipDate1, v0_.id AS id2, v0_.type AS type3, v0_.parent_id AS parent_id4, v0_.position_id AS position_id5, v0_.prevPosition_id AS prevPosition_id6, v0_.incubator_id AS incubator_id7, v0_.stock_id AS stock_id8, v0_.male_id AS male_id9, v0_.virgin_id AS virgin_id10, v0_.targetStock_id AS targetStock_id11, v0_.targetStockVial_id AS targetStockVial_id12 FROM Vial v0_ WHERE (v0_.id IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) AND v0_.type IN ('vial', 'stock', 'cross', 'injection')



 Comments   
Comment by Fabio B. Silva [ 10/Jun/13 ]

Could you please provide your entities ?

Thanks

Comment by Radoslaw Ejsmont [ 11/Jun/13 ]

This is the whole class hierarchy.

Comment by Radoslaw Ejsmont [ 11/Jun/13 ]

I have actually noticed, that the "partial" keyword is ignored even for entities that are not using any inheritance schema. So it seems that this keyword is generally ignored.

Right now the following query:

SELECT e, partial p.

{id}

, o, s FROM VIB\FliesBundle\Entity\StockVial e LEFT JOIN e.parent p LEFT JOIN e.position o LEFT JOIN e.stock s WHERE e.setupDate > :date AND e.trashed = false ORDER BY e.setupDate DESC ORDER BY e.id DESC

would result in the following SQL:

SELECT v0_.setupDate AS setupDate0, v0_.flipDate AS flipDate1, v0_.notes AS notes2, v0_.size AS size3, v0_.labelPrinted AS labelPrinted4, v0_.trashed AS trashed5, v0_.temperature AS temperature6, v0_.id AS id7, v1_.id AS id8, r2_.rackRow AS rackRow9, r2_.rackColumn AS rackColumn10, r2_.id AS id11, s3_.name AS name12, s3_.genotype AS genotype13, s3_.notes AS notes14, s3_.vendor AS vendor15, s3_.infoURL AS infoURL16, s3_.verified AS verified17, s3_.id AS id18, v0_.type AS type19, v0_.parent_id AS parent_id20, v0_.position_id AS position_id21, v0_.prevPosition_id AS prevPosition_id22, v0_.incubator_id AS incubator_id23, v0_.stock_id AS stock_id24, v1_.type AS type25, v1_.parent_id AS parent_id26, v1_.position_id AS position_id27, v1_.prevPosition_id AS prevPosition_id28, v1_.incubator_id AS incubator_id29, v1_.stock_id AS stock_id30, v1_.male_id AS male_id31, v1_.virgin_id AS virgin_id32, v1_.targetStock_id AS targetStock_id33, v1_.targetStockVial_id AS targetStockVial_id34, r2_.rack_id AS rack_id35, s3_.sourceCross_id AS sourceCross_id36 FROM Vial v0_ LEFT JOIN Vial v1_ ON v0_.parent_id = v1_.id AND v1_.type IN ('vial', 'stock', 'cross', 'injection') LEFT JOIN RackPosition r2_ ON v0_.position_id = r2_.id LEFT JOIN Stock s3_ ON v0_.stock_id = s3_.id WHERE (v0_.setupDate > '2013-04-11' AND v0_.trashed = 0) AND v0_.type IN ('stock') ORDER BY v0_.setupDate DESC, v0_.id DESC

Please note that ALL properties of parent have been included in the generated SQL.

You can find the whole project (Symfony2) on github: https://github.com/rejsmont/LabDB

Best,

R.

Comment by Radoslaw Ejsmont [ 11/Jun/13 ]

I have noticed that using the setHint(Doctrine\ORM\Query::HINT_FORCE_PARTIAL_LOAD, 1) forces partial load, however then even the entities I want loaded entirely (with proxied references) are partially loaded (i.e. all the references are forced to null, unless explicitly loaded via join).





[DDC-2452] Additional `WITH` condition in joins between JTI roots cause invalid SQL to be produced Created: 16/May/13  Updated: 27/Mar/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: DQL, ORM
Affects Version/s: Git Master
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Marco Pivetta Assignee: Marco Pivetta
Resolution: Unresolved Votes: 0
Labels: dql, sql-walker
Environment:

irrelevant



 Description   

Given a simple Joined Table Inheritance like following:

/**
 * @Entity @Table(name="foo") @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="discr", type="string")
 * @DiscriminatorMap({"foo" = "DDC2452Foo", "bar" = "DDC2452Bar"})
 */
class DDC2452Foo
{
    /** @Id @Column(type="integer") @GeneratedValue */
    public $id;
}

/** @Entity @Table(name="bar") */
class DDC2452Bar extends DDC2452Foo
{
}

Following DQL

SELECT foo1 FROM DDC2452Foo foo1 JOIN DDC2452Foo foo2 WITH 1=1

Will produce broken SQL:

SELECT
    f0_.id AS id0, f0_.discr AS discr1 
FROM 
    foo f0_ 
LEFT JOIN bar b1_ 
    ON f0_.id = b1_.id 
LEFT JOIN foo f2_ 
LEFT JOIN bar b3_ 
    ON f2_.id = b3_.id 
    ON (1 = 1)

(please note the duplicate `ON` in the SQL)

That is caused because of the SQL walker producing the JTI filter with already the `ON` clause in it.

That happens because the JTI join conditions are added in https://github.com/doctrine/doctrine2/blob/2.4.0-BETA2/lib/Doctrine/ORM/Query/SqlWalker.php#L823-L825 (`walkRangeVariableDeclaration`), while the additional defined `WITH` conditions are considered in `walkJoinAssociationDeclaration` later on.

Added a test case and fix at https://github.com/doctrine/doctrine2/pull/668






[DDC-2449] Amazon Redshift Support Created: 15/May/13  Updated: 15/May/13

Status: Awaiting Feedback
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: New Feature Priority: Major
Reporter: Kirill Fuchs Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Amazon Redshift



 Description   

It would be nice to get doctrine compatible with Amazon Redshift. It uses a Postgres connector but there are some differences. I'm currently facing an issue with the primary id, in Redshift the generation of an id is different from Postgres and so I'm getting errors associated with generating an id.

Here are some references that might be useful:
node-orm faced the same issue and seems like they figured it out: https://github.com/dresende/node-orm2/issues/39

Amazon Manual:
http://awsdocs.s3.amazonaws.com/redshift/latest/redshift-dg.pdf






[DDC-2411] Null values get reset when rehydrating an already managed entity Created: 23/Apr/13  Updated: 09/May/13

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Simon Garner Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: hydration


 Description   

Scenario:

1) You have an entity with a ManyToOne relation (and probably other kinds too, but this is all I have tested) to another entity which is nullable. For example, let's say you have a Book entity which has an "illustrator" field which refers to a Person entity, representing the person who illustrated the book. If the book is not illustrated then you set the field to null.

2) You fetch a Book (by ID) which has its illustrator set to a particular Person.

3) You set that Book's illustrator to null.

4) Without flushing, you fetch the Book again, using different criteria: for example, by title. Because entities are Identity Mapped, this will run a query but then locate the same instance in memory, and try to hydrate that instance with the old data it just fetched.

5) Any fields on the instance that have modified values retain their new values (for example, if we changed the illustrator to a different Person, this would be retained), BUT any fields on the instance which are null get overwritten with the old data (so if we previously set the illustrator to null, without flushing, it would now be reset to the Person value that it had before).

There seems to be a mistaken assumption here that null values are fields that have not been hydrated, when this is not necessarily the case. Is this the intended behaviour?

The code that causes this behaviour is here: https://github.com/doctrine/doctrine2/blob/e561f47cb2205565eb873f0643637477bfcfc2ff/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php#L471

If you are wondering why anybody would want to fetch the entity again in step 4, my use case for this is the Symfony Validator (but I presume there could be others).

If there are any unique constraints (Symfony ones, not Doctrine ones) on the entity, e.g. if we had a unique constraint on the Book title field, then when validating the Book the Symfony Validator would check if there are already any Book entities with the same title as the Book we're validating. It will find the Book that we are working with, and because entities are identity mapped, it will act upon the same instance, and the situation above occurs.

Code example:

<?php

// Create some entities

$john = new Person();
$john->setName('John Smith');

$jane = new Person();
$jane->setName('Jane Jones');

$joe = new Person();
$joe->setName('Joe Bloggs');

$book = new Book();
$book->setId(123);
$book->setTitle('Book Title');
$book->setIllustrator($john);
$book->setAuthor($jane);

$em->persist($john);
$em->persist($jane);
$em->persist($joe);
$em->persist($book);
$em->flush();

// Now let's try modifying the book

$book = $bookRepository->find(123);
$book->getIllustrator(); // returns Person "John Smith"
$book->getAuthor(); // returns Person "Jane Jones"

// make some changes
$book->setIllustrator(null); // illustrator is now null
$book->setAuthor($joe); // author is now "Joe Bloggs"

// now validate our changes with Symfony Validator
// note: the same effect can also be observed with
// $test = $bookRepository->findBy('title', 'Book Title');
$validator->validate($book);

// what happened to our book??
$book->getIllustrator(); // returns Person "John Smith" <- should be null
$book->getAuthor(); // returns Person "Joe Bloggs" <- correctly retains the new value



 Comments   
Comment by Fabio B. Silva [ 24/Apr/13 ]

Hi Simon,

Could you please try to write a failing test case or paste your entities ?

Cheers

Comment by Benjamin Eberlei [ 09/May/13 ]

Verified by code review that this issue exists, but it will be very tricky to fix, because the null check is there for other reasons as well.





[DDC-2401] INDEX BY not working on multiple columns Created: 16/Apr/13  Updated: 18/Apr/13

Status: Open
Project: Doctrine 2 - ORM
Component/s: Documentation, ORM
Affects Version/s: 2.3.3
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Quintenvk Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Zip Archive Testcase.zip    

 Description   

According to the docs on this page:
http://docs.doctrine-project.org/en/latest/reference/dql-doctrine-query-language.html#using-index-by

The following "multi-dimensional index" should be perfectly possible, with a default hydration mode:
SELECT b as business, p as product FROM Businesses b INDEX BY b.id JOIN Products p WITH b.id = p.businessid INDEX BY p.id

However, b.id is completely ignored (it is a numeric primary key).

I tried to go further, giving 2 products a matching barcode and indexing by barcode and then a (unique, numeric) productid. Only the barcode worked as a key and only one of the products with a matching barcode was selected. I used this query to test:
SELECT p FROM Products p INDEX BY p.barcode JOIN p.businessid b INDEX BY p.id

I also flagged the docs, because I don't think a userid should/could be starting from 0.



 Comments   
Comment by Fabio B. Silva [ 18/Apr/13 ]

Hi Quintenvk

Could you please try to write a failing test case ?

Thanks

Comment by Quintenvk [ 18/Apr/13 ]

I added a testcase. Please note that the database settings are to be configured in Core/simplys/simplys.php, and that the dump is in dummy.sql.

Apart from that all should run well immediately.

Comment by Quintenvk [ 18/Apr/13 ]

Fabio,

Please check the zip I just attached. I hope this helps you in finding the problem.

Thanks,
Quinten

Comment by Fabio B. Silva [ 18/Apr/13 ]

Thanks Quintenvk,

SELECT p.barcode, p.id, p.name FROM \core\Simplys\Entity\Products p INDEX BY p.barcode JOIN p.businessid b INDEX BY p.id

In this DQL you are trying to index by scalar values,
I think we does not support that, and a single dimensional array is the expected result in this case.

Also the INDEX BY documentations seems wrong to me.

The given DQL :

 SELECT u.id, u.status, upper(u.name) nameUpper FROM User u INDEX BY u.idJOIN u.phonenumbers p INDEX BY p.phonenumber 

Show the following result :

array
  0 =>
    array
      1 =>
        object(stdClass)[299]
          public '__CLASS__' => string 'Doctrine\Tests\Models\CMS\CmsUser' (length=33)
          public 'id' => int 1
          ..
      'nameUpper' => string 'ROMANB' (length=6)
  1 =>
    array
      2 =>
        object(stdClass)[298]
          public '__CLASS__' => string 'Doctrine\Tests\Models\CMS\CmsUser' (length=33)
          public 'id' => int 2
          ...
      'nameUpper' => string 'JWAGE' (length=5)

Which IMHO represents another DQL, something like :

 SELECT u, p , upper(u.name) nameUpper FROM User u INDEX BY u.id JOIN u.phonenumbers p INDEX BY p.phonenumber
Comment by Quintenvk [ 18/Apr/13 ]

Thanks for your reply Fabio.
Do you think there could be alternatives (apart from a foreach-loop) to achieve the expected result?

Thanks,
Quinten

Comment by Fabio B. Silva [ 18/Apr/13 ]

Not sure if it's exactly the result you need but you can try

Something like :

SELECT p, b FROM \core\Simplys\Entity\Products p INDEX BY p.barcode JOIN p.businessid b INDEX BY p.id

or something like :

SELECT PARTIAL p.{id, barcode, name}, b.{id, attributesYouNeed} FROM \core\Simplys\Entity\Products p INDEX BY p.barcode JOIN p.businessid b INDEX BY p.id

And than :

$result = $query->getArrayResult();
Comment by Quintenvk [ 18/Apr/13 ]

Both produce the same result as the query I had. I think i'll move on to loops after a bit more research, too bad it can't be done (at least for now) though... Would've been nice.

Thanks for your help though!





[DDC-2337] Allow an entity to use its own persister to take advantage of DB level features if necessary Created: 06/Mar/13  Updated: 06/Mar/13

Status: Open
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers, ORM
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: New Feature Priority: Major
Reporter: Nathanael Noblet Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File persister.patch    

 Description   

I have a situation where I wanted a single table to use INSERT DELAYED. Its an audit log table where I expect each http request to generate many inserts for. In an effort to not over tax the system I implemented a custom Entity Persister so that it would work. This obviously doesn't work with all mapping drivers. However if this is a feature that you think is worth integrating I will fork it on github and complete the implementation alongside any changes/improvements requested...






[DDC-2254] Exporting and restoring a query. Created: 23/Jan/13  Updated: 04/May/13

Status: Open
Project: Doctrine 2 - ORM
Component/s: Documentation, DQL, ORM
Affects Version/s: Git Master, 2.3.2
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Dries De Peuter Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: dql, rebuild, restore, save
Environment:

OSX



 Description   

When you have a queryBuilder and you want to break it down using getDQLParts, You can't restore it by looping over the parts and adding them.

This is what I am doing:

$parts = $qb->getDQLParts();

// save the parts and use them in a different environment.

$newQb = $em->createQueryBuilder();
foreach ($parts as $name => $part) {
  $newQb->add($name, $part);
}


 Comments   
Comment by Dries De Peuter [ 23/Jan/13 ]

I wrote a test showing the issue.

https://github.com/NoUseFreak/doctrine2/commit/8574b79fd3d245532bbe7e310c5cbe083892057a

Comment by Benjamin Eberlei [ 04/May/13 ]

This is not a bug, because restoring queries is not yet a feature of the QueryBuilder. Marking as possible improvement for future.





[DDC-2248] Expire result cache functionality not implemented Created: 19/Jan/13  Updated: 19/Jan/13

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3, 2.3.1, 2.3.2
Fix Version/s: None

Type: Documentation Priority: Major
Reporter: Piotr Niziniecki Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

According to documentation expireResultCache, should force cache to update but it's not working... Why? Because functionality is not implemented. You can set _expireResultCache variable, but there is no place where this variable is being checked.



 Comments   
Comment by Marco Pivetta [ 19/Jan/13 ]

A cache profile can be set and cleaned. I suppose that `expireResultCache` is an old piece of code that survived the refactoring. Should just be removed and documented accordingly





[DDC-2190] findBy() support finding by a single DateTime but not by multiple DateTime Created: 06/Dec/12  Updated: 09/May/13

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Christophe Coevoet Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None

Attachments: File DDC2190Test.php    

 Description   

The following code works:

$repository->findBy(array('date' => new \DateTime()))

but the following code fails as it does not apply the conversion of the date type for each element:

$repository->findBy(array('date' => array(new \DateTime(), new \DateTime('tomorrow')))


 Comments   
Comment by Benjamin Eberlei [ 06/Jan/13 ]

This is actually very hard to implement, the problem is that we only have ARRAY constants for PDO::PARAM_INT and PDO::PARAM_STR - all the other types would require special handling.

Comment by Benjamin Eberlei [ 09/May/13 ]

Attaching failing testcase.

The idea is to have something like "datetime[]" as type and detect this in the SQLParserUtils of DBAL.

Another approach would be to convert the values in the ORM already, before passing to the DBAL.





[DDC-2147] Custom annotation in MappedSuperclass Created: 15/Nov/12  Updated: 07/May/13

Status: Awaiting Feedback
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers, ORM
Affects Version/s: 2.2.1
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: kluk Assignee: Marco Pivetta
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Linux 3.6.6-1.fc17.x86_64


Attachments: Text File error.log    

 Description   

When you try use custom annotation in mappedsuperclass like here http://pastebin.com/YMxKvcLk and then i try get metadata for class i get this error
Undefined index: fieldName
ClassMetadataInfo.php function addInheritedFieldMapping
Problem is that custom annotation doesnt have fieldName.
Quick fix is add condition to test if fieldName isset.



 Comments   
Comment by kluk [ 15/Nov/12 ]

error log from orm:validate-schema

Comment by Marco Pivetta [ 23/Jan/13 ]

Copying from pastebin:

use \Doctrine\ORM\Mapping as ORM;
use \xxx\Doctrine\Annotation\Entity as re;
use \xxx\Doctrine\Annotation\Forms as rf;
use \Doctrine\Common\Collections;
 
/**
 * @ORM\Entity
 */
class EventPicture extends \Picture
{
 
    /**
     * @ORM\ManyToOne(targetEntity="Event", inversedBy="eventPicture")
     * @ORM\JoinColumn(name="FK_Event", referencedColumnName="id")
     */
    protected $event;
 
}
use \Doctrine\ORM\Mapping as ORM;
use \xxx\Doctrine\Annotation\Entity as re;
use \xxx\Doctrine\Annotation\Forms as rf;
use \Doctrine\Common\Collections;
 
/** @ORM\MappedSuperclass */
class Picture extends \xxx\Doctrine\Entity\BaseEntity
{
 
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="IDENTITY")
     * @var type
     */
    protected $id;
 
    /**
     * @ORM\Column(type="string",unique=true, nullable=false)
     *  @rf\FileUpload(fileSize="php",uploadType="local",fieldName="link",formControl="FileUploadField",image=true)
     *
     */
    protected $link;
 
}

kluk does this happen also with any other simple custom annotation? For example following:

/**
 * @Annotation 
 * @Target({"PROPERTY","ANNOTATION"})
 */
final class Entity implements Annotation
{
    /**
     * @var string
     */
    public $value;
}
Comment by kluk [ 30/Jan/13 ]

the same error when using simple annotation.

 
<?php

use \Doctrine\ORM\Mapping as ORM;
use \xxx\Doctrine\Annotation\Entity as re;
use \xxx\Doctrine\Annotation\Forms as rf;
use \Doctrine\Common\Collections;

/** @ORM\MappedSuperclass */
class Picture extends \xxx\Doctrine\Entity\BaseEntity {

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="IDENTITY")
     * @var type
     */
    protected $id;

   
    /**
     * @ORM\Column(type="integer")
     * @rf\SetClass({"class","hide"})
     */
    public $value;

    /**
     * @ORM\Column(type="string",unique=true, nullable=true)
     * @rf\FileUpload(fileSize="php",uploadType="local",fieldName="link",formControl="FileUploadField",image=true)
     *
     */
    protected $link;

}

When i remove $value , $picture from class everything goes ok.
Easy fix for me is change ClassMetadataInfo.

    /**
     * INTERNAL:
     * Adds a field mapping without completing/validating it.
     * This is mainly used to add inherited field mappings to derived classes.
     *
     * @param array $fieldMapping
     *
     * @return void
     */
    public function addInheritedFieldMapping(array $fieldMapping)
    {
        if(isset($fieldMapping['fieldName'])){
        $this->fieldMappings[$fieldMapping['fieldName']] = $fieldMapping;
        $this->columnNames[$fieldMapping['fieldName']] = $fieldMapping['columnName'];
        $this->fieldNames[$fieldMapping['columnName']] = $fieldMapping['fieldName'];
        }
    }

But i dont know if this fix can break another part of doctrine.

Comment by Benjamin Eberlei [ 04/May/13 ]

Can you put the code of your annotations online? I can't seem to understand why this happens.

Comment by kluk [ 07/May/13 ]
Unable to find source-code formatter for language: php. Available languages are: actionscript, html, java, javascript, none, sql, xhtml, xml
 
namespace libs\Doctrine\Annotation\Entity;
use Doctrine\Common\Annotations\Annotation;

/** @Annotation */
class CustomMapping extends Annotation
{
    /**
     *
     * @var string
     */
    public $className;
    /**
     * 
     * 
     * @var IQueryable| string
     */
    public $dataSource;
}




[DDC-2104] BasicEntityPersister::load() doesn't allow for cache usage Created: 25/Oct/12  Updated: 12/Nov/12

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: None
Security Level: All

Type: New Feature Priority: Major
Reporter: Dan McFaul Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: None
Environment:

This is a new feature, not a bug



 Description   

BasicEntityPersister::load() calls:
$stmt = $this->_conn->executeQuery($sql, $params, $types);
on line 665 of master/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php

The executeQuery function has an optional fourth parameter to pass a QueryCacheProfile variable to use caching on the query. This is ignored/not implemented by BasicEntityPersister::load()






[DDC-2100] Getting Started: Code First PHP fatal error:Call to undefined method Bug::setDescription() Created: 24/Oct/12  Updated: 24/Oct/12

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3
Fix Version/s: None

Type: Documentation Priority: Major
Reporter: bronze1man Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

ubuntu 1204 php5.3.8



 Description   

http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/getting-started.html
in file create_bug.php
$bug->setDescription("Something does not work!");
but the class Bug do not have setDescription function.

ps:
try find "setDescription" on that page. there is only one .






[DDC-2043] Extra cache operation in DBAL\Cache\ResultCacheStatement.php Created: 26/Sep/12  Updated: 26/Sep/12

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Bogdan Albei Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

CentOS, PHP 5.3.10



 Description   

This is the closeCursor() method in DBAL\Cache\ResultCacheStatement.php:

public function closeCursor()
    {
        $this->statement->closeCursor();
        if ($this->emptied && $this->data !== null) {
            $data = $this->resultCache->fetch($this->cacheKey);
            if ( ! $data) {
                $data = array();
            }
            $data[$this->realKey] = $this->data;

            $this->resultCache->save($this->cacheKey, $data, $this->lifetime);
            unset($this->data);
        }
    }

We are using Memcache and I noticed an extra GET operation on all cache misses. In the code above I believe the fetch call is not necessary and that the code would do the same without it.
Also, may I ask why is the SQL used as a key in the cached data?



 Comments   
Comment by Christophe Coevoet [ 26/Sep/12 ]

The SQL is used as a key because it is what identifies the query which is done (well, the statement and the parameters)

Comment by Bogdan Albei [ 26/Sep/12 ]

The cacheKey already identifies the query(or at least it should). Would we have cases where different queries would want to use the same cache key?





[DDC-2042] Metadata association overriding : allow to override 'targetEntity' Created: 26/Sep/12  Updated: 31/Mar/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Charles Rouillon Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

While associating object to an descriminated table I wasn't enable to fix the entityTarget (only one can be set in entity annotation).

It could be resolve by adding the possibility to override 'targetEntity' value in Doctrine\ORM\Mapping\ClassMetadataInfo::ClassMetadataInfo().

Such as :

if (isset($overrideMapping['targetEntity'])) {
$mapping['targetEntity'] = $overrideMapping['targetEntity'];
}

That would need to add a control on the new targetEntity in Doctrine\ORM\Mapping\ClassMetadataInfo::_validateAndCompleteAssociationMapping().

Such as :

if ( ! ClassLoader::classExists($mapping['targetEntity']) ) {
throw MappingException::invalidTargetEntityClass($mapping['targetEntity'], $this->name, $mapping['fieldName']);
}

cro.



 Comments   
Comment by Oleg Namaka [ 31/Mar/14 ]

We need this feature too. Why is this ticket in a limbo? Someone please add a comment whether this will be fixed.

Comment by Marco Pivetta [ 31/Mar/14 ]

Oleg Namaka you can open a pull request with a test and suggested improvement for this at https://github.com/doctrine/doctrine2





[DDC-1991] Add parameter indexBy to EntityRepository->createQueryBuilder() Created: 20/Aug/12  Updated: 20/Aug/12

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Philipp Cordes Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

createQueryBuilder() currently doesn’t have a parameter to set the third option on the FROM fragment: indexBy. Right now you have to read it, create a new From with the read properties and your desired indexBy value and replace the existing one on the QueryBuilder.

Should be ten minutes’ work including tests. Thanks a lot!






[DDC-1986] findBy hydration with limit and offset with Oracle database (oci8 driver) Created: 17/Aug/12  Updated: 08/Jan/13

Status: Awaiting Feedback
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Benjamin Grandfond Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: oracle
Environment:

composer.json require :

"php": ">=5.3.3",
"symfony/symfony": "2.1.*",
"doctrine/orm": ">=2.2.3,<2.4-dev",
"doctrine/doctrine-bundle": "dev-master",
"twig/extensions": "dev-master",
"symfony/assetic-bundle": "dev-master",
"symfony/swiftmailer-bundle": "dev-master",
"symfony/monolog-bundle": "dev-master",
"sensio/distribution-bundle": "dev-master",
"sensio/framework-extra-bundle": "dev-master",
"sensio/generator-bundle": "dev-master",
"jms/security-extra-bundle": "1.2.*",
"jms/di-extra-bundle": "1.1.*",
"twitter/bootstrap": "master",
"friendsofsymfony/rest-bundle": "dev-master",
"doctrine/doctrine-fixtures-bundle": "dev-master"



 Description   

I tried to use the findBy method with limit and offset parameters against an Oracle database using oci8 driver.

The query seems to executed successfully but the hydrator fails when hydrating data as there is a DOCTRINE_ROWNUM column appending the "limit" clause.

Here is the exception thrown : "Notice: Undefined index: DOCTRINE_ROWNUM in [...]/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php line 183"

I was thinking about something like this to fix this issue :

  • add an attribute (platformExtraColumns) to the platform class, storing every column added by methods like doModifyLimitQuery
  • check in hydrator method hydrateRowData if the column exists among the extra columns attribute of the custom platform
  • don't use the column if true

Maybe there is a better approach, what are your thoughts?



 Comments   
Comment by Benjamin Grandfond [ 17/Aug/12 ]

I implemented it in my forks :

https://github.com/benja-M-1/doctrine2/commit/c8d899b14446accf869ddc0043f4235284375755
https://github.com/benja-M-1/dbal/commit/b9423c8d46a2bcdaa5a1f0b26a9a28259b1e44a2

It works for me, but I didn't write unit tests.

Comment by Benjamin Grandfond [ 24/Aug/12 ]

Hi,

Did you have time to have a look at this issue?

Thanks

Comment by Christophe Coevoet [ 24/Aug/12 ]

Please send a pull request when you submit a fix. It is the proper way to submit them for review. When we want to see things waiting for review, we look at the list of pending PRs, not at all comments of the issue tracker to find links in them.

And I can tell you that this change has a big issue: it introduces a state in the database platform whereas it is currently stateless. This is likely to cause some issues when using more than 1 query (which is a common use case).

Comment by Benjamin Grandfond [ 29/Aug/12 ]

Hi Christophe thank you for your feedback.

I didn't send a PR because I wanted someone sharing his thoughts about what I suggested in this current issue. However I don't really understand the stateless argument, can you explain a bit more?

Otherwise how would do you proceed to tell Doctrine not to hydrate platform-specific columns?

Comment by Christophe Coevoet [ 29/Aug/12 ]

If you run several queries, they will be affected by the extra columns of previous requests, which is wrong

Comment by Benjamin Eberlei [ 29/Aug/12 ]

I think the ObjectHydrator catches this by skipping undefined columns, i think we might just have overoptimized the SimpleObjectHydrator a little bit.





[DDC-1960] mapping joins in native queries breaks if select columns are starting with columns from joined table Created: 31/Jul/12  Updated: 21/Nov/12

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1.4, 2.1.7
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Thomas Subera Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

ubuntu kernel 2.6.32-40-server
php 5.3.10-1ubuntu2ppa6~lucid with Suhosin-Patch (cli)
apache 2 2.2.14-5ubuntu8.9
postgres 9.1.4-1~lucid4


Attachments: Zip Archive testcase.zip    

 Description   

Using a simple Testcase like in http://docs.doctrine-project.org/projects/doctrine-orm/en/2.1/reference/native-sql.html there are two Tables:

*) users:

   Column   |  Type   | Modifiers | Storage  | Description 
------------+---------+-----------+----------+-------------
 u_id       | integer | not null  | plain    | 
 u_name     | text    | not null  | extended | 
 address_id | integer | not null  | plain    | 

*) address:

  Column  |  Type   | Modifiers | Storage  | Description 
----------+---------+-----------+----------+-------------
 a_id     | integer | not null  | plain    | 
 a_street | text    | not null  | extended | 
 a_city   | text    | not null  | extended | 

address_id is a foreign key to address;

Now i created the Entities and setup a native query using ResultSetMappingBuilder:

$rsm = new \Doctrine\ORM\Query\ResultSetMappingBuilder($entityManager);
$rsm->addRootEntityFromClassMetadata('MyProject\Entity\Users', 'u');
$rsm->addJoinedEntityFromClassMetadata('MyProject\Entity\Address', 'a', 'u', 'address');

$query = '
    SELECT
        u.*,
        a.*
    FROM
        users u
    LEFT JOIN address a ON (u.address_id = a.a_id)
';

/** @var $native \Doctrine\ORM\NativeQuery */
$native = $entityManager->createNativeQuery($query, $rsm);

$ret = $native->getResult();

This returns the Entities correctly:

array(2) {
  [0] =>
  class MyProject\Entity\Users#61 (3) {
    protected $id =>
    int(1)
    protected $name =>
    string(5) "Smith"
    protected $address =>
    class MyProject\Entity\Address#63 (4) {
      protected $id =>
      int(1)
      protected $street =>
      string(8) "Broadway"
      protected $city =>
      string(8) "New York"
      protected $users =>
      class Doctrine\ORM\PersistentCollection#64 (9) {
        ...
      }
    }
  }
  [1] =>
  class MyProject\Entity\Users#66 (3) {
    protected $id =>
    int(2)
    protected $name =>
    string(7) "Sherlok"
    protected $address =>
    class MyProject\Entity\Address#67 (4) {
      protected $id =>
      int(2)
      protected $street =>
      string(13) "Oxford Street"
      protected $city =>
      string(6) "London"
      protected $users =>
      class Doctrine\ORM\PersistentCollection#68 (9) {
        ...
      }
    }
  }
}

BUT if you change the order of the select columns starting with ones from address you get borked Data:

$query = '
    SELECT
        a.*,
        u.*
    FROM
        users u
    LEFT JOIN address a ON (u.address_id = a.a_id)
';
array(2) {
  [0] =>
  class MyProject\Entity\Users#61 (3) {
    protected $id =>
    int(1)
    protected $name =>
    string(5) "Smith"
    protected $address =>
    class MyProject\Entity\Address#63 (4) {
      protected $id =>
      int(2)
      protected $street =>
      string(13) "Oxford Street"
      protected $city =>
      string(6) "London"
      protected $users =>
      class Doctrine\ORM\PersistentCollection#64 (9) {
        ...
      }
    }
  }
  [1] =>
  class MyProject\Entity\Users#66 (3) {
    protected $id =>
    int(2)
    protected $name =>
    string(7) "Sherlok"
    protected $address =>
    NULL
  }
}

This happens because the function Doctrine\ORM\Internal\Hydration\AbstractHydrator::_gatherRowData does not consider the Mapping i set up. Instead it just add the columns as they get starting with address ones.

Doctrine\ORM\Internal\Hydration\ObjectHydrator::_hydrateRow then knows the Mapping and ignores the first Address as there is no User to map on, cycling to the next row will then add the address of the second row to the user from the first one.

There are multiple ways to fix this. One would be to consider the mapping in _gatherRowData, the second to rewrite the _hydrateRow generating the Entities first and then the mapping in a second foreach loop.

This bugger had me for 2 days until i finally figured it out.

thanks



 Comments   
Comment by Frederic [ 21/Nov/12 ]

Hello,

Has same issue with using DQL /createQuery() ! Try all the day to find where was my mistake but seems to be a CRITICAL bug !
How did you solve this ?

Doctrine version used : 2.3.1-DEV

<code>
$query = $this->getEntityManager()->createQuery("
SELECT cc, oc
FROM category cc
JOIN cc.offer_category oc
WHERE cc.catalog = :catalog_id
ORDER BY oc.name ASC
")
->setParameter(":catalog_id", $catalog_id)
;

</code>

Problem is that the order of the Aliases (cc, oc) is not considered on building SQL .
In my case, in the ObjectHydrator::hydrateRowData method :

$rowData = $this->gatherRowData($row, $cache, $id, $nonemptyComponents);

returns

Array
(

[oc] => Array
(
[id] => 14
[name] => toto
)
[cc] => Array
(
[catalog_id] => 1
[offer_category_id] => 14
)
)

As "oc" is a mapping, on the first loop the $parentAlias is not yet known and so :
<code>
if ($this->_rsm->isMixed && isset($this->_rootAliases[$parentAlias]))

{ echo "parentObject 1\n"; $first = reset($this->_resultPointers); $parentObject = $first[key($first)]; }

else if (isset($this->_resultPointers[$parentAlias]))

{ echo $parentAlias." parentObject 2\n"; $parentObject = $this->_resultPointers[$parentAlias]; }

else

{ // HERE : on first loop, for "oc", parent not yet known so skipped !!! continue; }

</code>

using a workaround on ObjectHydrator::hydrateRowData like this :
$rowData = array_reverse($rowData);

make it work...

Sorry for my dirty explanation...





[DDC-1965] Multiple Index fails if index name not specified Created: 02/Aug/12  Updated: 02/Aug/12

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Pont Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: Cli
Environment:

Ubuntu 11.04, PHP 5.3.6 with Suhosin-patch, Symfony 2.0.15



 Description   

@ORM\Table(name="applications", indexes={@ORM\Index(name="csl_idx", columns=

{"createdAt", "status", "loanType"}), @ORM\Index(name="s_idx", columns={"status"}), @ORM\Index(name="l_idx", columns={"loanType"})})

the above Annotation creates 3 different indexes BUT when:
* @ORM\Table(name="applications", indexes={@ORM\Index(columns={"createdAt", "status", "loanType"}

), @ORM\Index(columns=

{"status"}

), @ORM\Index(columns=

{"loanType"}

)})

index-names not specified Symfony2 schemaUpdate tools shows only the last Index






[DDC-1924] Let SQLFilters know the query type it is being applied to Created: 13/Jul/12  Updated: 13/Jul/12

Status: Reopened
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Jan Knudsen Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

I'm making an access control system and would like to automatically filter all queries based current user, targetEntity type and query type. Query type is relevant as different permissions are needed by the user for SELECT, UPDATE, DELETE and INSERT queries.

I can access the first two things in my filter easily enough, but I cannot find a way to have the filter know what type of query the filter is being applied to.



 Comments   
Comment by Benjamin Eberlei [ 13/Jul/12 ]

The Filter API only makes sense for SELECT clauses. Doctrine itself does not use DQL to do updates internally, so you need to use other mechanisms (EventListener) to prevent this operations if they are not allowed for a user.

Comment by Jan Knudsen [ 13/Jul/12 ]

But I can make custom DQL to update rows and would like to automatically filter this too.

e.g. $em->createQuery("UPDATE SomeEntity se SET se.field = "updated!")->execute();

The lifecycle events preUpdate etc. are not called when doing custom DQL queries.

Maybe it is bad practice and discouraged to do updates, inserts and deletes as custom DQL queries, but I would like to ensure that the other people in my organization can't accidentally bypass the Access Control, even if they make use of such bad practice.

And if the filter API only makes sense for Select statements, why are filters applied to update/delete/etc. statements too?

Comment by Benjamin Eberlei [ 13/Jul/12 ]

Well, they are applied to DQL UPDATE/DELETE. But not not UPDATE/DELETE that works through the internals of Doctrine. So yes, you can use it to filter DQL DELETE/UPDATE, but doctrine does not do that internally.

So you have to have two strategies, a DQL/SQL Filter - and Lifecycle events.

Comment by Jan Knudsen [ 13/Jul/12 ]

Which is fine by me. I already implemented the checks using lifecycle events before opening this issue. The access control is automatically handled when using the entitymanager and not custom DQL.

Now I would also like to filter the custom DQL, but currently I can't, because as originally stated, the filter needs to know which type of query it is being applied to.





[DDC-1879] Orphans are neither nulled nor removed when merging a graph of detached entities Created: 18/Jun/12  Updated: 23/Jan/13

Status: Awaiting Feedback
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.2.2
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Philippe Van Eerdenbrugghe Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Doctrine 2.2.2
PHP 5.3.10 with Suhosin-Patch
mysql Ver 14.14 Distrib 5.5.15, for osx10.7
Mac OS X 10.7 Lion



 Description   

When merging a graph of detached entities, the created entitied are created and the updated entities are updated but the non-present entities (which exist in the database but are not in the graph) are neither removed nor have them their association column nullified.

Example :

In my code I have 2 entities : Parent and Child. There is a OneToMany(cascade=

{"all"}

, orphanRemoval=true) relation defined in Parent.

In my database I have a Parent row with an id of 1, which has 3 Children with ids 1,2,3.

When I write the following code, I expect the Parent with id 1 and the Child with id 2 to be updated, a new Child to be created and the Child with id 1 and 3 to be deleted.

$parent = new Parent(); $parent->id = 1  // detached entity
$existing_child = new Child(); $child->id = 2 // detached entity
$new_child = new Child(); // new entity
$dinner->addChild($existing_child);
$dinner->addChild($new_child);

$em->merge($dinner);

$em->flush();

The objects I expect to be created and updated have the correct behaviour but the old children are not touched, they are still present in the database.



 Comments   
Comment by Marco Pivetta [ 23/Jan/13 ]

I don't think this is valid. Orphan removal scheduling is handled only when an unit of work is available.

What's the state of `$dinner` before your example? Can you `var_dump` it?





[DDC-1882] AbstractQuery#getResultCacheId() should be public to be able to manage the cache Created: 19/Jun/12  Updated: 19/Jun/12

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1.6
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Ignacio Larranaga Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File AbstractQuery.patch    

 Description   

The method getResultCacheId of Doctrine\ORM\AbstractQuery should be public.

I'm trying to customize the cache refresh mechanism to clear previously cached objects in my app.
To do that I'm adding a prefix to define regions in the cache.
To be able to set the Id's correctly (adding region prefixes) I need to get the "normal" hash doctrine were used in the normal scenario (trying to avoid introduce new code).
That's why I will prefer the method to be public.



 Comments   
Comment by Ignacio Larranaga [ 19/Jun/12 ]

Attaching the patch despite is a trivial change.





[DDC-1806] DQL with and without fetch join cause Created: 01/May/12  Updated: 01/May/12

Status: Open
Project: Doctrine 2 - ORM
Component/s: DQL, ORM
Affects Version/s: 2.2, 2.2.1, 2.2.2, Git Master
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Marco Pivetta Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None

Attachments: File DDC1806Test.php     GZip Archive gist2473775-d202a38fdfb91921ef010df36322fb646561593a.tar.gz    

 Description   

When running following DQL in newly cleared EntityManager, with the provided entities (see attached archive or gist at https://gist.github.com/2473775 ), results in different fetched association:

DQL without join:
SELECT a FROM Entity\A a WHERE a.id = :id

SQL without join:
SELECT a0_.a_id AS a_id0, a0_.id AS id1 FROM a a0_ WHERE a0_.a_id = ?

Result without join:
$query->getOneOrNullResult()>getB()>getName(); // 'correct'

DQL with fetch join:
SELECT a, b FROM Entity\A a LEFT JOIN a.b b WHERE a.id = :id

SQL with fetch join:
SELECT a0_.a_id AS a_id0, b1_.id AS id1, b1_.name AS name2, a0_.id AS id3 FROM a a0_ LEFT JOIN b b1_ ON a0_.id = b1_.id WHERE a0_.a_id = ?

Result with fetch join:
$query->getOneOrNullResult()>getB()>getName(); // 'wrong' (different result)

The problem seems to be strictly related with how the `@JoinColumn` is configured.



 Comments   
Comment by Marco Pivetta [ 01/May/12 ]

Attaching failing test from https://github.com/Ocramius/doctrine2/compare/DDC-1806





[DDC-1803] Paginator usage with a DQL query that is using 2 time the same named binded value failed Created: 30/Apr/12  Updated: 25/Jan/13

Status: Awaiting Feedback
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Marc Drolet Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

linux, oracle



 Description   

I use a dql query where I bind a named parameter 2 time in the same query for different joined fields. The query work but the count query failed saying that there are missing bind variable.

ex:
$qb = $this->getQueryBuilder()
->select('
partial fl.

{id, title, listing_date, abstract}

,
partial fla.

{id},
partial ca.{id}

,
partial ds.

{id}

')
->from('Fo_Listing', 'fl')
->join('fl.listing_properties', 'flp')
->join('flp.property', 'fp')
->leftjoin('fl.listing_assets', 'fla')
->leftjoin('fla.asset', 'ca')
->leftjoin('ca.ds', 'ds')
->where('fp.id = :propertyId')
->setParameter('propertyId', $id)
->andWhere('fl.object_status_id <> :deleted')
->setParameter('deleted', CoRefObjectStatus::DELETE)
->andWhere('fl.publishing_status_id = :published')
->setParameter('published', CoRefPublishingStatus::PUBLISHED)
->andWhere('fp.object_status_id <> :deleted')
->setParameter('deleted', CoRefObjectStatus::DELETE)
->andWhere('fp.publishing_status_id = :published')
->setParameter('published', CoRefPublishingStatus::PUBLISHED)
->add('orderBy', 'fl.listing_date DESC, fl.published_date DESC')
->setMaxResults($onTheMarketLimit);

$onTheMarket = new Paginator($qb, $fetchJoin = true);

To make it work, I've renamed the second usage of the named variable with a 2 at the end. deleted2 and published2.



 Comments   
Comment by Marco Pivetta [ 23/Jan/13 ]

This seems to be quite old. Marc Drolet is it still valid with the latest ORM?

Comment by Marc Drolet [ 25/Jan/13 ]

I'll try to test this problem on an updated version and I'll let you know.
The bug entry is also quite old and I've a local modified version of the paginator here to make it work with oracle, so it can take some time before I can test this out on the current doctrine version.

Comment by Marco Pivetta [ 25/Jan/13 ]

Ok, marking as awaiting feedback





[DDC-1732] Unserialized non-initialized proxy classes should throw an exception when a method is called Created: 28/Mar/12  Updated: 28/Mar/12

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.2, Git Master
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Benjamin Morel Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File ProxyFactory.php.patch    

 Description   

When we serialize entities in a session, we often have pointers to uninitialized proxies.
These proxies have $_entityPersister == null.

The problem is that if you happen to call by mistake a method on such a proxy, you're not aware that this is an uninitialized proxy, and the business methods are called, with null values for every property.

I think the proxy should throw an exception in that case.
Attached, a patch with the proposed modification.






[DDC-1729] Translate queries into graphs of value objects (instead of array hydration?) Created: 27/Mar/12  Updated: 09/Jun/12

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

Type: New Feature Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

In decoupled applications the model layer returns "data-transfer-objects" through the boundary into the controller/view layer. It would make sense to have Doctrine directly generate any data-transfer/value-object from native and dql queries.



 Comments   
Comment by Benjamin Eberlei [ 09/Jun/12 ]

Example:

$dql = "SELECT new CustomerAddressView(c.id, c.name, a.id, a.street, a.number, a.city, a.code)
             FROM Customer c INNER JOIN c.address a WHERE c.id = ?1";

This supersedes DDC-1819.

1. One additional property in ResultSetMapping => $viewModelClass?
2. Changes to Parser (new ... syntax)
3. Changes to sQL Walker?
4. Changes to Hydration (Only object hydration!)





[DDC-1728] There is no exact alternative function like MONTH in mysql Created: 27/Mar/12  Updated: 27/Mar/12

Status: Open
Project: Doctrine 2 - ORM
Component/s: DQL, ORM
Affects Version/s: 2.2.0-RC1, 2.2, 2.2.1
Fix Version/s: None
Security Level: All

Type: New Feature Priority: Major
Reporter: Sudheesh MS Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Ubuntu 11.10



 Description   

i am not able to extract only month from the date field using doctrine2 using 'MONTH' function






[DDC-1721] LIKE clausule should accept functions on the pattern Created: 21/Mar/12  Updated: 01/Apr/14

Status: Awaiting Feedback
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1.6
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Ignacio Larranaga Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 2
Labels: querybuilder,, sql-walker

Attachments: Text File Parser.patch     Text File SqlWalker.patch    

 Description   

Example:
SELECT .... WHERE upper(n.title) LIKE upper(:filter)

should be a valid SQL, now is rejected because the walker only accept a variable or an string expression.

I'm adding a patch to address this.



 Comments   
Comment by Ignacio Larranaga [ 21/Mar/12 ]

Sorry the Parser has to be modified also to allow expressions to be recognized, I'm attaching the necessary patch.

Comment by Benjamin Eberlei [ 22/Mar/12 ]

I am sure there is a reason why the walker doesn't accept this such as not all supported vendors allowing functions in right hand side LIKE expressions, but i am not sure about this.

Comment by Glen Ainscow [ 03/Oct/12 ]

This is not possible either:

WHERE CASE WHEN p.name IS NULL THEN u.username ELSE p.name END LIKE :name

Comment by Thomas Mayer [ 24/Jan/13 ]

In my case it worked when using "=" instead of "LIKE".

//works:
(CASE WHEN (Book.id = BookFrom.id) THEN BookTo.displayName ELSE BookFrom.displayName END) = :name

//[Syntax Error] line 0, col 1217: Error: Expected =, <, <=, <>, >, >=, !=, got 'LIKE'
(CASE WHEN (Book.id = BookFrom.id) THEN BookTo.displayName ELSE BookFrom.displayName END) LIKE :name

So the LIKE operator only needs to be allowed here.

I'm wondering which vendor should not be able to handle that:
The CASE WHEN ... THEN ... END is documented in DQL, and allowed.
LIKE itself is allowed.
If an RDBMs cannot use CASE WHEN and LIKE in combination, this would be a strange limitation.

Comment by Martin Keckeis [ 31/Mar/14 ]

Having the same problem here.

LIKE + CASE is often used in my application at the WHERE part.
(e.g. data filtering of a datagrid column)





[DDC-1720] SqlWalter private variables should be protected to allow walker extensions Created: 21/Mar/12  Updated: 21/Mar/12

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1.6
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Ignacio Larranaga Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File SqlWalker.patch    

 Description   

I'm attaching a patch with the suggestion.






[DDC-1714] Prevent inverse side lazy loading owning side of the oneToOne relationsip if owning side's id is an assosiationKey of inversed side Created: 18/Mar/12  Updated: 23/Mar/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: David Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

This issue was originally discussed in http://www.doctrine-project.org/jira/browse/DDC-357

Say there is User and UserData with oneToOne bidirectional relationship. When we fetch User objects, UserData is lazy loaded right away.

If we were to set UserData 's id as asssosiationKey of User, then user_id becomes the id of UserData and User object can already know that UserData owning side's id will equal it's own User->id.

Can this be implemented?



 Comments   
Comment by Doctrine Bot [ 23/Mar/14 ]

A related Github Pull-Request [GH-970] was closed:
https://github.com/doctrine/doctrine2/pull/970





[DDC-1532] PostFlush lifecycle event Created: 13/Dec/11  Updated: 14/Dec/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: None
Security Level: All

Type: New Feature Priority: Major
Reporter: Jack van Galen Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: None


 Description   

In some cases, the database-id of the newly created record is needed in some postproccessing steps, like sending an e-mail containing a link to the just created entity. I've recently seen the added support for PostFlush, but this is not a lifecycle event.

class SomeEntityClass{

/** @PostFlush */
function sendSomeEmail()

{ sendEmail(' 'Hi, you're new invoice can be found online: http://www.example.com/invoices/invoice_'.$this->id '; }

}

Perhaps it's even possible to have multiple PostFlush events, that differentiate between the first time a record is created, and when the record is merely updated.



 Comments   
Comment by Jack van Galen [ 14/Dec/11 ]

Okay, please ignore this issue, as I now see that the @PostPersist does exactly what I need. I was thrown by the name, because to me, the order in which stuff happens is persist -> flush. The ID's are only known after flush, so i'd expected something like postflush to exist. Sorry.





Possible Regression with OneToOne relation (DDC-1461)

[DDC-1506] Possible Regression with OneToOne relation Created: 23/Nov/11  Updated: 23/Nov/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1.2
Fix Version/s: None
Security Level: All

Type: Sub-task Priority: Major
Reporter: Maxim Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   
/**
 * @ORM\Entity
 */
class Top
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;
    /**
     * @ORM\OneToOne(targetEntity="LevelOne", orphanRemoval="true", cascade={"persist", "remove"})
     */
    protected $levelOne;
    
    public function getId()
    {
        return $this->id;
    }

    public function setLevelOne(LevelOne $levelOne)
    {
        $this->levelOne = $levelOne;
    }

    public function getLevelOne()
    {
        return $this->levelOne;
    }
}

/**
 * @ORM\Entity
 */
class LevelOne
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;
    /**
     * @ORM\OneToOne(targetEntity="LevelTwo", orphanRemoval="true", cascade={"persist", "remove"})
     */
    protected $levelTwo;

    public function getId()
    {
        return $this->id;
    }
    
    public function setId($id)
    {
        $this->id = $id;
    }

    public function setLevelTwo(LevelTwo $levelTwo)
    {
        $this->levelTwo = $levelTwo;
    }

    public function getLevelTwo()
    {
        return $this->levelTwo;
    }
}

/**
 * @ORM\Entity
 */
class LevelTwo
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;
    
    public function getId()
    {
        return $this->id;
    }
    
    public function setId($id)
    {
        $this->id = $id;
    }
}

trying to clone objects

$top = new Top();
        $top->setLevelOne(new LevelOne());
        $top->getLevelOne()->setLevelTwo(new LevelTwo());
        
        $this->em->persist($top);
        $this->em->flush();
        
        $newTop = new Top();
        $newTop->setLevelOne(clone $top->getLevelOne());
        $newTop->getLevelOne()->setId(null);
        $newTop->getLevelOne()->getLevelTwo()->setId(null);
        
        var_dump($newTop->getLevelOne()->getId());
        var_dump($newTop->getLevelOne()->getLevelTwo()->getId());
        
        $this->em->persist($newTop);
        $this->em->flush();

the output is:
NULL
NULL
[PDOException]
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1' for key 'UNIQ_82A72CD0778BC57F'
(it duplicates level two entity)
I worked for a while with entities, in a certain set of entity properties it completely persisted into database, but without relation between level one and level two.






[DDC-1450] UnitOfWork Transaction Rollback Support Created: 24/Oct/11  Updated: 20/Dec/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

Type: Improvement Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

The UnitOfWork does not handle the case very well where a rollback is necessary. Can this be optimized?



 Comments   
Comment by Guilherme Blanco [ 20/Dec/11 ]

Updating fix version





[DDC-1390]  Lazy loading does not work for the relationships of an entity instance, whose class inherits from another entity class Created: 22/Sep/11  Updated: 06/Jan/13

Status: In Progress
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1.1
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Daniel Alvarez Arribas Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Debian Linux 6.0, MySQL 5.0.51a


Attachments: File CommissionNoteCreatorResult.php     File ConsumerInvoiceExporterResult.php     File DataObject.php     File DataVersion.php     File DDC1390Test.php     File InvoiceCreatorResult.php     File Result.php     File Run.php    

 Description   

Lazy loading does not work for the relationships of an instance of an entity, whose class inherits from another entity class.

Assume there are two entity classes, A and B, where A inherits from B.

Now let $a be an instance of A, e. g. the result of "SELECT a FROM \A WHERE a.id = 1".

Outputting $a will confirm it is a valid instance of a proxy object inheriting from A.

Assume that the database row corresponding to $a contains a non-null foreign key that actually links to an existing row in another table, corresponding to another entity instance of a different class.

Now, $a->someRelationship will always returns null in this scenario. I assume this is unintended behaviour, because clearly, the other entity should be lazily loaded on accessing it, and there is a value in the database.

The fetch annotation attribute on that relationship has not been explicitly set, so I assume it is set to the default value, which, according to the docs, should be "lazy".

The loading only fails when accessing the relationships of an entity instance, whose class inherits from another entity class. For entity instances, whose classes do not inherit from another entity class, lazy loading of their relationships works as expected.

I had a look at the proxy objects and verified that they are present and override the __get method with an implementation containing a call to the load() method. Still, the loading won't work for some reason.

This could be related to Bug DDC-1389 (http://www.doctrine-project.org/jira/browse/DDC-1389) which also happens exclusively in an inheritance scenario. Maybe the current implementation of inheritance is generally wrong or incomplete.



 Comments   
Comment by Benjamin Eberlei [ 31/Oct/11 ]

Did this get fixed with the correction of your data?

Comment by Daniel Alvarez Arribas [ 01/Nov/11 ]

No it did not. This issue is completely unrelated to the other one.

For this, I have manually implemented workarounds, fetching the associations using DQL queries. Lazy loading in the inheritance scenario above still would not work.

Comment by Benjamin Eberlei [ 01/Nov/11 ]

So A is an entity in a hierachy A -> B, and "someRelationship" is a field on A or on B towards an Entity C that is in an inheritance hierachy or not?

Could you post parts of the mappings (entity docblock and the relationship)?

Comment by Daniel Alvarez Arribas [ 06/Nov/11 ]

Hey, thanks for taking care of this.

I attached the entities involved in the szenario to this issue.

I had problems lazy loading entities through the following associations:

Run.invoiceCreatorResult
Run.commissionNoteCreatorResult
Run.consumerInvoiceExporterResult

as well as

InvoiceCreatorResult.dataVersion
CommissionNoteCreatorResult.dataVersion
ConsumerInvoiceExporterResult.dataVersion

In this scenario, InvoiceCreatorResult, CommissionNoteCreatorResult and ConsumerInvoiceExporterResult all inherit from Result, which in turn inherits from a mapped superclass DataObject. Run and DataVersion inherit from DataObject directly.

The associations where lazy loading does not work are associations both to and from the entity classes InvoiceCreatorResult, CommissionNoteCreatorResult and ConsumerInvoiceExporterResult.

Comment by Benjamin Eberlei [ 18/Nov/11 ]

Now let $a be an instance of A, e. g. the result of "SELECT a FROM \A WHERE a.id = 1".

Outputting $a will confirm it is a valid instance of a proxy object inheriting from A.

Just a short Q on understanding: Why is $a a proxy of A if you select it explicitly?

Comment by Benjamin Eberlei [ 18/Nov/11 ]

This a working test-case with a model that i believe resembles yours exactly.

I also put your models into another test and ran schema validation on them, which works out without problems.

From the workflow with proxies, maybe DDC-1452 might be related to your issue?

Comment by Daniel Alvarez Arribas [ 18/Nov/11 ]

Regarding the proxy question, I just ment the query to be an example to further illustrate the type of $a. It was redundant and unnecessary though and probably misleading. Sorry for that. I did not select anything in the actual scenario. $a is merely some object of type A. No queries are involved.

Comment by Daniel Alvarez Arribas [ 18/Nov/11 ]

Have you been able to make the tests fail with the original data provided?

If not, I could set up a test case and post it.

Comment by Benjamin Eberlei [ 18/Nov/11 ]

No i only checked the validity of mappings with the original data. If you could setup a testcase that would be really great.

Comment by Daniel Alvarez Arribas [ 19/Nov/11 ]

I will set up a test case and upload it. I'll see if I can do it one of the next evenings.

Comment by Benjamin Eberlei [ 17/Dec/11 ]

I tried again, also extended DDC-1390, but it was impossible for me to reproduce this. I ran this against master, 2.1.x and 2.1.1 specifically.

Comment by Daniel Alvarez Arribas [ 05/Jan/13 ]

Sorry, I got swamped with work. Now I am working on this dedicatedly, testing against the latest release. Will let you know once I have a testcase.

Comment by Benjamin Eberlei [ 06/Jan/13 ]

Good to hear, thanks for the persistent work on this.





[DDC-1380] Standardize proxy class naming Created: 18/Sep/11  Updated: 18/Sep/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.x
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Johannes Schmitt Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

see https://github.com/doctrine/doctrine2/pull/125






[DDC-1357] Queries with multiple joins resulting in multiple scalar results for each top level entity only retain one scalar value for each entity Created: 01/Sep/11  Updated: 01/Sep/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Nils Adermann Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Consider this example:

select g.id, u.id, u.status, count(p.phonenumber) numPhones from Group
     * g join g.user u join u.phonenumbers p group by g.id, u.status, u.id

With data:

phonenumbers:
    [1, 2, 3, 4, 5, 6]
users:
    [{id: 1, status: developer, phonenumbers: [1, 2]},
     {id: 2, status: developer, phonenumbers: [3]},
     {id: 3, status: developer, phonenumbers: [4, 5, 6]}]
groups:
    [{id: 1, users: [1, 2]]},
     {id:2, users: [3]}]

The result currently is:

array(
    array(
        0 => object(CmsGroup) {
            'id' => 1,
            'users' => Collection(
                object(CmsUser) { 'id' => 1 },
                object(CmsUser) { 'id' => 2 }
            )
         },
        'numPhones' => 1
    ),
    array(
        0 => object(CmsGroup) {
            'id' => 2,
            'users' => Collection(
                object(CmsUser) { 'id' => 3 }
            )
        },
        'numPhones' => 3
    )
)

Note that the first entry contains only one value numPhones => 1, even though there are two users associated with that group. One of whom has 2 phone numbers and the other has 1.

The result I would expect is:

array(
    array(
        0 => object(CmsGroup) {
            'id' => 1,
            'users' => Collection(
                object(CmsUser) { 'id' => 1 },
                object(CmsUser) { 'id' => 2 }
            )
         },
        'numPhones' => array(2, 1)
    ),
    array(
        0 => object(CmsGroup) {
            'id' => 2,
            'users' => Collection(
                object(CmsUser) { 'id' => 3 }
            )
        },
        'numPhones' => array(3)
    )
)

The difference is that numPhones for each row now contains an array of the
scalar values matching the corresponding users.



 Comments   
Comment by Nils Adermann [ 01/Sep/11 ]

You can find a test case for the correct result here: https://github.com/naderman/doctrine2/commit/a1ca3d9847cbc514fc951fb0b221b26fe03a6619





[DDC-1443] Subscribers reachs maximum nesting level when creating association on pre/postPersist with cascade persist Created: 20/Oct/11  Updated: 29/Oct/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Guilherme Blanco Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None

Attachments: File DDC1443Test.php     File DDC1443Test.php    

 Description   

Suppose a situation where:

A -> B

Where the OneToOne unidirectional association contains cascade persist.

If I decide to save an entity B that should create an A instance, it goes into maximum nesting level no matter if I track prePersist or postPersist.



 Comments   
Comment by Guilherme Blanco [ 20/Oct/11 ]

Failing test case

Comment by Guilherme Blanco [ 20/Oct/11 ]

Uploading a new version, now passing successfully, but consuming the onFlush event (which should not be ideal).

Comment by Benjamin Eberlei [ 29/Oct/11 ]

Ah yes, this never worked. The transaction stuff will fix that. You have to use scheduleForInsert() something inside prePersist.





[DDC-1441] Metadata cannot be loaded for not registered proxy objects Created: 20/Oct/11  Updated: 05/Apr/12

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1.2
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Aigars Gedroics Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

MySQL, Ubuntu, PHP 5.3.6


Attachments: File DDC1441Test.php     File not-loaded-proxy-patch.diff    

 Description   

We are using several Doctrine managers in our project with the same entity classes and different database tables.

The problem appears when we are willing to merge entity with lazy associations from one manager to another. The second entity manager instance hasn't got the proxy object metadata defined yet so it fails with Doctrine\ORM\Mapping\MappingException exception "Class EntityProxy is not a valid entity or mapped super class.".

If both entity managers share the proxy objects the problem can be fixed by calling

$em->getProxyFactory()->getProxy('Entity', -1);

which will register the entity metadata for the proxy classname as well.

Still if the proxy configuration differs, there is no fix found without changing the Doctrine ORM code.

The fix inside the Doctrine would be to detect Proxy classes before loading the metadata and load the metadata for it's parent class instead. Please see the diff attached with proposed solution.

Also I think this issue could arise when unserialized entity objects will be merged into the entity manager. I will try creating test case for this.



 Comments   
Comment by Aigars Gedroics [ 24/Nov/11 ]

Test case attached.

Comment by Aigars Gedroics [ 05/Apr/12 ]

See my pull request in https://github.com/doctrine/doctrine2/pull/332.





[DDC-1431] Current event system is not flexible enough Created: 18/Oct/11  Updated: 18/Oct/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Oleg Stepura Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: None
Environment:

Doctrine 2.1


Sub-Tasks:
Key
Summary
Type
Status
Assignee
DDC-1449 Create postFlush event Sub-task Resolved Benjamin Eberlei  

 Description   

Hi!

According to http://www.doctrine-project.org/docs/orm/2.1/en/reference/events.html

Current event system seem to be not as flexible as it could be.

1. According Lifecycle Events of the entity (marked with @HasLifecycleCallbacks annotation tag):
It would be useful to have access to Entity Manager inside the callbacks. This could be achieved by passing the entity manager as a parameter to all these callbacks.

Here is the situation:
I have an entity for a news item. After somehow modifying this entity and before persisting I want to be able to change the inner association of images linked to this news (for example parsed from news body text). From the OO point of view it's a task of the News entity itself so this should be done a callback. But since inside callback I do not have access to entity manager (to find existing image entities and only if not found creating a new one) I cannot do this.
This leads to creating a separate event listener which is split from the news entity (and that is not possible, see 2.).

Passing entity manager to callbacks may improve it's usefulness.

2. Currently there is no events to be called before the changes have been computed. And there is no callback to be called after flush has been finished. (preFlush, postFlush)
The problem:
Assume we have a News entity. I want to modify external system (even not written in PHP) via remote call after any change to news being made. This has to be called AFTER the flush has persisted all the changes. Currently the only place to do this is onFlush (which is called before the persisting is done).
PostPersist, postRemove, postUpdate cannot be used as it's called after each one entity is modified and we cannot tell when all entites has been processed.

Also I faced a problem when implementing the event listener for situation 1. If I register the onFlush listener - the entites changeset is already calculated. If I change something according associations I loose this changes.
If I call $unitOfWork->computeChangeSet($classMetadata, $entity) or $unitOfWork->recomputeSingleEntityChangeSet($classMetadata, $entity); I only get the changes being made after previous changeset calculation loosing the initial changes. I think the preFlush could be a lifesaver for this (to be called before computing the changeset for the first time).






[DDC-1429] Add a method to the unit of work that merges any detached entity into UoW without calling SQL Created: 17/Oct/11  Updated: 17/Oct/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

This is for those that know what they are doing






[DDC-1320] Ship Immutable date time with Doctrine Common, use in ORM - Should implement __toString() Created: 06/Aug/11  Updated: 31/Oct/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

Type: Improvement Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None

Issue Links:
Dependency
depends on DDC-1316 Insert statement for joined subclass ... Resolved

 Comments   
Comment by Benjamin Eberlei [ 31/Oct/11 ]

Has to be pushed back as immutable date time cannot be implemented in userland that well.





[DDC-1262] Have proxies copy docblocks aswell Created: 09/Jul/11  Updated: 09/Jul/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0.6, 2.1, Git Master
Fix Version/s: 2.x
Security Level: All

Type: Improvement Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Whenever a Proxy is generated it does not copy the docblocks.

This means when you do something like "$refl = new ReflectionObject($proxy)" you might be in trouble.

However if we add docblocks then we have to make sure that proxies do not magically appear as entities by throwing an exception in the AnnotationDriver.






[DDC-1219] Remove dependancy on Collection interface in Domain Objects Created: 21/Jun/11  Updated: 04/Jul/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1
Fix Version/s: 2.x
Security Level: All

Type: Improvement Priority: Major
Reporter: André R. Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Short: This issue is all about being able to use doctrine with naked domain objects without any use of doctrine classes.
I 'm not talking about PersistentCollection here, fully aware of that being tied into Doctrine, but those are injected, this is all about code dependency on ArrayCollection.

Seems like some of the UnitOfWork code is cable of handling other types of arrays, like:

    // If $actualData[$name] is not a Collection then use an ArrayCollection.
    if ( ! $actualData[$name] instanceof Collection) {
        $actualData[$name] = new ArrayCollection($actualData[$name]);
    }

But in __cascade* functions this is not the case in all but two:

    if ($relatedEntities instanceof Collection) {
        if ($relatedEntities instanceof PersistentCollection) {
            // Unwrap so that foreach() does not initialize

2 however have:

    if (($relatedEntities instanceof Collection || is_array($relatedEntities))) {
        if ($relatedEntities instanceof PersistentCollection) {
            // Unwrap so that foreach() does not initialize

Would it be an idea to do "instanceof Traversable" instead of " instanceof Collection"?



 Comments   
Comment by André R. [ 21/Jun/11 ]

Note: If the fist code block is always performed before the last 2 blocks then there is no issue here, just a need to make it more clear in Doc that this is possible but that you should not rely custom implementation as PersistentCollection will be injected when loaded from db.





[DDC-1137] SchemaTool#getUpdateSchemaSql() does not respect database identifier in table names Created: 05/May/11  Updated: 14/May/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM, Tools
Affects Version/s: 2.0.4
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Hugh Lomas Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Linux 2.6.18-194.32.1.el5.centos.plus x86_64 GNU/Linux



 Description   

Given two databases, 'foo' and 'bar', with entities in /Entities/Foo/ annotated as follows:

/**
 * Test
 *
 * @Table(name="foo.test")
 * @Entity
 */

Create an EntityManager instance with

$connectionOptions = array( 
    'dbname' => 'Foo', 
    'driver' => 'pdo_mysql', 
    <..etc..>
);

Use EntityManager#getClassMetaData( "Entities\\Foo
Test" ) to pass to SchemaTool#createSchema() and Doctrine appropriately creates a database table foo.test

Use EntityManager#getClassMetaData( "Entities\\Foo
Test" ) to pass to SchemaTool#updateSchema() and Doctrine fails with Exception
-> SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'test' already exists

Inserting

die( print_r( $fromSchema, 1 ) . print_r( $toSchema, 1 ) . print_r( $schemaDiff, 1 ) );

into Doctrine/ORM/Tools/SchemaTool.php line 632 shows $fromSchema outputs

[_tables:protected] => Array
        (
            [test]

but $toSchema outputs

[_tables:protected] => Array
        (
            [foo.test]

which causes $schemaDiff to output

[newTables] => Array
        (
            [foo.test]

In summary, Doctrine/DBAL/Schema/Comparator considers foo.test a new table, because Doctrine/DBAL/Schema/AbstractSchemaManager lists its table as "test" rather than "foo.test".



 Comments   
Comment by Hugh Lomas [ 05/May/11 ]

It seems that changing AbstractSchemaManager.php to the following corrected the issue for me, however I am not sure of any repercussions that may arise as a result, being unfamiliar with the codebase.

Doctrine/DBAL/Schema/AbstractSchemaManager.php line 228

return new Table( $tableName, $columns, $indexes, $foreignKeys, false, array());

Doctrine/DBAL/Schema/AbstractSchemaManager.php line 228

return new Table( $this->_conn->getDatabase() . "." . $tableName, $columns, $indexes, $foreignKeys, false, array());

Comment by Benjamin Eberlei [ 14/May/11 ]

Multi databases are not supported by schema manager and schema tool yet.





[DDC-1016] Example code does not reflect real code Created: 03/Feb/11  Updated: 03/Feb/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0.1
Fix Version/s: None
Security Level: All

Type: Documentation Priority: Major
Reporter: thoth Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Website



 Description   

http://www.doctrine-project.org/docs/orm/2.0/en/reference/working-with-objects.html#entity-state

In the switch cases all the UnitOfWork constants are invalid.

Example:
UnitOfWork::NEW instead of being UnitOfWork::STATE_NEW






[DDC-999] DQL always needs a FROM clause, should be changed Created: 23/Jan/11  Updated: 23/Jan/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0
Fix Version/s: None
Security Level: All

Type: New Feature Priority: Major
Reporter: Timo A. Hummel Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: None


 Description   

Sometimes a developer needs to issue a query without a FROM clause. This especially occurs using the QueryBuilder, when you may or may not have a table to select from, but call a stored procedure always.

Example:

$query = $em>createQuery('SELECT (1+1)');

The above query fails because the lexer expects T_FROM. If you replace (1+1) with a stored procedure, this example makes more sense.

One might argue about that you should use DBAL directly, but I disagree, because it always can happen that you end up in a situation like this:

$qb = $em->createQueryBuilder();

$qb->select("SOMEFANCYPROCEDURE()");

if ($condition) {
  $qb = $qb->from("additionalTable t");
}





[DDC-785] Post-Post-Persist event Created: 02/Sep/10  Updated: 14/Jan/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0-BETA4
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: arnaud-lb Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 0
Labels: None


 Description   

postPersist/postUpdate events are triggered in the middle of a unitOfWork, and querying the DB in such events causes infinite loops. Doctrine attempts to flush the entity manager before running any query, which triggers flushing of entities, and postPersist/postUpdate events are triggered again.

I did not checked, but the flush() before each query may be a performance problem too, if doctrine has to determine what has changed, depending on the changetracking policy.

Also, it would be great if postPersist / postUpdate events were triggered after all entities have been persisted. It looks like that entities are flushed by groups of same 'type', and that events for a type are triggered once all of the elements of that group have been flushed, potentially before entities of an other type have been flushed : postPersist / postUpdate events are triggered while some other entities are still not flushed.



 Comments   
Comment by Benjamin Eberlei [ 03/Sep/10 ]

That is documented and for perfomance reasons we cannot move the preUpdate/postUpdate/prePersist/postPersist events to other locations inside the UnitOfWork.

There is an onFlush event that allows for more flexibility and is triggered before any update/insert/delete is done by the UnitOfWork.

Comment by arnaud-lb [ 04/Sep/10 ]

Thanks.

I understand that. Is there any chance of getting some onPostFlush or similar, which would be triggered like onFlush, but after all update/insert/delete ? Or just some post-something event which is allowed to issue db queries.

Comment by Gediminas Morkevicius [ 24/Sep/10 ]

onFlush you can store your entity for furher processing and on postPersist you can check if there are no more insertions and process the entity if it needs additional query
I have faced all these issues and you can check http://github.com/l3pp4rd/DoctrineExtensions/tree/master/lib/DoctrineExtensions/Translatable/
for a solution to your problem

Comment by Gediminas Morkevicius [ 14/Jan/11 ]

I think this issue should be closed since the main reason of opening it was the possibility to execute additional queries when inserts were pending in unit of work. In current release it does not cause a flush during an additional query execution anymore.





[DDC-779] Doctrine\ORM\Configuration should be immutable after construction of EntityManager Created: 30/Aug/10  Updated: 30/Aug/10

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0-BETA3
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Benjamin Eberlei Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Currently the Doctrine\ORM\Configuration instance is not immutable after construction of the EM, which can lead to funny behavior when changing essential dependencies such as caches or others.






[DDC-763] Cascade merge on associated entities can insert too many rows through "Persistence by Reachability" Created: 23/Aug/10  Updated: 04/Jul/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

Type: Improvement Priority: Major
Reporter: Dave Keen Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 2
Labels: None

Attachments: Text File 0149-DDC-763.patch     File DDC763Test.php     File multipleaddmerge.diff    

 Description   

I think that the UnitOfWork needs to maintain a map of spl_object_hash($newEntity)->$managedEntity for entities that were persisted via reachability during a merge. doMerge should then only call persistNew if the original entity has not already been persisted (if it has already been persisted it should merge the managed entity from the map). The map should be maintained until a flush() or until the UnitOfWork is cleared. The reasoning is as follows.

Imagine we have a simple doctor object with no associations:

$doctor = new Doctor();
$em->persist($doctor);
$em->persist($doctor);
$em->flush();

After the first persist() $doctor is MANAGED so the second persist has no effect and this results in a single Doctor row.

If we do the same thing using merge and persistence by reachability:

$doctor = new Doctor();
$em->merge($doctor);
$em->merge($doctor);
$em->flush();

we get 2 Doctor rows being added.

Obviously in this particular case we should use the return value from the first merge() as the parameter of the second merge which would give correct behaviour.

However, now imagine one Doctor has many Patients and many Patients have one Doctor, all the associations have cascade merge enabled, and further assume that $d1 (Doctor id=1) is already in the database. We now attempt to create two patients and assign them to the existing doctor:

$d1= new Doctor(); $d1->id = 1; // This is a DETACHED entity

$p1 = new Patient();
$p2 = new Patient();

$d1->patients->add($p1); $p1->doctor = $d1;
$d1->patients->add($p2); $p2->doctor = $d1;

$em->merge($p1);
$em->merge($p2);

$em->flush();

This actually results in 4 rows being added to the 'patients' table instead of 2, I think because $p1 and $p2 are getting persisted both as the root objects and then again from the patient->doctor->patients array. Since the cascade merging happens internally we can't replace the array contents with the managed return values without walking through the object graph (in which case there is no point in using cascade merge in the first place). Maintaining a map in UnitOfWork will allow doMerge to ensure it doesn't persist the same entities twice.

I'm not sure, but this might be relevant for cascade persist too.

P.S. Another bug report on this can be found at http://code.google.com/p/flextrine2/issues/detail?id=32 (it basically says the same thing with different entities).



 Comments   
Comment by Benjamin Eberlei [ 29/Aug/10 ]

@Roman A possible fix for this in my opinion is another map in UnitOfWork $mergedEntities = array(); and a patch like this:

diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php
index 242d84b..1d0d8b3 100644
--- a/lib/Doctrine/ORM/UnitOfWork.php
+++ b/lib/Doctrine/ORM/UnitOfWork.php
@@ -1340,6 +1340,10 @@ class UnitOfWork implements PropertyChangedListener
             return; // Prevent infinite recursion
         }
 
+        if (isset($this->mergedEntities[$oid])) {
+            return $this->mergedEntities[$oid];
+        }
+
         $visited[$oid] = $entity; // mark visited
 
         $class = $this->em->getClassMetadata(get_class($entity));
@@ -1468,6 +1472,8 @@ class UnitOfWork implements PropertyChangedListener
 
         $this->cascadeMerge($entity, $managedCopy, $visited);
 
+        $this->mergedEntities[$oid] = $managedCopy;
+
         return $managedCopy;
     }
Comment by Dave Keen [ 29/Aug/10 ]

I have tested this patch with my application and it fixes the problem in all my relevant test cases apart from one. The test case that's failing is one that persists a bi-directional many to many relationship, so the associations interweave with each other (if you know what I mean).

I wonder if perhaps doMerge need to continue cascading even if it finds an item in $this->mergedEntities

This is the Flextrine code that fails - it results in no entries in movie_artist. This might also be related to DDC-758?

m1 = new Movie();
m1.title = "Movie 1";

m2 = new Movie();
m2.title = "Movie 2";

a1 = new Artist();
a1.name = "Artist 1";

a2 = new Artist();
a2.name = "Artist 2";

m1.artists.addItem(a1); a1.movies.addItem(m1);
m1.artists.addItem(a2); a2.movies.addItem(m1);

m2.artists.addItem(a1); a1.movies.addItem(m2);
m2.artists.addItem(a2); a2.movies.addItem(m2);

// These translate to cascade merges on the server
em.persist(m1);
em.persist(m2);
em.persist(a1);
em.persist(a2);

// Now flush
em.flush();

Comment by Dave Keen [ 29/Aug/10 ]

P.S. This test passes if I translate em.persist() to $em->persist() (not cascading) on the server instead of translating it to a cascade merge; not sure if that helps

Comment by Roman S. Borschel [ 30/Aug/10 ]

I'd really like to avoid introducing an additional instance variable just to solve this issue but I did not find the time yet to really look into it.

Does someone have a unit test for this already and can attach it to the issue?

Comment by Roman S. Borschel [ 31/Aug/10 ]

Rescheduling for RC1.

Comment by Dave Keen [ 13/Sep/10 ]

Here is a functional test case containing three tests:

testMultiMerge tests basic merging of two new entities, checking that only a single entity ends up in the database. This passes with Benjamin's patch.

testMultiCascadeMerge tests the more complex case of merging a OneToMany association. This also passes with Benjamin's patch.

testManyToManyPersistByReachability tests the ManyToMany case described above and this fails with Benjamin's patch, probably because doMerge doesn't cascade down entities that it has already merged and some ManyToMany associations are being ignored. Its a bit hard to be certain what is causing this as even without Benjamin's patch this test would fail due to DDC-758.

Comment by Benjamin Eberlei [ 15/Sep/10 ]

@Roman i thought about this issue, its not possible without that additional map of merged entities. There is no way we can get that information from other sources.

Problem is rather that the use-case probably only applies in mass-merging scenarios and client-server serialization.

Comment by Dave Keen [ 21/Sep/10 ]

Added another failing test case - adding the same entity from different ends of a many to many bi-directional association to check that there isn't an integrity constraint violation caused by Doctrine trying to add the same row twice.

Comment by Dave Keen [ 21/Sep/10 ]

Attached a patch for this issue.

Comment by Benjamin Eberlei [ 22/Sep/10 ]

can you comment why all the additionall stuff is necessary compared to my patch?

Comment by Dave Keen [ 22/Sep/10 ]

It fixes the two additional test cases - testManyToManyPersistByReachability and testManyToManyDuplicatePersistByReachability.

testManyToManyPersistByReachability was failing with your original patch because there are ManyToMany cases where an entity may have already been merged, but its still necessary to add it to an association and continue to cascade. Running the following with the original patch will miss out some of the associations.

$m1 = new Movie();
$m1->title = "Movie 1";

$m2 = new Movie();
$m2->title = "Movie 2";

$a1 = new Artist();
$a1->name = "Artist 1";

$a2 = new Artist();
$a2->name = "Artist 2";

$m1->artists->add($a1); $a1->movies->add($m1);
$m1->artists->add($a2); $a2->movies->add($m1);
$m2->artists->add($a1); $a1->movies->add($m2);
$m2->artists->add($a2); $a2->movies->add($m2);

$em->merge($a1);
$em->merge($a2);
$em->flush();

The other change in my patch is to protect against this case. It ensures that the following code doesn't add the same entity twice to a collection.

$em->merge($m1);
$em->merge($m2);
$em->merge($a2);
$em->merge($a2);
$em->flush();
Comment by Benjamin Eberlei [ 31/Oct/10 ]

I am not sure if the issue here is rather multiple calls to merge that contain different parts of the same object-graph.

There should be a very simple fix for this, call ->clear() after each merge.

I am not sure if this patch drags us into a blackhole of issues with merging.

Comment by Dave Keen [ 31/Oct/10 ]

Calling ->clear() and ->flush() after each merge is a workaround for the simple case, but unless I am misunderstanding I don't think its a solution for cases where the merging is happening automatically in cascadeMerge. I've actually encountered this issue in another project and scenario to do with creating REST APIs and merging JSON objects into entities, and applying the patch fixed it so a) I think this issue might be a more common that we first thought and b) the patch basically seems to work (plus it doesn't introduce any failing cases in the existing test suite). I can actually still find one edge case to do with cascading merging interlinked many to many associations that this doesn't fix, but I was planning to open that as a new ticket after this My feeling is that the current merge already has issues and this definitely improves it.

Comment by Benjamin Eberlei [ 01/Nov/10 ]

It cannot happen inside a single merge, single merges use the $visited to avoid infinite recursions, each entity can only be merged once inside a single merge operation.

Comment by Benjamin Eberlei [ 10/Nov/10 ]

Added a note into the documentation about using EntityManager#clear between merging of entities which share subgraphs and cascade merge.

Handling this issue in UnitOfwork will be declared an improvement, not a bug anymore and be scheduled for later releases. The required changes to the core are to dangerous and big.

Comment by Dave Keen [ 11/Nov/10 ]

Where in the docs is that?

Just to summarize, the equivalent operation to having multiple merges and a single flush is to call merge followed by flush each time, with the whole thing surrounded by a transaction? Does this have a big impact on performance?

Comment by Dave Keen [ 11/Nov/10 ]

Ben - even given the decision not to implement this (and I do understand your thinking, as it is a major change), is there any reason not to implement the bit that ensures that the same entity isn't added to a collection twice during a merge? I can't think of a situation where this should be allowed, and I have a use case where I get 'DUPLICATE KEY' errors if this isn't there.

Please see attached patch.

Comment by Benjamin Eberlei [ 11/Nov/10 ]

What bit of that huge patch is that? Can you extract it into another ticket if thats possible?

Comment by Benjamin Eberlei [ 11/Nov/10 ]

I added it to "Working with Objects" and the descripton of Merge. Its not yet live on the site.

Using this current workaround has a performance impact, since more SELECT statements have to be issued against the database.

Comment by Dave Keen [ 11/Nov/10 ]

Apologies for not being clear - only the 3rd patch (multipleaddmerge.diff) is relevant to the 'DUPLICATE KEY' error I am now talking about, but I'll put it in a nother ticket if you prefer.

Comment by Benjamin Eberlei [ 11/Nov/10 ]

please add a new ticket, patch looks good.

Comment by Dave Keen [ 11/Nov/10 ]

Created as DDC-875





[DDC-688] Original Entity Data gets overridden by the change set Created: 12/Jul/10  Updated: 28/Dec/10

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0-BETA2
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Jasper Kuperus Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Mac OS X 10.6; PHP 5.3.2; MySQL 5.1.44



 Description   

When changing data in an entity, the UnitOfWork will call computeChangeSet on a flush event. If there is a changeset, the original data ($this->_originalEntityData) gets overridden by the new data. However, the _originalEntityData should hold the original data, that was present at the time the entity was reconstituted from the database. This does no longer hold now.

I think this can simply be fixed by commenting this line, however I do not know of any consequences this may bring with it:

$this->_originalEntityData[$oid] = $actualData; (in computeChangeSet, after if( $changeSet ));

Anyway, I ran into this problem while trying to retrieve the original data at the onFlush event of an update.



 Comments   
Comment by Roman S. Borschel [ 08/Aug/10 ]

This is actually currently expected. You can not get access to the original data in the onFlush event right now. I'm not saying that this will never be possible but it is simply the way it works at the moment.

Comment by Jasper Kuperus [ 08/Dec/10 ]

Does this mean that it is currently impossible to implement a Versionable mechanism using snapshots?

Comment by Benjamin Eberlei [ 09/Dec/10 ]

You can hold a map of them yourself if your listener also implements the "postLoad" event:

$entity = $args->getentity();
$this->originalData[spl_object_hash($entity)] = $args->getEntityManager()->getUnitOfWork()->getOriginalData($entity);
Comment by Benjamin Eberlei [ 28/Dec/10 ]

Changed into possible improvement for the future





[DDC-683] EntityManager#lock() on unitialized proxy coudl be optimized Created: 10/Jul/10  Updated: 21/Jul/10

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0-BETA2
Fix Version/s: None
Security Level: All

Type: New Feature Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None

Issue Links:
Reference
relates to DDC-681 PATCH: UnitOfWork#lock locks by colum... Resolved

 Description   

If you call lock() on an unitiialized proxy, it would be possible to combine the fetch and lock in one operation. Is this feasible from a technical / workflow perspsective?



 Comments   
Comment by Benjamin Eberlei [ 21/Jul/10 ]

Ok this is what refresh() with LOCK support is actually needed for:

    public function lock($entity, $lockMode, $lockVersion = null)
    {
        if ($this->getEntityState($entity) != self::STATE_MANAGED) {
            throw new InvalidArgumentException("Entity is not MANAGED.");
        } else if ($entity instanceof Proxy && $entity->__isInitialized__) {
            $this->refresh(....); // with LOCK!
        }
        ...
    }




[DDC-676] Find a way to test serialize/unserialize of all ClassMetadata properties in isolation Created: 10/Jul/10  Updated: 29/Aug/10

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

Type: Improvement Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

We should find a way, using PHPUnit Data Providers or anything else, to check the serialize/unserialize of every property in the ClassMetadata instance, since errors here can be very subtle but dangerous.






[DDC-667] Lock Timeout Query Hint for DQL Queries Created: 04/Jul/10  Updated: 16/Sep/10

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0-BETA2
Fix Version/s: 2.x
Security Level: All

Type: New Feature Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

After the implementation of DDC-178 there is now only outstanding the support for locking queries based on a given timeout.

This will be a DQL query feature only and be available via a query hint:

$query->setHint(Query::LOCK_TIMEOUT, $timeoutMs);

It will be only working on Oracle.



 Comments   
Comment by Roman S. Borschel [ 30/Aug/10 ]

If this is to be implemented for 2.0, it needs to happen for RC1, therefore rescheduling to RC1. Feel free to reschedule to 2.x if necessary.

Comment by Benjamin Eberlei [ 16/Sep/10 ]

Only oracle supports lock timeouts and no other vendor seems to plan to support it. I move to 2.x, but i guess this would rather be an issue of user extension.





[DDC-668] add upsert support Created: 04/Jul/10  Updated: 20/Dec/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

Type: New Feature Priority: Major
Reporter: Lukas Kahwe Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 4
Labels: None


 Description   

Didnt find anything in the docs on this. Is D2 capable of doing an UPSERT [1] in case I am trying to persist an object that may or may not have been saved previously. Different RDBMS support different syntax for this case. Like MySQL has INSERT .. ON DUPLICATE KEY UPDATE (or even INSERT IGNORE) while the SQL standard defines a MERGE syntax which seems to be gaining support. Of course you can always fallback to a SELECT FOR UPDATE (or if you want to be hacky an INSERT which catches duplicate key violations .. but probably not a good idea since many RDBMS rollback on a failure inside a transaction).

[1] http://en.wikipedia.org/wiki/Upsert

See also http://opensource.atlassian.com/projects/hibernate/browse/HHH-3011 asking for MERGE support

Ideally there would be a way to define on a model or model instance level if merge logic should be applied.



 Comments   
Comment by Robert Burkhead [ 09/Jul/10 ]

Doctrine_Record defines a replace() method.

In the MySQL Doctrine implementation, however, it is not the same as INSERT .. ON DUPLICATE KEY UPDATE. The replace() method implemented in Doctrine_Connection_Mysql uses the REPLACE INTO syntax, which is a DELETE and then INSERT when the key exists. This is fine, except for tables that use auto-increment fields. The delete-then-insert operation yields a new auto-incremented value, whereas INSERT .. ON DUPLICTATE KEY UPDATE would not.

Comment by Lukas Kahwe [ 09/Jul/10 ]

MySQL (and SQLite) REPLACE is a no go. It causes way too much disc I/O and worse yet totally screws up the on disk data structures because of the deleting.

Comment by Benjamin Eberlei [ 31/Jul/11 ]

Scheduled for 2.2

Comment by Benjamin Eberlei [ 31/Jul/11 ]

Evaluating this makes me sad, except MySQL support for this is rather non-existant, and the oracle merge is aiming at batch operations.

Comment by Benjamin Eberlei [ 22/Oct/11 ]

Should this be done with

1. Select first, then insert
2. Catch and evaluate exception then update

I am leaning towards 1.

Comment by Guilherme Blanco [ 20/Dec/11 ]

Updating fix version





Allow @Id on @ManyToOne fields (DDC-117)

[DDC-658] Reverse engineering with Oracle (DBDriver and Associations as Identifier) Created: 27/Jun/10  Updated: 11/Dec/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

Type: Sub-task Priority: Major
Reporter: Mickael Perraud Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: None
Environment:

Ubuntu 10.04 + Oracle 11g Entreprise + PHP 5.3.2 + Doctrine2 Git (up-to-date)



 Description   

I am playing with reverse engineering with Oracle and I have some problems:

My schema:

drop table PHONE_NUMBER;
drop table CUSTOMER;

create table CUSTOMER (
   CUSTOMER_ID             NUMBER(4)                       not null,
   CUSTOMER_LASTNAME       VARCHAR2(50)                    not null,
   CUSTOMER_MODIFIED       DATE,
   constraint PK_CUSTOMER primary key (CUSTOMER_ID)
         using index
       tablespace TBS_INDEX
       storage
       (
           initial 100K
           next 100K
       )
)
storage
(
    initial 100K
    next 100K
)
tablespace TBS_DATA;

create table PHONE_NUMBER (
   PHONE_NUMBER_ID         NUMBER(4)                       not null,
   CUSTOMER_ID             NUMBER(4)                       not null,
   PHONE_NUMBER            VARCHAR2(50)                    not null,
   PHONE_NUMBERMODIFIED    DATE,
   constraint PK_PHONE_NUMBER primary key (PHONE_NUMBER_ID, CUSTOMER_ID)
         using index
       tablespace TBS_INDEX
       storage
       (
           initial 100K
           next 100K
       )
)
storage
(
    initial 100K
    next 100K
)
tablespace TBS_DATA;

alter table PHONE_NUMBER
   add constraint PHONE_NUMBER__CUSTOMER foreign key (CUSTOMER_ID)
      references CUSTOMER (CUSTOMER_ID);

I obtain "Fatal error: Uncaught exception 'Doctrine\ORM\Mapping\MappingException' with message 'Property "customerId" in "PhoneNumber" was already declared, but it must be declared only once'"

It's because a foreign key is a component of the primary key.



 Comments   
Comment by Mickael Perraud [ 28/Jun/10 ]

This is the continuation of http://www.doctrine-project.org/jira/browse/DDC-616. Only the schema is different.

Comment by Benjamin Eberlei [ 28/Jun/10 ]

just for understanding this scenario:

Is this a One-To-One relation and the TABLE_TEST2 "inherits" the primary key from its parent TABLE_TEST1?

If yes, this construct is not yet supported by Doctrine 2, we still need to include an ID-Generator that supports this kind of schema.

Comment by Mickael Perraud [ 28/Jun/10 ]

Change for a more understandable use case. Note that it's not my real use case and that I work on legacy database on which I can't change the structure.

Comment by Benjamin Eberlei [ 01/Jan/11 ]

updated the issue topic to get a better grasp of what needs to be done here.

Comment by waldo [ 09/Jun/11 ]

I have the same error with Mysql whit the same condition.

Comment by Benjamin Eberlei [ 28/Nov/11 ]

More details on the work to be done:

The relevant code is in Doctrine/ORM/Mapping/Driver/DatabaseDriver.php only.

The idea is currently many-to-many tables are detected by checking that the table has foreign keys on all the primary key columns (no additional columns!)

Now with the 2.1 feature of foreign key/primary key entities this is not necessarily true anymore. You can have the primary keys being foreign keys BUT have additional columns that are not part of the primary key. This has to be detected.

If a foreign key-primary-key entity is found that has additional columns a ClassMetadata has to be created and the associations have to be created with the "id" => true flag in mapManyToOne().

Comment by Scott Steffens [ 11/Dec/11 ]

For what it's worth, I'm getting this error when I have a PK that is a single column and not a FK.

PRIMARY KEY (`id`),
UNIQUE KEY `cycle_station_id` (`cycle`,`station_id`),
KEY `station_id_idx` (`station_id`),
KEY `readings` (`readings`),
KEY `source` (`source`),
KEY `temperature_min_max` (`temperature_max`,`temperature_min`),
KEY `station_id_cycle` (`station_id`,`cycle`,`updated_at`),
CONSTRAINT `compiled_1_station_id_stations_id` FOREIGN KEY (`station_id`) REFERENCES `stations` (`id`),
CONSTRAINT `compiled_1_station_id_stations_id_1` FOREIGN KEY (`station_id`) REFERENCES `stations` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=160833690 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci





[DDC-265] Possibility for Nested Inheritance Created: 21/Jan/10  Updated: 16/Jan/13

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: New Feature Priority: Major
Reporter: Michael Fürmann Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 0
Labels: None

Issue Links:
Duplicate
duplicates DDC-138 Allow for mixed inheritance mapping Open

 Description   

It would be great if Doctrine had the possibility to define a further inharitance in a subclass.

Example:
There is a class DataObject managing things like created- and lastedit-
timestamps, archiving objects before updates, ...
One of the sub-objects is Content.
There are several types of content.
Written directly to a database field, read from a textfile on server,
executed php file on server, loaded from another server via xmlrpc and
so on.

I'd like to use a single table inheritance to map all information of
the different content objects in one table.
If I understand the model right the only alternate solution would be
to write each single content object to the discriminator map of
DataObject.



 Comments   
Comment by Benjamin Eberlei [ 21/Jan/10 ]

The DataObject you describe is a no-go for Doctrine 2. Its just a very bad practice.

Inheritance Mapping is for REAL inheritance only, otherwise you shouldnt go with a relational database in the first place.

You should use the Event system for such changes, it offers you roughly the same possibilities and keeps you from having to use inheritance mapping. You could still create an abstract data object and define the fields that will be used in each "implementation" and then in events do something like:

if ($entity instanceof DataObject) {
     $entity->updated();
     $archiver->makeSnapshot($entity);
}
Comment by Jonathan H. Wage [ 20/Mar/10 ]

With this patch I think you could setup a nice similar model where you can introduce new children of this parent class and have it added to the discriminator map from the child instead of having to modify the parents mapping information.

http://www.doctrine-project.org/jira/browse/DDC-447





[DDC-3091] Not set entity to results if use query with JOIN Created: 17/Apr/14  Updated: 17/Apr/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Vitaliy Zhuk Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Hi.
I have a problem, if i can use query with JOIN without grouping (DISTINCT) by identifier entity. Problem: not set entities to result, if entity has cached in ObjectHydration.

For example:

SQL query:

SELECT 
  b0_.id AS id0,
  b0_.hash AS hash1, 
  b0_.mii AS mii2, 
  b0_.iin AS iin3, 
  b0_.last_digits AS last_digits4, 
  b0_.number AS number5, 
  b0_.holder AS holder6, 
  p1_.keyword AS keyword7, 
  t2_.client AS client8, 
  CONCAT(b0_.hash, CONCAT(p1_.keyword, t2_.client)) AS sclr9 

FROM bank_card b0_ 
  INNER JOIN transaction_bank_card t2_ ON (t2_.bank_card_id = b0_.id) 
  INNER JOIN projects p1_ ON (t2_.project_key = p1_.keyword) 

WHERE (p1_.keyword = 'project1' AND t2_.client = '123') OR (p1_.keyword = 'project2' AND t2_.client = '321') /* ... Other where */

GROUP BY sclr9

Mysql result:

id0 hash1 mii2 iin3 last_digits4 number5 holder6 keyword7 client8 sclr9
28 1d741fd06f3315dad28039926effc5d7 5 533330 2763 533330******2763 John Doe p6 78165 1d741fd06f3315dad28039926effc5d7p678165
34 58b021876f625e3000137cd835f5fe40 5 555456 5047 555456******5047 OLOLO OLOLO p6 78165 58b021876f625e3000137cd835f5fe40p678165
2 887d30e9b4d18676c6e0dc8e21e36d28 5 556458 4251 556458******4251 Monkey Testing p6 78165 887d30e9b4d18676c6e0dc8e21e36d28p678165
1 bb14a77f2e363cd144b669f0b594d304 4 432114 1118 432114******1118 Monkey Testing p6 100673 bb14a77f2e363cd144b669f0b594d304p6100673
1 bb14a77f2e363cd144b669f0b594d304 4 432114 1118 432114******1118 Monkey Testing p6 100922 bb14a77f2e363cd144b669f0b594d304p6100922
1 bb14a77f2e363cd144b669f0b594d304 4 432114 1118 432114******1118 Monkey Testing p6 101441 bb14a77f2e363cd144b669f0b594d304p6101441
1 bb14a77f2e363cd144b669f0b594d304 4 432114 1118 432114******1118 Monkey Testing p6 78165 bb14a77f2e363cd144b669f0b594d304p678165
1 bb14a77f2e363cd144b669f0b594d304 4 432114 1118 432114******1118 Monkey Testing p6 85550 bb14a77f2e363cd144b669f0b594d304p685550
1 bb14a77f2e363cd144b669f0b594d304 4 432114 1118 432114******1118 Monkey Testing p6 85566 bb14a77f2e363cd144b669f0b594d304p685566
1 bb14a77f2e363cd144b669f0b594d304 4 432114 1118 432114******1118 Monkey Testing p6 85768 bb14a77f2e363cd144b669f0b594d304p685768

And the PHP code (from custom entity repository):

$qb
            ->select('bc')
            ->addSelect('p.key AS project_key')
            ->addSelect('tbc.client AS client')
            ->addSelect('CONCAT(bc.hash, CONCAT(p.key, tbc.client)) AS unique_key')
            ->innerJoin('FooBundle:TransactionBankCard', 'tbc', 'WITH', 'tbc.bankCard = bc.id')
            ->innerJoin('BarBundle:Project', 'p', 'WITH', 'tbc.project = p.key')
            ->where($orX)
            ->groupBy('unique_key');

        $result = $qb->getQuery()->getResult();

And this code returned only unique entities by identifier (Identifier: id field), but must returned the all entities from query.

The Object Hyndration has cached created entities, and if the next row is entity (indicate as identifier and dql alias), then hydration not set this entity to result.
Problem code: https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php#L569-L572

Thank.






[DDC-2783] EntityManager::transactional empty values as true Created: 07/Nov/13  Updated: 18/Apr/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Kirill chEbba Chebunin Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: entitymanager, transactional


 Description   

The problem:
Any response from transactional callback which is evaluated to false (empty array, empty string, 0, null, etc) becomes true

$return = call_user_func($func, $this);

$this->flush();
$this->conn->commit();

return $return ?: true;

There is the old resolved issue DDC-1336, which describes this behavior.
@return tag is clear now.

@return mixed Returns the non-empty value returned from the closure or true instead

But this logic is blowing mind and leading to unexpectable results. The expected behavior is just return callback result, i don't see any good use cases for current implementation.

It requires a BC break. Can the deprecation process be started to change this behaviour in few major releases?



 Comments   
Comment by Christophe Coevoet [ 07/Nov/13 ]

I agree that this makes the method hard to use. And I don't undertstand why it would replace the return value.

What was the intention for this Benjamin ?

Comment by Guilherme Blanco [ 18/Apr/14 ]

Christophe Coevoet Benjamin Eberlei I'm considering to remove the ternary and always return the callback result.
What do you think? It seems like a minor BC break, but would like to get more feedback around this.

Comment by Marco Pivetta [ 18/Apr/14 ]

Guilherme Blanco this was already refused before because of the BC break.





[DDC-3096] JoinColumn definition does not regard column type with value translation Created: 22/Apr/14  Updated: 22/Apr/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.4.2
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Volker Nauruhn Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: entityPersister, mapping, mysql, orm
Environment:

Symfony 2.4.3



 Description   

I made a custom column type for doctrine which converts values between MySQL and PHP.

When I use a field with this column type as JoinColumn in a ManyToOne relation plus the column has a different name than the field, the BasicEntityPersister gets always "null" when he is asking for type of the given column name because he is ascing for given column name and not field name.

Example
=====================

Make.php:

/**
 @ORM\Column(name="language_code", type="locale")
 */
private $locale;

Foobar.php

/**
 @ORM\ManyToOne(targetEntity="Make")
 @ORM\JoinColumn(name="make_locale", referencedColumnName="language_code")
 */
private $makes;

The localeType translates between long and short language codes. For exmaple "de" (PHP) to "de_DE" (MySQL).



 Comments   
Comment by Marco Pivetta [ 22/Apr/14 ]

This is not a blocker, as you're really going into custom implementations.

You should probably provide a failing test case to clarify what you are doing





[DDC-2917] Inheritance using joins generates invalid SQL when used in SELECT queries with GROUP BY on Postgresql Created: 15/Jan/14  Updated: 15/Jan/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Tom Pryor Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: None


 Description   

Say you have an entity with InheritanceType("JOINED"), some child entities defined in the DiscriminatorMap which include additional columns and are using PostgreSQL then try and execute a DQL query as below:

SELECT parententity FROM MyStuff\Entity\ParentEntity parententity GROUP BY parententity

Note: This is simplified for ease of reproduction, obviously the GROUP BY is pointless but in my actual query, which is significantly larger, the GROUP BY is actually useful.

PostgreSQL will give the following error:

SQLSTATE[42803]: Grouping error: 7 ERROR:  column "f2_.my_additional_column" must appear in the GROUP BY clause or be used in an aggregate function

Where f2_ is an alias in the actual SQL for one of the child entities.

This is because the SELECT in the actual SQL attempts to fetch the columns from the joined child entities but does not include them in the GROUP BY clause.

Bad SQL generated:

SELECT f0_.id AS id0, <f0_.* columns>, f2_.my_additional_column AS my_additional_column6
FROM parententitys f0_
LEFT JOIN childentity f2_ ON f0_.id = f2_.id
GROUP BY f0_.id, <f0_.* columns>

The SQL should be:

SELECT f0_.id AS id0, <f0_.* columns>, f2_.my_additional_column AS my_additional_column6
FROM parententitys f0_
LEFT JOIN childentity f2_ ON f0_.id = f2_.id
GROUP BY f0_.id, <f0_.* columns>, f2_.my_additional_column

N.b later versions of PostgreSQL don't require the GROUP BY on all the columns, just the primary key. Therefore the following would be sufficient:

SELECT f0_.id AS id0, <f0_.* columns>, f2_.my_additional_column AS my_additional_column6
FROM parententitys f0_
LEFT JOIN childentity f2_ ON f0_.id = f2_.id
GROUP BY f0_.id, f2_.id





[DDC-3115] UnitOfWok can't access proxies protected property Created: 04/May/14  Updated: 04/May/14

Status: Reopened
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Machete Assignee: Marco Pivetta
Resolution: Unresolved Votes: 0
Labels: orm
Environment:

php5.5.11-1~dotdeb.1
debian 7.5 64bit
apache2
doctrine-orm-module 0.8.0


Attachments: PNG File doctrine-error.PNG    

 Description   

Running the code on different environments for a while now, I have never had any problems. Recently I installed the code onto a different server and I've been experiencing the following issue:

> Fatal error: Cannot access protected property DoctrineORMModule\Proxy_CG_\Page\Entity\PageRevision::$date in src/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php on line 2596

I am absolutely clueless, why this happens. It seems to be affecting only specific data rows, as you might reproduce here: http://de.serlo.org/pages

The field is defined as followed:

    /**
     * @ORM\Column(type="datetime", options={"default"="CURRENT_TIMESTAMP"})
     */
    protected $date;

However, the exact same database snapshot works fine here: http://ptr.serlo.org/pages

Attached you will find a screenshot of the datarows. The yellow ones mark each one working and one not working row.

I have no idea what the problem is here.



 Comments   
Comment by Marco Pivetta [ 04/May/14 ]

Discussed this on IRC - very tricky, seems like one of the servers has the reflection property not set to "accessible"

Comment by Machete [ 04/May/14 ]

Adding `$class->reflFields[$field]->setAccessible(true)` before line 2596 resolved this issue. Even after removing it, everything worked fine.

note to self:
> [18:23] <@ocramius> machete_: can you find out where that particular property is instantiated?
> [18:23] <@ocramius> should be in `ClassMetadataInfo::wakeUpReflection()` or such
> [18:25] <@ocramius> if you find that again, consider looking at locations in the code where `new ReflectionClass()` is instantiated





[DDC-3104] Invalid count on EXTRA LAZY collection of SINGLE TABLE entities Created: 28/Apr/14  Updated: 20/May/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3.2
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Oleg Namaka Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: None

Issue Links:
Reference
relates to DDC-1595 Wrong count in relation with inheritance Resolved

 Description   
  • This issue relates to http://www.doctrine-project.org/jira/browse/DDC-1595
  • With the following entities
    • EntityPromotionAbstract entity:
      * @ORM\Entity
       * @ORM\InheritanceType("SINGLE_TABLE")
       * @ORM\Table(name="entity_promotion")
       * @ORM\DiscriminatorColumn(name="type", type="string")
       * @ORM\DiscriminatorMap({
       *     "brand"           = "BrandPromotion",
       *     "category"        = "CategoryPromotion",
       * })
       */
      abstract class EntityPromotionAbstract
      
    • CategoryPromotion entity:
       * @ORM\Entity
       */
      class CategoryPromotion extends EntityPromotionAbstract
      {
          /**
           * Category
           *
           * @var Category
           * @ORM\ManyToOne(targetEntity="Category", inversedBy="CategoryPromotions")
           * @ORM\JoinColumn(name="instance_id", referencedColumnName="category_id")
           */
          protected $Category;
      ...
      }
      
    • BrandPromotion entity:
       * @ORM\Entity
       */
      class BrandPromotion extends EntityPromotionAbstract
      {
          /**
           * Brand
           *
           * @var Brand
           * @ORM\ManyToOne(targetEntity="Brand", inversedBy="BrandPromotions")
           * @ORM\JoinColumn(name="instance_id", referencedColumnName="brand_id")
           */
          protected $Brand;
      }
      
    • Brand entity:
          /**
           * Associated BrandPromotions
           *
           * @var \Doctrine\Common\Collections\Collection
           *
           * @ORM\OneToMany(targetEntity="BrandPromotion", mappedBy="Brand", fetch="EXTRA_LAZY")
           */
          protected $BrandPromotions;
      
    • Category entity:
          /**
           * Associated CategoryPromotions
           *
           * @var \Doctrine\Common\Collections\ArrayCollection|\Doctrine\ORM\PersistentCollection
           *
           * @ORM\OneToMany(targetEntity="CategoryPromotion", mappedBy="Category", fetch="EXTRA_LAZY")
           */
          protected $CategoryPromotions;
      
  • When Brand::BrandPromotions collection is not initialized, calling count on it will return a count of BrandPromotion and CategoryPromotion elements, but calling isEmpty will return a count of BrandPromotion entities only.
  • \Doctrine\ORM\Persisters\OneToManyPersister::count does not take into account a discriminator value of 'brand':
            foreach ($targetClass->associationMappings[$mapping['mappedBy']]['joinColumns'] as $joinColumn) {
                $whereClauses[] = $joinColumn['name'] . ' = ?';
    
                $params[] = ($targetClass->containsForeignIdentifier)
                    ? $id[$sourceClass->getFieldForColumn($joinColumn['referencedColumnName'])]
                    : $id[$sourceClass->fieldNames[$joinColumn['referencedColumnName']]];
            }
    
    
  • This results in a query:
    SELECT count(*) FROM entity_promotion t WHERE instance_id = ?
    
  • The query should include a type condition:
    SELECT count(*) FROM entity_promotion t WHERE instance_id = ? AND (t.type in 'brand')
    


 Comments   
Comment by Marco Pivetta [ 29/Apr/14 ]

Why would the query include a type conditional? To me, it seems like the association was built between invalid data types instead.

Comment by Oleg Namaka [ 06/May/14 ]
  • Could you elaborate on what exactly you mean when you are saying, that the association was built between invalid data types?
  • Even if your statement is valid, then why calling on a initialized collection $collection->isEmpty() produces a correct result? Calling $collection->count() produces also a correct result on an initialized collection, wheres calling $collection->count() on an unitialized collection results in an invalid element count.
Comment by Marco Pivetta [ 06/May/14 ]

Ah, I see what you mean now. Sorry, I was confusing this with a joined table inheritance.

Comment by Vigintas Labakojis [ 20/May/14 ]

Exactly same behaviour just wasted me a few hours. Shame I'll have to switch fetch mode back to LAZY until this gets fixed.





[DDC-3136] DQL JOIN association return null Created: 24/May/14  Updated: 24/May/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: DQL, Mapping Drivers, ORM
Affects Version/s: 2.4.2
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Raphael Parazols Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Symfony2



 Description   

Hello,
I observe a strange behavior of a query result done by DQL (only tested DQL in fact). In the last entry of my result, the joined entity are returned to null

My tables are:

Entity1
/**
 * @ORM\Table(name="entity1")
 * @ORM\Entity()
**/
class Entity1
{	
	 /**
     * @ORM\Column(name="entity1_id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
	protected $entity1_Id; 
	
	/**
	* @ORM\Column(name="entity1_text", type="string")
	*/
    protected $entity1_Text;
}
Entity2
/**
 * @ORM\Table(name="entity2")
 * @ORM\Entity()
**/
class Entity2
{	
        /**
	* @ORM\OneToOne(targetEntity="Entity1")
	* @ORM\JoinColumn(name="entity1_id", referencedColumnName="entity1_id")
	* @ORM\Id
	*/
	protected $entity1_id; 
    
	/**
	* @ORM\ManyToOne(targetEntity="Entity3")
	* @ORM\JoinColumn(name="entity3_id", referencedColumnName="entity3_id")
	*/
	protected $entity3; 
}
Entity3
/**
 * @ORM\Table(name="entity3")
 * @ORM\Entity()
**/
class Entity3
{	
	 /**
     * @ORM\Column(name="entity3_id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
	protected $entity3_Id; 
	
	/**
	* @ORM\Column(name="entity3_text", type="string")
	*/
    protected $entity3_Text;
}

So when I do a simple request like this:

DQL Request
SELECT ent2, ent3 FROM f4cIndexBundle:Entity2 ent2 JOIN ent2.entity3 ent3

The result is looks like this

Result NOK
array (size=2)
  0 => 
    object(f4c\IndexBundle\Entity\Entity2)[550]
      protected 'entity1_id' => 
        object(Proxies\__CG__\f4c\IndexBundle\Entity\Entity1)[502]
          ...
      protected 'entity3' => 
        object(f4c\IndexBundle\Entity\Entity3)[497]
          protected 'entity3_Id' => int 2
          protected 'entity3_Text' => string 'TEXT OF ENTITY 3 - SPECIFIC 2' (length=29)
  1 => 
    object(f4c\IndexBundle\Entity\Entity2)[498]
      protected 'entity1_id' => 
        object(Proxies\__CG__\f4c\IndexBundle\Entity\Entity1)[499]
          ...
     protected 'entity3' => null

The entity3 of the last result is never joined and set to null (it's not possible because of the JOIN no ?)
I spent to days on this and I observed that when I add a property in my entity 2 like this

Entity2
/**
 * @ORM\Table(name="entity2")
 * @ORM\Entity()
**/
class Entity2
{	
    ...
    /**
	* @ORM\Column(name="entity2_text", type="string")
	*/
    protected $entity2_Text;
}

The result is ok

Result OK
array (size=2)
  0 => 
    object(f4c\IndexBundle\Entity\Entity2)[550]
      protected 'entity1_id' => 
        object(Proxies\__CG__\f4c\IndexBundle\Entity\Entity1)[498]
         ...
      protected 'entity2_Text' => string 'TEXT2' (length=5)
      protected 'entity3' => 
        object(f4c\IndexBundle\Entity\Entity3)[499]
          protected 'entity3_Id' => int 1
          protected 'entity3_Text' => string 'TEXT OF ENTITY 3 - SPECIFIC 1' (length=29)
  1 => 
    object(f4c\IndexBundle\Entity\Entity2)[494]
      protected 'entity1_id' => 
        object(Proxies\__CG__\f4c\IndexBundle\Entity\Entity1)[495]
          ...
      protected 'entity2_Text' => string 'TEXT1' (length=5)
      protected 'entity3' => 
        object(f4c\IndexBundle\Entity\Entity3)[496]
          protected 'entity3_Id' => int 2
          protected 'entity3_Text' => string 'TEXT OF ENTITY 3 - SPECIFIC 2' (length=29)

Is it normal ? Is this a kwon issue ?

Thanks for your help

Raphael P.






[DDC-3134] Inconsistent defaults for onDelete when defining many-to-many relations Created: 23/May/14  Updated: 23/May/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.4.2
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Adria Lopez Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Symfony 2.5.0-BETA2



 Description   

When defining a relation with the following annotation:

/**
 * @ORM\ManyToMany(targetEntity="A\B\C")
 */

The following SQL is generated for the foreign key constraints:

ALTER TABLE the_table ADD CONSTRAINT FK_A63A409AA76ED395 FOREIGN KEY (something1) REFERENCES thing2 (id) ON DELETE CASCADE;
ALTER TABLE the_table ADD CONSTRAINT FK_A63A409AF8BD700D FOREIGN KEY (something2) REFERENCES thing1 (id) ON DELETE CASCADE;

As it can be seen, the default seems to be to include ON DELETE CASCADE. This feels like a dangerous behaviour (and I couldn't find it documented), but fair enough. The inconsistency comes when adding:

/**
 * @ORM\ManyToMany(targetEntity="A\B\C")
 * @ORM\JoinTable(name="the_table",
 *      joinColumns={@ORM\JoinColumn()},
 *      inverseJoinColumns={@ORM\JoinColumn()}
 * )
 */

In this case, even if we are not providing any values for the join and inverse join columns, we get:

ALTER TABLE the_table ADD CONSTRAINT FK_A63A409AA76ED395 FOREIGN KEY (something1) REFERENCES something2 (id);
ALTER TABLE user_unit ADD CONSTRAINT FK_A63A409AF8BD700D FOREIGN KEY (something2) REFERENCES something1 (id);

As it can be seen, the ON DELETE CASCADE is gone.

I understand this is the case because, when giving empty JoinColumn annotations it's not the engine defaults that are processed, but the inferred values for the annotation. Still, this seems to be either a bug or an undocumented behaviour.

Am I doing anything wrong here? Should this be looked into?






[DDC-3135] Unnecessary SELECT after updating of versioned table Created: 23/May/14  Updated: 23/May/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.4.2
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: ikti Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

PHP 5.5.9-1ubuntu4 (cli) (built: Apr 9 2014 17:11:57)



 Description   

When I update entity with version doctrine generates 2 SQLs:

INSERT INTO TableA (key, value) VALUES (1, 1);
SELECT version FROM TableA WHERE key = 1;

OR

UPDATE TableA SET value= 2, version = version + 1 WHERE key = 1 AND version = 1;
SELECT version FROM TableA WHERE key = 1;

Not only second query is unnecessary (version value is always 1 after persisting and is always prev version + 1 after successful update) but can also read incorrect value if row is updated between update and select statement. In this case entity manager will have outdated data, but most recent version.






[DDC-3148] ResultSetMappingBuilder::generateSelectClause ignores quoted column names Created: 02/Jun/14  Updated: 02/Jun/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Christian Ruhstaller Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

If an entity has a quoted column (Magic Words etc.) and you want to use "generateSelectClause" for the specific entity it won't return the quoted name, just the plain name. If the name is a SQL Magic Word the corresponding SQL will fail.

Exp.: "profile.real" (wrong) instead of "profile.`real`".

File: Doctrine/ORM/Query/ResultSetMappingBuilder.php
Function: generateSelectClause

Line 445:
$sql .= " AS " . $columnName;

Example Entity:
...
class Profile

{ /** * @ORM\Column(name="`real`", type="boolean") */ protected $real=false; }




[DDC-3165] one to zero or one with identity through foreign entity Created: 13/Jun/14  Updated: 13/Jun/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Andries Seutens Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   
<?php

/**
 * @Entity
 */
class User
{
    /** 
     * @Id @Column(type="integer") 
     * @GeneratedValue 
     */
    private $id;
    
    /**
     * @ORM\OneToOne(targetEntity="Address")
     *
     * @var Address
     */
    private $address;
    
    public function getAddress()
    {
        return $this->address;
    }
}

/**
 * @Entity
 */
class Address
{
    /**
     * @Id @OneToOne(targetEntity="User") 
     */
    private $user;
    
    public function foo()
    {}
}


?>

The relation between user and address is one to zero or one. When a record exists on both sides, everything goes fine. When the right side (address) does not have a relevant record, calling $user->getAddress(); always returns an instance. Calling a method on that instance results in an exception:

Fatal error: Uncaught exception 'Doctrine\ORM\EntityNotFoundException' with message 'Entity of type 'Address' was not found.' in doctrine/orm/lib/Doctrine/ORM/Proxy/ProxyFactory.php on line 176

Expected behaviour:
$user->getAddress() should return NULL when the right side is empty.

NOTES:
Mind that the address is identified through a foreign entity (User)






[DDC-3169] ManyToMany association fails when joining on a single column of a composity key Created: 17/Jun/14  Updated: 17/Jun/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.4.2
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Bram Gerritsen Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: association, composite, orm


 Description   

I have two entities with a ManyToMany association between them. The first entity Campsite has a composite key (campsiteID, year). The second entity Region has a single key (regionID).
I want to create an association between Campsite::campsiteID and Region::regionID. See the entities below.

Campsite
/**
 * @ORM\Table(name="Campsite")
 */
class Campsite
{
    /**
     * @ORM\Id
     * @ORM\Column(name="campsiteID", type="integer", precision=0, nullable=false)
     */
    protected $campsiteID;

    /**
     * @ORM\Id
     * @ORM\Column(name="year", type="smallint", precision=0, nullable=false)
     */
    protected $year;

    /**
     * @ORM\ManyToMany(targetEntity="AcsiGeo\Entity\Region", fetch="EAGER", cascade={"detach"})
     * @ORM\JoinTable(name="CampsiteRegion",
     *   joinColumns={
     *     @ORM\JoinColumn(name="campsiteID", referencedColumnName="campsiteID", nullable=false)
     *   },
     *   inverseJoinColumns={
     *     @ORM\JoinColumn(name="regionID", referencedColumnName="regionID", nullable=false)
     *   }
     * )
     * @var \Doctrine\Common\Collections\ArrayCollection $regions
     */
    protected $regions;
}
Region
/**
 * @ORM\Table(name="Region")
 */
class Region
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     * @ORM\Column(name="regionID", type="integer", precision=0, nullable=false)
     */
    protected $regionID;
}

I run the following code to persist a new one.

$campsite = new Campsite();
$campsite->setCampsiteID(111111);
$campsite->setYear(2014);

$region = new Region();
$region->setRegionID(1);
$campsite->addRegion($region);

$em->persist($region);
$em->persist($campsite);
$em->flush();

This results in a record added to the CampsiteRegion table:

campsiteID : 2014
regionID: 1

This is clearly wrong as the value of the year field is added to the campsiteID column.

While debugging the problem I've found an issue with the method to determine the params in ManyToManyPersister on line 147.
The following code pops the last identifier from the array of identifiers.

$params[] = $isRelationToSource ? array_pop($identifier1) : array_pop($identifier2);

In my case:

array(
    'campsiteID' => 111111,
    'year' => 2014
)

Which picks 2014 as the value to use.
When I change the code to get the actual column from the array everything works as expected.

$params[] = $isRelationToSource ? $identifier1[$joinTableColumn] : $identifier2[$joinTableColumn];

I am not 100% sure if this change will have some side effects / edge case I'm not aware of.

For the time being I have fixed the problem bij just reversing the properties in my class, but this is not a real fix of course.






[DDC-3170] SimpleObjectHydrator fails to get discriminator column from mapped SQL result Created: 17/Jun/14  Updated: 17/Jun/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Ulf Reimers Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: hydrator, inheritance, orm


 Description   

When querying a simple entity which uses single table- or class table inheritance using simple object hydration (AbstractQuery::HYDRATE_SIMPLEOBJECT), the mapped discriminator column is not retrieved correctly.

Example:

/**
 * @Entity
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="type", type="string")
 * @DiscriminatorMap({"product" = "Product"})
 */
abstract class AbstractEntity
{
    /** @Id @Column(type="integer") @GeneratedValue */
    public $id;
}

/**
 * @Entity
 */
class Product extends AbstractEntity
{
}

$manager->createQueryBuilder()
                ->select('p')
                ->from('Product, 'p')
                ->getQuery()
                ->getResult(AbstractQuery::HYDRATE_SIMPLEOBJECT);

// -> Exception: [Doctrine\ORM\Internal\Hydration\HydrationException] The discriminator column "type" is missing for "Product" using the DQL alias "p".

The SQL statement used is equal to:

SELECT r0_.id AS id0, r0_.type AS type1 FROM Product r1_ INNER JOIN AbstractEntity r0_ ON r1_.id = r0_.id

As you can see, the type column is given an alias of type1. This is saved in the ResultSetMapping of the request but not taken into account when actually retrieving the discriminator column back from the SQL result.

The problem is inside SimpleObjectHydrator#hydrateRowData().

When the discriminator column name is fetched via

$discrColumnName = $this->_platform->getSQLResultCasing($this->class->discriminatorColumn['name']);

the result is simply type which is wrong because the alias is type2. This can be fixed by adding

if ($metaMappingDiscrColumnName = array_search($discrColumnName, $this->_rsm->metaMappings)) {
    $discrColumnName = $metaMappingDiscrColumnName;
}

right after the column retrieval, because then the alias of the meta field type is correctly taken into account.

I'll create a PR with a unit test for this fix right after this ticket's creation.

I hope I'm doing everything right, this is my first contribution.



 Comments   
Comment by Ulf Reimers [ 17/Jun/14 ]

PR is https://github.com/doctrine/doctrine2/pull/1060

I though that I first create a ticket, then propose a fix for that with a PR and by adding the Ticket ID in the PR-Title they are linked automatically. But unfortunately it seems I've done something wrong there.

Comment by Doctrine Bot [ 17/Jun/14 ]

A related Github Pull-Request [GH-1060] was closed:
https://github.com/doctrine/doctrine2/pull/1060





[DDC-3176] Table-inheritance and OneToOne association as entity ID Created: 18/Jun/14  Updated: 18/Jun/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.4.3
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Elioty Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: association, identity, inheritance, orm
Environment:

Ubuntu 14.04, PHP 5.5.9-1ubuntu4, Symfony 2.5



 Description   

The issue is fully described here:
http://stackoverflow.com/questions/24265731/symfony-doctrine-class-table-inheritance-and-foreign-key-as-primary-key






[DDC-3183] Add JsonSerializable to Collections Created: 22/Jun/14  Updated: 22/Jun/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 3.0
Fix Version/s: 3.0
Security Level: All

Type: New Feature Priority: Major
Reporter: Gabriel Bull Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: collection, orm


 Description   

Implement this:

http://www.php.net/manual/fr/class.jsonserializable.php

Can't really make this claim if Doctrine is not implementing basic interfaces for collections:

> The missing (SPL) Collection/Array/OrderedMap interface.






[DDC-3189] blob doctrine2 not inserting file in mysql Created: 24/Jun/14  Updated: 26/Jun/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.4.3
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Gustavo Monti Rocha Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Linux Ubuntu 12.04, Mysql 5


Attachments: PNG File a.png     Zip Archive testedoctrineupload.zip    

 Description   

I have an entity mapped as:

/**
 * @Entity @Table(name="Upload")
**/
class Upload
{
/** @Id @Column(type="integer") @GeneratedValue **/
protected $id;

/** @Column(type="string") **/
protected $nome;

/** @Column(type="blob") **/
protected $arquivo;

When I use this (WORKS)

 $query = "INSERT INTO Upload1 (name, size, type, content ) "."VALUES ('$fileName', '$fileSize', '$fileType', '$content')";

 mysql_query($query)

When I use this doctrine way (NOT WORKING, if you try to get this file from mysql, return a corrupted or empty file)

$upload = new Upload();

$upload-> setContent($content);
$upload-> setName($fileName);
$upload-> setSize($fileSize);
$upload-> setType($fileType);

$entityManager->persist($upload);
$entityManager->flush();

My html file:

<form method="post" enctype="multipart/form-data">
<table width="350" border="0" cellpadding="1" cellspacing="1" class="box">
<tr> 
<td width="246"> 
<input type="hidden" name="MAX_FILE_SIZE" value="2000000">
<input name="userfile" type="file" id="userfile"> 
</td>
<td width="80"><input name="upload" type="submit" class="box" id="upload" value=" Upload    "></td>
</tr>
</table>
</form>


 Comments   
Comment by Gustavo Monti Rocha [ 24/Jun/14 ]

trying to insert this image

Comment by Gustavo Monti Rocha [ 24/Jun/14 ]

Using:
$entityManager->getConnection()>getConfiguration()>setSQLLogger( new Doctrine\DBAL\Logging\EchoSQLLogger());

Getting:
"START TRANSACTION" INSERT INTO Upload (name, type, size, content) VALUES (?, ?, ?, ?) array(4) { [1] => string(5) "a.png" [2] => string(9) "image/png" [3] => int(264547) [4] => string(270342) "‰PNG  \0\0\0 IHDR\0\0@\0\0„\0\0\0v/jõ\0\0\0sBITÛáOà\0\0\0tEXtSoftware\0gnome-screenshotï¿>\0\0 \0IDATxœìw|TÅöÀÏܲ{·$›^I¥“Лҫ€ QPô©`

{êÏγ÷^ŸýYÀ‚ˆ\"¢ô %½m’í햙ߛ,›mÙe¾>š½÷Ι™3gæÎœ;]3ÿR P( …B¡P( …\0\0³X¾Ÿ†X]ŸÞ]ÿÂôP(\0àÜnñ¯N…B¡P( …B¡P(„B\0\0\\.÷ñ’ÊüünݺÇøîÚl¶m;æçfh4\0@BUR)”3®©šR( …B¡P( …ræa2Y+«ëV\0@4……}

Y–<¸§×KEÙ±ãHaaßâ¢#n·\0Ãf¦§ÄÇÇþÅé¦PÎ0¨‹B¡P( …B¡P(g(„ÙttTJ5\"\0< g§æefe¥ú?3rd¿Š £V.W7ì&\0˜âF+‰ø%9uÆF\0HINø«pôx…ZÅuÉL¥“Ô(‘Ù³¯\0ú÷í}ã¶9°A‡Óãr¥Åé¯n"... } array(4)

{ [1] => string(6) "string" [2] => string(6) "string" [3] => string(7) "integer" [4] => string(4) "blob" }

"COMMIT"

Comment by Steve Müller [ 26/Jun/14 ]

This looks more like a DBAL issue. Can you please provide the error/exception message that you receive from the driver/database server? Also do you use PDOMySQL or mysqli driver?

Comment by Gustavo Monti Rocha [ 26/Jun/14 ]

Steve,

I'm not getting any error/expection. Table looks like insert the blob file but when I try to download it is corrupted. You could see at getting .zip file and executing it.

I'm using PDOMysql.

Comment by Marco Pivetta [ 26/Jun/14 ]

This would probably need a data sample to reproduce the issue.

Comment by Gustavo Monti Rocha [ 26/Jun/14 ]

Marco,

you could use project attached and image in order to reproduce.

Comment by Marco Pivetta [ 26/Jun/14 ]

Gustavo Monti Rocha you should actually provide a functional test for this in case, see https://github.com/doctrine/dbal/tree/master/tests/Doctrine/Tests/DBAL

For example, the zip file you uploaded fails on various includes, and doesn't show the failures to me.





[DDC-3188] Call to a member function getValue() on a non-object in vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php Created: 24/Jun/14  Updated: 27/Jun/14

Status: Reopened
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.4
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Daniel Imhoff Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

PHP 5.4.11
opensuse
apache2



 Description   

This is the line that causes the fatal error: https://github.com/doctrine/doctrine2/blob/v2.4.2/lib/Doctrine/ORM/UnitOfWork.php#L678

This is the association that is breaking it (i.e. reflFields[ 'user' ] is a non-object):

Tweet.php
/**
 * @ManyToOne(targetEntity="User")
 * @JoinColumn(name="user_id", referencedColumnName="id")
 *
 * @var User
 */
protected $user;

This is the pk of the referenced entity.

User.php
/**
 * @Id
 * @Column(name="id", type="bigint", nullable=false)
 *
 * @var int
 */
protected $id;

If an exception was thrown due to missing metadata information, I could catch it, but fatal errors due to this bug have been crashing our scripts and they've had to be manually restarted.

Let me know what other information is needed.

Full stack trace:

PHP 5. Doctrine\ORM\EntityManager->flush() our_code.php
PHP 6. Doctrine\ORM\UnitOfWork->commit() vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:389
PHP 7. Doctrine\ORM\UnitOfWork->computeChangeSets() vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:297
PHP 8. Doctrine\ORM\UnitOfWork->computeScheduleInsertsChangeSets() vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:703
PHP 9. Doctrine\ORM\UnitOfWork->computeChangeSet() vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:404
PHP Fatal error: Call to a member function getValue() on a non-object in vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php on line 678



 Comments   
Comment by Marco Pivetta [ 24/Jun/14 ]

Did you actually validate your mappings?

Comment by Daniel Imhoff [ 24/Jun/14 ]

I did not validate the mapping. I did not know about the orm:validate-schema until just now. I will fix these errors and resubmit if there is still an issue.

Sorry about that, thanks.

Comment by Daniel Imhoff [ 24/Jun/14 ]

The tweet and user relationship is not in the list of invalid mappings.

Comment by Marco Pivetta [ 26/Jun/14 ]

Are User and Tweet in the same namespace?

Comment by Daniel Imhoff [ 27/Jun/14 ]

Yes, and I've since then used the FQNS. I would get a class not found error when validating schema.
This is something that I know can't really be debugged by you guys, I was just hoping for a little direction. We are using memcache to store our metadata, and we are clearing and regenerating the metadata during every deploy (it is not autogenerated). I'm now using a commit hash as the namespace of the metadata, so we'll see if this fixes the issue.

Comment by Marco Pivetta [ 27/Jun/14 ]

It looks like a typo (CasESensiTIViTy issue) to me.





[DDC-1698] Inconsistent proxy file name & namespace result in __PHP_Incomplete_Class when unserializing entities Created: 13/Mar/12  Updated: 25/Sep/13

Status: Reopened
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.2, 2.2.1, 2.3, 2.4
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Benjamin Morel Assignee: Marco Pivetta
Resolution: Unresolved Votes: 2
Labels: proxy


 Description   

Starting with Doctrine 2.2, the Proxy classes have inconsistent naming with their file name, which raises problems with class autoloading.
For example, a class named Application\Model\User creates the following proxy class:

Application\Proxy\__CG__\Application\Model\User

This class is located in the following file:

Application/Proxy/__CG__ApplicationModelUser.php

But whe we serialize such an entity, then unserialize it in another session, the framework autoloader expects the class to be located in:

Application/Proxy/__CG__/Application/Model/User.php

But it is not.
As a result, a __PHP_Incomplete_Class is created instead of the expected proxy class.

I'm not sure whether this is an intended behavior, but I would assume this is a bug.



 Comments   
Comment by Benjamin Morel [ 13/Mar/12 ]

It looks like there is an even broader problem with the new _CG_ prefix; the PSR-0 standard for autoloading states that the underscores should be handled this way:

\namespace\package\Class_Name => {...}/namespace/package/Class/Name.php

Which means that in the above example, it could even expect the file to be located in:

Application/Proxy///CG///Application/Model/User.php

... which is far away from the actual location.
Upgrade to 2.2 broke this code, for us.

Comment by Benjamin Eberlei [ 14/Mar/12 ]

Proxy classes do not follow PSR-0. For the case unserializing objects we should provide an extra autoloader i guess.

See here how symfony does it https://github.com/doctrine/DoctrineBundle/blob/master/DoctrineBundle.php#L57

Comment by Benjamin Eberlei [ 14/Mar/12 ]

See https://github.com/doctrine/doctrine2/commit/9b4d60897dfc7e9b165712428539e694ec596c80 and https://github.com/doctrine/orm-documentation/commit/01381fae1ff3d4944086c7cfe46721925bf6ca15

Comment by Benjamin Morel [ 14/Mar/12 ]

Thanks for the quick fix, Benjamin.
However, I have to admit that I'm not fully happy with the fix, as we (and probably many others) are not using the Doctrine autoloader.
I supposed that the purpose of PSR-0 was precisely not to be tied to a particular autoloader implementation, and this benefit is lost with this version of Doctrine.

You mentioned in the doc that the proxies are not PSR-0 compliant "for implementation reasons"; as this was working fine before 2.2, could you please explain what requirement prevents Doctrine from keeping the previous naming convention?

Comment by Benjamin Eberlei [ 29/Mar/12 ]

In 2.1 the proxies are not PSR-0 compatible themselves, however their class naming is simpler.

In 2.2 we changed proxy names so that you can derive the original name of the proxy by searching for the _CG_ flag. This flag obviously contains the __ chars that some PSR autoloaders detect as directory seperators. I agree this is an unfortunate decision, but it was done this way.

I do think however that we can automatically register the proxy atuoloader (if not yet done) in EntityManager#create(). This would hide this fact from developers automatically.

Comment by Benjamin Morel [ 29/Oct/12 ]

@Benjamin Eberlei
In 2.3 we still have to manually call Autoloader::register() before unserializing entities that may contain proxies.
So EntityManager::create() still doesn't register it. Is there a plan to add this feature?

Comment by Benjamin Eberlei [ 06/Jan/13 ]

Benjamin Morel Not at the moment, seems too dangerous for me since it might produce race conditions. This should really be done in the bootstrap of the system.

We need to document this though.

Comment by Benjamin Morel [ 06/Jan/13 ]

Ok, thanks for your answer!

Comment by Matthieu Napoli [ 09/Sep/13 ]

Sorry to be a pain, but can the description of the task be updated:

  • Affects Version/s: should show all versions (or none) but not just 2.2, 2.2.1
  • Fix Version/s: should be blank

This is to make it clear that this bug is not resolved (since we are way past v2.2.2).

Thanks

Comment by Chris Hawkins [ 25/Sep/13 ]

Some additional documentation about this would be useful. I just spent some considerable time diagnosing an error related to restoring an entity from a cache. I wasn't able to find a mention of the need to call Autoloader::register until I found this page. It was resolved fairly quickly after I found this. For reference, I added this to my bootstrap:

ini_set('unserialize_callback_func', 'proxymissing');
function proxymissing( $name ) {
	if ( preg_match( '/^DoctrineProxies/', $name ) ) {
		\Doctrine\ORM\Proxy\Autoloader::register( PROXYPATH, 'DoctrineProxies' );
	}
}




[DDC-1970] DiscriminatorMap recursion when using self-reference Created: 06/Aug/12  Updated: 01/Jul/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3
Fix Version/s: None
Security Level: All

Type: New Feature Priority: Major
Reporter: Krzysztof Kolasiak Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 2
Labels: None


 Description   

I've ran into a problem with self-referencing entity. When fetching an entity, recursion occurs, fetching every related entity defined by ManyToOne relation
(in this example $sponsor), ignoring LAZY or EXTRA_LAZY fetch mode - it executes numerous queries.

/**
 * @ORM\Entity(repositoryClass="Acme\Bundle\UserBundle\Entity\Repository\UserRepository")
 * @ORM\Table(name="f_user")
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="type", type="string")
 * @ORM\DiscriminatorMap({"user_person" = "UserPerson", "user_company" = "UserCompany"})
 */
abstract class UserBase extends FOSUser

/* .... */

    /**
     * @var UserBase
     *
     * @ORM\OneToMany(targetEntity="UserBase", mappedBy="sponsor")
     */
    protected $referrals;

    /**
     * @ORM\ManyToOne(targetEntity="UserBase", inversedBy="referrals")
     * @ORM\JoinColumn(name="sponsor_id", referencedColumnName="id")
     */
    protected $sponsor;



 Comments   
Comment by Alexander [ 14/Aug/12 ]

I have changed this into a feature request because you have hit the limitations of using inheritance and self referencing entities.

Doctrine2 cannot currently lazy load UserBase#$sponsor because we don't know which proxy we have to insert. It can either be UserPerson or UserCompany. In order to know this Doctrine2 has to query the actual object to determine its type. The current strategy is then to load the actual entity because we have all data anyway.

In order to implement this feature we need to insert a proxy instead of the actual entity. If we do that there should be no recursion happening.

Comment by Marco Pivetta [ 21/Feb/13 ]

Reduced priority

Comment by Prathap [ 10/May/13 ]

It'd be great if this is a configurable option.

Comment by Kevin Bond [ 01/Jul/14 ]

I have also run into this.





[DDC-2332] [UnitOfWork::doPersist()] The spl_objact_hash() generate not unique hash! Created: 05/Mar/13  Updated: 08/Jul/14

Status: Awaiting Feedback
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Krisztián Ferenczi Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Symfony 2.1.8, php 5.4.7 and php 5.4.12, Windows 7


Attachments: Text File hashlogs.txt    

 Description   

I created fixtures and some data was inserted many times without calling the Task entity PrePersist event listener.

I printed the used and generated hash and I saw a Proxies_CG_\Asitly\ProjectManagementBundle\Entity\User hash equal a Task entity hash!



 Comments   
Comment by Marco Pivetta [ 05/Mar/13 ]

Please provide either a code example or a test case. As it stands, this issue is incomplete

Comment by Benjamin Eberlei [ 05/Mar/13 ]

Are you calling EntityManager#clear() inbetween? Because PHP reuses the hashes. The ORM accounts for this.

Comment by Benjamin Eberlei [ 05/Mar/13 ]

This is not a reproduce case, i don't want to execute your whole project.

I want to know, what is the actual bug that you see? Can you just print a list of all the hashes? Because the hashes dont differ at the end, bu tjust somewhere in the middle.

Comment by Krisztián Ferenczi [ 05/Mar/13 ]

I attached a hashlogs.txt file. The last Task class hash is 0000000050ab4aba0000000058e1cb12 ( line 3 129 )

This is not unique, view the line 2 760 . The Task is not being saved and the program don't call the prePersist listener. The "UnitOfWork" believe the entity has been saved because the isset($this->entityStates[$oid]) is true. But it is an other entity.

Comment by Krisztián Ferenczi [ 06/Mar/13 ]

The EntityManager::clear() fix the problem, but this is not "good" and "beautiful" solution. Shows no sign of that conflicts were and this is causing the problem. I was looking for the problem 7 hours.

Comment by Marco Pivetta [ 26/Jun/14 ]

One possible issue here is that a listener registers an entity as managed while a proxy is being loaded.

The given data is still insufficient to actually verify the problem.





[DDC-2929] Pessimistic lock on Query does not update the entity with the DB values if it's already cached Created: 22/Jan/14  Updated: 22/Jan/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Renaud Drousies Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: None
Environment:

PHP 5.4.13-1~dotdeb.1


Issue Links:
Reference
is referenced by DDC-1846 Pessimistic lock does not retreive la... Resolved

 Description   

When asking for a pessimistic lock through a Query object, the entities already in the cache are not refreshed with the latest values from the database (unless you set the Query::HINT_REFRESH hint)

Example:

        $em->beginTransaction();
        try {
            $bar = $em->createQuery('SELECT b FROM Foo:Bar b WHERE b.id = :id')
                        ->setParameter('id', 150)
                        ->getSingleResult();
            var_dump($bar->getAmount()); // Yields some positive value
            $bar->setAmount(0);
            $bar = $em->createQuery('SELECT b FROM Foo:Bar b WHERE b.id = :id')
                        ->setParameter('id', 150)
                        ->setLockMode(\Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE)
                        // ->setHint(\Doctrine\ORM\Query::HINT_REFRESH, true)
                        ->getSingleResult();
            var_dump($bar->getAmount()); // Yields 0

            $em->flush();
            $em->commit();
        } catch (\Exception $e) {
            $em->rollback();
        }

This is similar to DDC-1846

(Tested on 2.4.0 and 2.4.1)






[DDC-2930] Pessimistic locking using $em->find('Entity', $id, LockMode::PESSIMISTIC_WRITE) and $em->lock($entiy, LockMode::PESSIMISTIC_WRITE) differs in (not)refreshing entity state from DB Created: 23/Jan/14  Updated: 23/Jan/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.4.1
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Jiri Kavalik Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: None
Environment:

ubuntu 12.04, mysql, zf2



 Description   

When using pessimistic locking on MySQL(InnoDB tables) there is difference which surprised me:

$em->find('Entity', $id, LockMode::PESSIMISTIC_WRITE);

will reload entity state from DB even when entity was already managed in cache (implemented in DDC-2929)
So I supposed that

$em->lock($entiy, LockMode::PESSIMISTIC_WRITE);

will work alike even when in this case entity is sure already loaded and managed
But it is not the case, actual query log showed only

SELECT 1 FROM table WHERE id FOR UPDATE

If this difference is intended it would be nice to mention it in http://docs.doctrine-project.org/en/latest/reference/transactions-and-concurrency.html

As a workaround I use

$em->refresh($entiy);





[DDC-2767] ID property of MayToOne association has wrong type Created: 30/Oct/13  Updated: 14/Jul/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: flack Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

I'm seeing the following behaviour in some Doctrine code I'm writing:

$entity = array_pop($qb->getQuery()->getResult());
echo gettype($entity->getId()) . ' ' . $entity->getId();
// prints: integer 123

$association = $entity->getAssociation(); // unidirectional ManyToOne link to some other entity
echo gettype($association->getId()) . ' ' . $association->getId();
// prints: string 345

When I load the associated entity directly (via find() f.x.), it's ID has the integer type as expected, and the database structure looks correct, too.

I'm not entirely sure if this is a problem in my code or some issue in QueryBuilder or some other Doctrine component, but if someone could point me into the right direction, that would really be helpful.

I guess normally the type of the ID is not so important because you're not supposed to access it directly anyways, but I need to provide backward compatibility for a lot of code written against a different ORM API that provided exactly this behaviour.



 Comments   
Comment by flack [ 07/Nov/13 ]

After some research, the problem sounds kind of similar to

http://www.doctrine-project.org/jira/browse/DDC-2494

only that in my case, it's not a custom type, but a builtin one that is not working. But AFAICT, in both cases it's getting the ID from a proxy that is problematic

Comment by Doctrine Bot [ 14/Jul/14 ]

A related Github Pull-Request [GH-1073] was closed:
https://github.com/doctrine/doctrine2/pull/1073





[DDC-3211] Annotation @ORM\Table(name="schema.table") don't generate sql using OCI8 Created: 09/Jul/14  Updated: 12/Jul/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers, ORM
Affects Version/s: 2.4.1, 2.4.2
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Jorge Potosme Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: cli, mapping, oci8, oracle, orm, symfony
Environment:

OS: Fedora 20
Web Server: Apache
DBMS: Oracle 12c
Framework: Symfony2
PHP version: 5.5.14
DBMS Driver: OCI8



 Description   

Using Symfony and "doctrine/orm": "2.4.@dev", "doctrine/doctrine-bundle": "1.3.@dev", with OCI8(Oracle Call Interface)
I have an entity
/**
* @ORM\Entity
* @ORM\Table(name="rrhh.usuario")
*/
class Usuario implements UserInterface

{ ... }

When i use de CLI (php app/console doctrine:schema:create --dump-sql) this don't show nothing, the output is empty.

If i change (name="rrhh.usuario") to (name="usuario", schema="rrhh") the CLI show the sql query but without the schema.



 Comments   
Comment by Marco Pivetta [ 09/Jul/14 ]

Duplicates this issue





[DDC-2141] Query should not be final Created: 13/Nov/12  Updated: 13/Nov/12

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Tarjei Huse Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: None
Environment:

All



 Description   

The Query class should not be marked final as this makes it impossible to Mock it.






[DDC-3229] Error when running the tests Created: 24/Jul/14  Updated: 24/Jul/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Jeroen De Dauw Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Fresh clone at 089cca636e0e44a70dd9167b7d813762ea80daca.

php -v
PHP 5.5.9-1ubuntu4.3 (cli) (built: Jul 7 2014 16:36:58)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
with Zend OPcache v7.0.3, Copyright (c) 1999-2014, by Zend Technologies
with Xdebug v2.2.3, Copyright (c) 2002-2013, by Derick Rethans

j@wd42:~/workspace/doctrine2$ phpunit
PHPUnit 4.3-ge243de0 by Sebastian Bergmann.

Configuration read from /home/j/workspace/doctrine2/phpunit.xml.dist

............................................................. 61 / 2500 ( 2%)
........S.................................................... 122 / 2500 ( 4%)
............................................................. 183 / 2500 ( 7%)
............................................................. 244 / 2500 ( 9%)
............................................................. 305 / 2500 ( 12%)
............................................................. 366 / 2500 ( 14%)
.........................S...SSSS.S.......................... 427 / 2500 ( 17%)
............................................................. 488 / 2500 ( 19%)
....................................................SS....... 549 / 2500 ( 21%)
............................................................. 610 / 2500 ( 24%)
............................................................. 671 / 2500 ( 26%)
............................................................. 732 / 2500 ( 29%)
............................................................. 793 / 2500 ( 31%)
........................................................S.SSS 854 / 2500 ( 34%)
SSSSSSSSS.................................................... 915 / 2500 ( 36%)
..........................................SS................. 976 / 2500 ( 39%)
.............S...S...........S..............................S 1037 / 2500 ( 41%)
........PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 65552 bytes) in /home/j/workspace/doctrine2/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyGenerator.php on line 280
PHP Stack trace:
PHP 1.

{main}

() /usr/bin/phpunit.phar:0
PHP 2. PHPUnit_TextUI_Command::main() /usr/bin/phpunit.phar:586
PHP 3. PHPUnit_TextUI_Command->run() phar:///usr/bin/phpunit.phar/phpunit/TextUI/Command.php:132
PHP 4. PHPUnit_TextUI_TestRunner->doRun() phar:///usr/bin/phpunit.phar/phpunit/TextUI/Command.php:179
PHP 5. PHPUnit_Framework_TestSuite->run() /home/j/workspace/doctrine2/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:423
PHP 6. PHPUnit_Framework_TestSuite->run() /home/j/workspace/doctrine2/vendor/phpunit/phpunit/src/Framework/TestSuite.php:715
PHP 7. PHPUnit_Framework_TestCase->run() /home/j/workspace/doctrine2/vendor/phpunit/phpunit/src/Framework/TestSuite.php:715
PHP 8. PHPUnit_Framework_TestResult->run() /home/j/workspace/doctrine2/vendor/phpunit/phpunit/src/Framework/TestCase.php:672
PHP 9. PHPUnit_Framework_TestCase->runBare() /home/j/workspace/doctrine2/vendor/phpunit/phpunit/src/Framework/TestResult.php:654
PHP 10. PHPUnit_Framework_TestCase->runTest() /home/j/workspace/doctrine2/vendor/phpunit/phpunit/src/Framework/TestCase.php:734
PHP 11. ReflectionMethod->invokeArgs() /home/j/workspace/doctrine2/vendor/phpunit/phpunit/src/Framework/TestCase.php:859
PHP 12. Doctrine\Tests\ORM\Functional\Ticket\DDC1436Test->testIdentityMap() /home/j/workspace/doctrine2/vendor/phpunit/phpunit/src/Framework/TestCase.php:859
PHP 13. Doctrine\ORM\AbstractQuery->getOneOrNullResult() /home/j/workspace/doctrine2/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1436Test.php:42
PHP 14. Doctrine\ORM\AbstractQuery->execute() /home/j/workspace/doctrine2/lib/Doctrine/ORM/AbstractQuery.php:766
PHP 15. Doctrine\ORM\AbstractQuery->executeIgnoreQueryCache() /home/j/workspace/doctrine2/lib/Doctrine/ORM/AbstractQuery.php:923
PHP 16. Doctrine\ORM\Internal\Hydration\AbstractHydrator->hydrateAll() /home/j/workspace/doctrine2/lib/Doctrine/ORM/AbstractQuery.php:977
PHP 17. Doctrine\ORM\Internal\Hydration\ObjectHydrator->hydrateAllData() /home/j/workspace/doctrine2/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php:147
PHP 18. Doctrine\ORM\Internal\Hydration\ObjectHydrator->hydrateRowData() /home/j/workspace/doctrine2/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php:160
PHP 19. Doctrine\ORM\Internal\Hydration\ObjectHydrator->getEntity() /home/j/workspace/doctrine2/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php:432
PHP 20. Doctrine\ORM\UnitOfWork->createEntity() /home/j/workspace/doctrine2/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php:268
PHP 21. Doctrine\Common\Proxy\AbstractProxyFactory->getProxy() /home/j/workspace/doctrine2/lib/Doctrine/ORM/UnitOfWork.php:2714
PHP 22. Doctrine\Common\Proxy\AbstractProxyFactory->getProxyDefinition() /home/j/workspace/doctrine2/vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php:119
PHP 23. Doctrine\Common\Proxy\ProxyGenerator->generateProxyClass() /home/j/workspace/doctrine2/vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php:218
PHP 24. strtr() /home/j/workspace/doctrine2/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyGenerator.php:280






[DDC-3228] ORM\Tools\Export\Driver\PhpExporter.php does not properly export manyToOne associations Created: 24/Jul/14  Updated: 24/Jul/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers, ORM, Tools
Affects Version/s: Git Master
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Dan V Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: mapping, orm, schematool
Environment:

PHP 5.5.9-1ubuntu4 (cli)



 Description   

PhpExporter.php fails to check the association for manyToOne/oneToOne and exports all associations as oneToOne.

See https://github.com/doctrine/doctrine2/tree/master/lib/Doctrine/ORM/Tools/Export/Driver/PhpExporter.php#L116 where oneToOne is hardcoded if the bitmask matches either manyToOne or oneToOne.

As opposed to YamlExporter.php:

https://github.com/doctrine/doctrine2/tree/master/lib/Doctrine/ORM/Tools/Export/Driver/YamlExporter.php#L165

Which does roughly the same thing, but then properly sets the association type by checking the actual association on lines 186 through one 190:

https://github.com/doctrine/doctrine2/tree/master/lib/Doctrine/ORM/Tools/Export/Driver/YamlExporter.php#L186-L190






[DDC-2922] Flushing new Entities reachable over several paths that do not all "cascade persist" Created: 17/Jan/14  Updated: 18/Aug/14

Status: Awaiting Feedback
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3.3
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Matthias Pigulla Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: None


 Description   

Please consider the following associations:

  A <>--> B <-- C  

A is an "aggregate" type object w/ a OneToMany collection of Bs. This association is set to cascade persist operations.

C has a unidirectional OneToOne association to B as well.

Adding a new B to A's collection and flushing the EntityManager works - B is persisted (persistence by reachability).

However, when also creating a new C and pointing it to the new B, adding C to the EntityManager and then flushing leads to an exception because B is discovered as a new Entity through a relationship not set to cascade persist operations.

Obviously the problem here is that there are two paths through which we can discover new Entities. The UoW currently starts search from newly (explicitly) added Entities first before it walks through collections of already-managed entities.

I am unsure if it is just a documentation issue or a deeper problem?

If the UoW worked the other way round, the same problem would occur if the cascade persist was on the other association.

A solution would probably require the UoW to first collect all offending (new) Entities and the link they were discovered through, but later on remove Entities from this list if they are found through another association with the cascade persist option. The exception must not be thrown unless the whole reachability graph has been traversed.



 Comments   
Comment by Marco Pivetta [ 18/Aug/14 ]

Can this be factored into a failing test case? I'm not sure if we can support it, but the code would make it much easier to track down the issue into something fixable.





[DDC-2835] No Lock Hint on Joins Created: 03/Dec/13  Updated: 18/Aug/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Paul Mansell Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Microsoft SQL Server 2008/2012



 Description   

There seems to be no lock hits added to the joins on a query. For example, take the following query :

SELECT w0_.name AS name0, w1_.name AS name1, c2_.name AS name2, count(w3_.id) AS sclr3 FROM workflow_request w3_ WITH (NOLOCK) INNER JOIN workflow_request_status w1_ ON w3_.status_id = w1_.id INNER JOIN workflow_action w0_ ON w3_.action_id = w0_.id LEFT JOIN workflow_transition w4_ ON w3_.transition_id = w4_.id INNER JOIN core_mno_account c5_ ON w4_.mno_account_id = c5_.id INNER JOIN core_mno c2_ ON c5_.mno_id = c2_.id LEFT JOIN workflow_state w6_ ON w3_.current_state_id = w6_.id WHERE w1_.ident IN (?) GROUP BY w0_.name, w1_.name, c2_.name ORDER BY w0_.name ASC, w1_.name ASC, c2_.name ASC [["waiting"]]

the with(nolock) is only added to the FROM clause .... it should be added after each join too






[DDC-2695] Order by clause left in subquery when using MSSQL and Paginator Created: 20/Sep/13  Updated: 18/Aug/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3.4
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Paul Mansell Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Windows, Microsoft SQL Server



 Description   

When using the Doctrine paginator and Fetch Join Collections = true and when the original query has an "ORDER BY" clause in it - the subquery created is something like "SELECT DISTINCT FROM (.... ORDER BY ....) as dctrn_result" - when using Microsoft SQL server having the "ORDER BY" clause in a subquery throws an error. This is a similar problem to http://doctrine-project.org/jira/browse/DDC-2282 but that was for the Count Walker - this is for the LimitSubqueryOutputWalker. The fix is the same.



 Comments   
Comment by Paul Mansell [ 20/Sep/13 ]

Problem still occurs in 2.4 - but different error message,

Query :

SELECT * FROM (SELECT DISTINCT id0, ROW_NUMBER() OVER (ORDER BY c1_.iccid ASC) AS doctrine_rownum FROM (SELECT w0_.id AS id0, w0_.batch_id AS batch_id1, c1_.id AS id2, c1_.iccid AS iccid3, c2_.id AS id4, c2_.msisdn AS msisdn5, c3_.id AS id6, c3_.name AS name7, c4_.id AS id8, c5_.id AS id9, c5_.name AS name10, w6_.id AS id11, w6_.created AS created12, w7_.id AS id13, w7_.ident AS ident14, w8_.id AS id15, w8_.ident AS ident16, c9_.id AS id17, c10_.id AS id18, c10_.contract_length AS contract_length19, c10_.rental AS rental20, w11_.id AS id21, w11_.ident AS ident22 FROM workflow_request w0_ WITH (NOLOCK) INNER JOIN core_sim c1_ ON w0_.sim = c1_.id LEFT JOIN core_connection c2_ ON c1_.active_connection_id = c2_.id INNER JOIN core_billing_account c3_ ON c1_.billing_account_id = c3_.id INNER JOIN core_mno_account c4_ ON c1_.mno_account_id = c4_.id INNER JOIN core_mno c5_ ON c4_.mno_id = c5_.id INNER JOIN workflow_request_log w6_ ON w0_.id = w6_.request INNER JOIN workflow_action w7_ ON w0_.action = w7_.id INNER JOIN workflow_request_status w8_ ON w0_.status = w8_.id INNER JOIN core_customer_solution c9_ ON w0_.customer_solution = c9_.id INNER JOIN core_customer_tariff c10_ ON c9_.customer_tariff_id = c10_.id INNER JOIN workflow_request_action w11_ ON w6_.request_action = w11_.id WHERE w7_.ident IN (?) AND w8_.ident = ? AND w11_.ident = ?) dctrn_result) AS doctrine_tbl WHERE doctrine_rownum BETWEEN 1 AND 25' with params ["activate", "network", "approved"]

Error :

SQLSTATE[42000]: [Microsoft][SQL Server Native Client 11.0][SQL Server]The multi-part identifier "c1_.iccid" could not be bound.





[DDC-2901] entity-listeners are not propagated to children of mapped superclasses Created: 09/Jan/14  Updated: 19/Aug/14

Status: Awaiting Feedback
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.4.1
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Stuart Carnie Assignee: Fabio B. Silva
Resolution: Unresolved Votes: 0
Labels: mapping


 Description   

If I have event-listeners set on the subclass and mapped superclass, event-listeners will not be propagated, per this code. Conversely, lifecycle events are, per this



 Comments   
Comment by Marco Pivetta [ 18/Aug/14 ]

Stuart Carnie I lost the code references that you linked, since the code changed and the line numbers don't match anymore.

Any chance that you can provide a failing test for this issue, as well as update the links to reference a fixed commit hash or tag?

Comment by Stuart Carnie [ 19/Aug/14 ]

Marco Pivetta, I've updated the URIs in the description to the right tree

Comment by Marco Pivetta [ 19/Aug/14 ]

The code explicitly forbids inheriting listeners when the child class does not have any.

Fabio B. Silva can you provide any insight on why this decision was made?





[DDC-3146] Hydrator memory leak when using iterator Created: 30/May/14  Updated: 14/Aug/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3.2, 2.3.5, 2.4.2
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Emiel Nijpels Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: hydrator, leak, memory
Environment:

PHP 5.4.21, OS X 10.9.3; PHP 5.3.28, OS X 10.9.4



 Description   

When the hydrator iterate() function is invoked, a new event is added to the event manager with a reference to the current hydrator object. This reference is never cleared which causes the hydrator object to never be cleared from memory by the PHP garbage collection.

/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php
$evm = $this->_em->getEventManager();
$evm->addEventListener(array(Events::onClear), $this);

The effects of this bug are best visible when creating multiple iterator objects after each other in a repository:

// Loop through test code 10 times
for ($f = 0; $f < 10; $f++) {
    // Create test query
    $query = $this->createQueryBuilder('p')->getQuery();

    // Create IterableResult object
    $iterableResult = $query->iterate();

    // Loop through the iterator
    foreach ($iterableResult as $row) {}

    // Print out memory usage
    print(memory_get_usage() . PHP_EOL);
}

This results in the following output:

10536552
10549920
10563288
10576664
10590040
10603416
10616792
10630168
10643608
10656984

Notice how the used memory increases by about 13KB after each iteration.
To stop this memory leak the following code can be added to the end of the cleanup() function in the AbstractHydrator class:

$evm = $this->_em->getEventManager();
$evm->removeEventListener(array(Events::onClear), $this);

The output is now:

10537920
10537048
10537048
10537048
10537048
10537048
10537048
10537048
10537048
10537048

The reference to the event manager is now automatically removed in the cleanup function which allows the hydrator object to be cleaned up by the garbage collection function in PHP.



 Comments   
Comment by Jeremiah Johnson [ 12/Aug/14 ]

I'm experiencing the same problem on 2.3.2

Comment by Jeremiah Johnson [ 14/Aug/14 ]

Tested latest of 2.3.x (2.3.5) and problem still exists.

Comment by Marco Pivetta [ 14/Aug/14 ]

Jeremiah Johnson can you provide a PR with the fix and a test?





[DDC-2133] Issue with Query::iterate and query mixed results Created: 09/Nov/12  Updated: 01/May/13

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.2.1
Fix Version/s: 3.0
Security Level: All

Type: Bug Priority: Major
Reporter: Oleg Namaka Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: None

Issue Links:
Duplicate
is duplicated by DDC-1314 DQL permits partial select using SQL Resolved

 Description   

Consider this code:

$dql = "
    SELECT Page, Product.name
    FROM Dlayer\\Entity\\Page Page
    INNER JOIN Page.Product Product
    ";
$q = ($em->createQuery($dql));
foreach ($q->iterate() as $entry) {
  $page = $entry[0][0];
  $name = $entry[0]['name'];
}

This results with undefined index: 'name' for the second entry.

First result keys are (notice just one array element with index 0):

0
array(2) {
  [0] =>
  int(0)
  [1] =>
  string(4) "name"
} 

but all others are different (notice two array elements with index 0 and the other one that is incrementing):

the second one:
0
array(1) {
  [0] =>
  int(0)
}
1
array(1) {
  [0] =>
  string(4) "name"
} 
the third one:
0
array(1) {
  [0] =>
  int(0)
}
2
array(1) {
  [0] =>
  string(4) "name"
} 

What's wrong with this approach? Is it a bug or mixed results should not be used with the iterate method?



 Comments   
Comment by Benjamin Eberlei [ 12/Nov/12 ]

This is a known issue that we don't have found a BC fix for and as I understand Guilherme Blanco requires considerable refactoring.





[DDC-3280] ObjectHydrator does not support iteration over non-distinct result sets Created: 27/Aug/14  Updated: 27/Aug/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.x
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Timothy Michael Bradley Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: orm


 Description   

ObjectHydrator attempts to retrieve previously created objects during iteration (i.e. Query::iterate()). It needs to create an entirely new object because the previous one is not available.

This may also be a performance/scalability issue, and it may be a matter of setting default behavior.

Note that calling Query::useResultCache(false) does not fix this issue.

This part of the code causes a warning because of this issue.

// Update result pointer
$index = $this->identifierMap[$dqlAlias][$id[$dqlAlias]];
$this->resultPointers[$dqlAlias] = $result[$index];
$resultKey = $index

Here is the warning:

Notice: Undefined offset: 0 in [basedir]/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php on line 519





[DDC-3277] Yaml convert-mapping bug Created: 27/Aug/14  Updated: 01/Sep/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers, ORM, Tools
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Vladimir Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: mapping, orm, yaml, yml
Environment:

Windows+XAMPP, PHP5.3, Zend Framework 2



 Description   

I use yaml mapping in my project for better migration management. For example, I use

    orm:convert-mapping yml ./yml --from-database --namespace="User\Entity\\" --filter="User\Entity\User"

To make yml entites for my User module. In my yml I have smth like this:

      password:
            type: string
            nullable: false
            length: 256
            fixed: false
            comment: ''
        email:
            type: string
            nullable: false
            length: 64
            fixed: false
            comment: ''
        status:
            type: smallint
            nullable: false
            unsigned: false
            comment: ''

I can write a comment to column

         status:
                type: smallint
                nullable: true
                unsigned: false
                comment: '%some comment%'
                column: status

And when I perform migration comment disappears. Here https://github.com/doctrine/migrations/issues/184 I was adviced to use such construction:

    status:
        type: smallint
        nullable: true
        column: status
        options:
            unsigned: false
            comment: '%some comment%'

And It works! But convert-mapping generates wrong code. Does anyone know any way to generate a correct one with convert-mapping?



 Comments   
Comment by Marco Pivetta [ 28/Aug/14 ]

Seems like Christophe Coevoet started working on this: https://github.com/doctrine/doctrine2/pull/1123

Comment by Vladimir [ 29/Aug/14 ]

Thank you very much! Will with feature be available with update through composer?

Comment by Doctrine Bot [ 30/Aug/14 ]

A related Github Pull-Request [GH-1123] was assigned:
https://github.com/doctrine/doctrine2/pull/1123

Comment by Doctrine Bot [ 30/Aug/14 ]

A related Github Pull-Request [GH-1123] was closed:
https://github.com/doctrine/doctrine2/pull/1123

Comment by Steve Müller [ 01/Sep/14 ]

Vladimir there is no release date scheduled for 2.5 yet. If you want to use the patch you will have to use "dev-master" version in your composer.json





[DDC-3195] indexBy implementation on containsKey of PersistentCollection in EXTRA LAZY mode uses property name as column name instead of column name Created: 26/May/14  Updated: 26/Jun/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers, ORM
Affects Version/s: 2.4.2
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: jos de witte Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: None
Environment:

Any



 Description   

indexBy implementation on containsKey (and possibly other EXTRA LAZY implemented methods) of PersistentCollection in EXTRA LAZY mode uses property name as column name instead of column name for OneToMany collections

For example property = fieldName, column name field_name.
Set indexBy on OneToMany annotation to fieldName (as it should be ) and it tries to use fieldName in backend instead of field_name






[DDC-3296] JoinColumns seems to only populate one JoinColumn Created: 04/Sep/14  Updated: 04/Sep/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.4.2
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Daniel Platt Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: orm
Environment:

Symfony 2.3.19



 Description   

I have two entities that are linked via two properties (trackingClickId and trackingSiteId).

However it seems to miss the second JoinColumn.

[Mapping] FAIL - The entity-class '...\Entity\SaleData' mapping is invalid:

  • The join columns of the association 'click' have to match to ALL identifier columns of the target entity '..\Entity\SaleData', however 'tracking_site_id' are missing.
TrackingData.php
class TrackingData
{

    /**
     * @ORM\Column(name="tracking_click_id", type="integer")
     * @ORM\Id
     */
    private $trackingClickId;

    /**
     * @ORM\Column(name="tracking_site_id", type="integer")
     * @ORM\Id
     * @Assert\NotBlank
     */
    private $trackingSiteId;

    /**
     * @ORM\OneToMany(targetEntity="SaleData", mappedBy="click")
     * @ORM\JoinColumns=({
     *      @ORM\JoinColumn(name="tracking_click_id", referencedColumnName="tracking_click_id"),
     *      @ORM\JoinColumn(name="tracking_site_id", referencedColumnName="tracking_site_id"), 
     * })
     */
    private $sales;
    
}
SaleData.php
class SaleData
{

    /**
     * @ORM\Column(name="tracking_site_id", type="integer")
     * @ORM\Id
     * @Assert\NotBlank
     */
    private $trackingSiteId;

    /**
     * @ORM\Column(name="tracking_click_id", type="integer")
     * @ORM\Id
     * @Assert\NotBlank
     */
    private $trackingClickId;

    /**
     * @ORM\ManyToOne(targetEntity="TrackingData", inversedBy="sales")
     * @ORM\JoinColumns=({
     *      @ORM\JoinColumn(name="tracking_click_id", referencedColumnName="tracking_click_id"),
     *      @ORM\JoinColumn(name="tracking_site_id", referencedColumnName="tracking_site_id")
     * })
     */
    private $click;
}

I have been poking around in Doctrine\ORM\Tools\SchemaValidator (L:215).

var_dump($identifierColumns, $assoc['joinColumns']);

array(2) {
  [0] =>
  string(17) "tracking_click_id"
  [1] =>
  string(16) "tracking_site_id"
}
array(1) {
  [0] =>
  array(6) {
    'name' =>
    string(17) "tracking_click_id"
    'unique' =>
    bool(false)
    'nullable' =>
    bool(true)
    'onDelete' =>
    NULL
    'columnDefinition' =>
    NULL
    'referencedColumnName' =>
    string(17) "tracking_click_id"
  }
}





[DDC-1756] Allow for master table only models on joined subclass inheritance Created: 03/Apr/12  Updated: 13/Sep/14

Status: Awaiting Feedback
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Markus Wößner Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Think of a joined subclass inheritance setup where abstract base class A has many concrete child classes C1 ... CN. For each child class a table necessarily has to created. Yet if there are many child classes not defining any additional fields you will get many "id only" child tables. This leads to unnecessary join and insert overhead on database operations as well as a bunch of quite senseless tables in your schema that need to be maintained.

While there are already tickets requesting support for mixed inheritance mapping (e.g. DDC-138) I want to propose another - obviously easy to implement - solution that addresses the "id only table" problem. The basic idea is to extend ClassMetadata by a flag "hasOwnTable" which is true by default and applicable for child classes of a joined subclass tree. Setting this flag to <false> would lead to...
1.) no child table creation for corresponding model
2.) no joins to this table while rendering SQL from DQL statements
3.) no INSERT, UPDATE and DELETE statements for this table in methods executeInserts(), update() and delete() on Doctrine\ORM\Persisters\JoinedSubclassPersister.

(3) can easily be implemented since the mentioned methods all loop on ClassMetadata::parentClasses. For those classes which set the flag "hasOwnTable" to false the operation will be skipped. On the other hand (2) doesn't seem to a big deal either. Extending SqlWalker::_generateClassTableInheritanceJoins() by means of a flag test seems to be enough. Of course setting the flag to <false> while defining additional fields on child class level must be rejected.

If you go for this feature I would be pleased to provide an implementation.






[DDC-2406] Merging of new detached entities with PrePersist lifecycle callback breaks Created: 19/Apr/13  Updated: 14/Sep/14

Status: Awaiting Feedback
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3.2
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Oleg Namaka Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: merge,, prePersist


 Description   

Merging of new detached entities with PrePersist lifecycle callback breaks:

Code snippet:

    class A
    {
       /**
        *  @ORM\ManyToOne(targetEntity= ...
        *  @ORM\JoinColumn(name=" ...
        */
        protected $b;
        
        public function getB()
        {
            return $this->b;
        }
        
        public function setB($b)
        {
            $this->b = $b;
        }
        
        /**
         *
         * @ORM\PrePersist
         *
         * @return void
         */
        public function onPrePersist()
        {
           if ($this->getB() === null) {
                throw new \Exception('B instance must be defined);
           }
           ....
        }
    }
    
    class B 
    {
    }
    
    $a = new A();
    $b = $em->find('B', 1);
    $a->setB($b);
    $em->persist($a); // works fine as B instance is set
    $em->detach($a);
    
    $a = $em->merge($a) // breaks in onPrePersist

The reason it happens is that the merge operation is trying to persist a new entity created by uow::newInstance($class) without populating its properties first:

 // If there is no ID, it is actually NEW.
    ....
    if ( ! $id) {
        $managedCopy = $this->newInstance($class);

        $this->persistNew($class, $managedCopy);
    } else {
	....

This should happen first for the $managedCopy:

    // Merge state of $entity into existing (managed) entity
    foreach ($class->reflClass->getProperties() as $prop) {
        ....


 Comments   
Comment by Fabio B. Silva [ 28/Apr/13 ]

Benjamin Eberlei, Is this an expected behavior ?

I mean.. This issue is about dispatch the event before copy the original values into the managed instance.
But overall, should $em->detach() trigger @PrePersist events ?

Comment by Benjamin Eberlei [ 01/May/13 ]

Fabio B. Silva he talks about $em->merge() on a detached entity calling pre persist. This should only happen on a NEW entity, not on a DETACHED one.

Comment by Oleg Namaka [ 01/May/13 ]

I tend to disagree with the statement above about pre persist that should not happen on a detached entity being merged back in. If this event handler contains a business logic that this entity needs to be checked against and the detached entity was modified before the merge operation in a way that invalidates it in the prePersist than I will end up with the invalid entity in the identity map. If the merge operation calls persist it must run the prePersist event handler as well for consistency.

If there is a logic that prevents persisting invalid entities why should it bypassed in the merge operation?

Comment by Cory Close [ 28/Nov/13 ]

I can confirm that this bug has not been fixed while using doctrine 2.4

Exactly as Oleg Namaka has described, my organization is trying to use @PrePersist callbacks to enforce validation on new entities.

However, we use an extensive client side framework that sends json back to our server. Our workflow is then:

deserializeJson into detached entity
merge detached entity to get it managed (this will apply our edits to an existing entity, or create a new one if this one is new)
persist

However, some entities run into the above problem while using this workflow, so our validation is not run. I can provide more code samples if required.

Comment by Oleg Namaka [ 29/Apr/14