[DDC-844] Call to undefined function Doctrine\ORM\Query\ctype_alpha() in Doctrine/ORM/Query/Lexer.php Created: 20/Oct/10  Updated: 20/Oct/10  Resolved: 20/Oct/10

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

Type: Bug Priority: Blocker
Reporter: Justin Otherguy Assignee: Roman S. Borschel
Resolution: Fixed Votes: 1
Labels: None
Environment:

OpenWRT/x86 within vmware fusion
OpenWRT backfire 10.03
lighttpd - 1.4.26-2
php5 - 5.3.1-3
php5-cgi - 5.3.1-3
php5-mod-json - 5.3.1-3
php5-mod-pdo - 5.3.1-3
php5-mod-pdo-pgsql - 5.3.1-3
php5-mod-pgsql - 5.3.1-3
pgsql-server - 8.3.3-2



 Description   

Hi there,

we're trying to get our code to run on OpenWRT; for now inside a vmware environment.
You can find our code here:
http://github.com/volkszaehler/volkszaehler.org

accessing this url
http://192.168.189.179/backend/index.php/data/a301d8d0-903b-11df-94bb-d943d061b6a8.json
we get:

"Fatal error: Call to undefined function Doctrine\ORM\Query\ctype_alpha() in /www/doctrine/doctrine/lib/Doctrine/ORM/Query/Lexer.php on line 158"

our debug output ("&debug=5" appended to URL) looks like this:
{"source":"volkszaehler.org","version":0.2,"component":"backend","exception":{"type":"Exception","message":"Unknown format: json&debug=5","code":0}}

Thanks in advance!

Regards, J.



 Comments   
Comment by Justin Otherguy [ 20/Oct/10 ]

Hi,

seems package php5-mod-ctype was missing.

It's working now...

Thanks anyway!

Keep up the good work - looking forward to the final version

Regards, J.





[DDC-1251] EntityGenerator uses non-existing constant T_AMPERSAND Created: 05/Jul/11  Updated: 09/Jul/11  Resolved: 09/Jul/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Tools
Affects Version/s: 2.1
Fix Version/s: 2.0.7, 2.1.1, 2.2
Security Level: All

Type: Bug Priority: Blocker
Reporter: Jordi Boggiano Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

Irrelevant



 Description   

As per http://www.php.net/manual/en/tokens.php - the T_AMPERSAND token does not exist. I'm not sure what was the intent, but the entity generator fails on the following code:

            $elems = array_map(function($el) {
                return $el;
            }, $elems);

Due to the way notices are handled in Symfony, this basically stops the execution of the generator entirely. Not so great.

  [ErrorException]                                                                                            
  Notice: Use of undefined constant T_AMPERSAND - assumed 'T_AMPERSAND' in ./vendor/doctrine/lib/Doctrine/ORM/Tools/EntityGenerator.php line 454

Commenting out the offending line makes it work fine though, so I think it's just choking while expecting a function that takes args by reference or something.



 Comments   
Comment by Benjamin Eberlei [ 09/Jul/11 ]

Fixed





[DDC-1231] In ObjectHydrator->_getEntity(...) looking for the discriminator should be in uppercase Created: 27/Jun/11  Updated: 28/Jun/11  Resolved: 28/Jun/11

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

Type: Bug Priority: Blocker
Reporter: Alexandre Mathieu Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

On line 204:
$discrColumn = $this->_rsm->metaMappings[$this->_rsm->discriminatorColumns[$dqlAlias]];

$this->_rsm->discriminatorColumns[$dqlAlias] is in lowercase, whereas $this->_rsm->metaMappings[$this->_rsm->discriminatorColumns[$dqlAlias]] is in uppercase.

$discrColumn cannot be assigned.

A simple fix could be:
$discrColumn = $this->_rsm->metaMappings[strtoupper($this->_rsm->discriminatorColumns[$dqlAlias])];



 Comments   
Comment by Benjamin Eberlei [ 27/Jun/11 ]

What version of the code are you using? I fixed this problem yesterday on git master.

Comment by Alexandre Mathieu [ 27/Jun/11 ]

2.1.0RC1 downloaded this morning from the website.

Comment by Benjamin Eberlei [ 27/Jun/11 ]

ah yes, please update to Git Master then or wait for the RC2 release happening this week.

Comment by Benjamin Eberlei [ 28/Jun/11 ]

This was fixed on master





[DDC-1186] Proxy Objects are incompatible with Serialization Created: 01/Jun/11  Updated: 01/Jun/11  Resolved: 01/Jun/11

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

Type: Bug Priority: Blocker
Reporter: Johannes Schmitt Assignee: Benjamin Eberlei
Resolution: Invalid Votes: 0
Labels: None


 Description   

Lazy-loading users is impossible atm if you want to serialize them at some point, and they are using private member variables.

My suggestion is to check whether the proxied class implements the Serializable interface, and in these cases instead of implementing a __sleep method, a serialize/unserialize method should be implemented instead.

Something like:

public function serialize()

{ return serialize(array($this->__isInitialized__, parent::serialize())); }

public function unserialize($str)

{ list($this->__initialized__, $parentStr) = unserialize($str); parent::unserialize($parentStr); }

At the moment, this makes Doctrine Proxy objects incompatible with the Symfony Security component, and if possible it should be fixed for the 2.1 release. If you need help on this, let me know.



 Comments   
Comment by Johannes Schmitt [ 01/Jun/11 ]

Closing this, not sure what I was debugging there, the problem is a Symfony one





[DDC-1176] Error on proxy loading with foreign Key Created: 27/May/11  Updated: 11/Jun/11  Resolved: 11/Jun/11

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

Type: Bug Priority: Blocker
Reporter: Jonathan Clus Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

Doctrine 2.1Beta



 Description   

Look at this thread:http://groups.google.com/group/doctrine-user/browse_thread/thread/2a03a6aea43428d6

This entity class configuration:

class IndividualsStatus
{
    /**
     * @var Individuals
     *
     * @Id
     * @ManyToOne(targetEntity="Individuals", inversedBy="diagnosers", cascade={"persist","refresh","remove"})
     * @JoinColumns({
     *   @JoinColumn(name="individuals_id", referencedColumnName="id")
     * })
     */
    private $individuals;

    /**
     * @var Diagnosers
     *
     * @Id
     * @ManyToOne(targetEntity="Diagnosers", inversedBy="individuals", cascade={"persist","refresh"})
     * @JoinColumns({
     *   @JoinColumn(name="diagnosers_id", referencedColumnName="id")
     * })
     */
    private $diagnosers;

    /**
    * @var smallint $status
    *
    * @Column(name="status_individuals", type="smallint")
    */
    private $statusIndividuals;

    [...]
}

class Individuals
{
    /**
     * @var Users
     *
     * @OneToOne(targetEntity="Users", cascade={"persist","detach","merge","refresh","remove"}, orphanRemoval=true)
     * @JoinColumns({
     *   @JoinColumn(name="users_id", referencedColumnName="id", unique=true)
     * })
     */
    private $users;

    /**
     * @var Advertisements
     *
     * @OneToMany(targetEntity="Advertisements", mappedBy="individuals")
     */
    private $advertisements;

    /**
     * @var IndividualsStatus
     *
     * @OneToMany(targetEntity="IndividualsStatus", mappedBy="individuals", cascade={"refresh", "remove", "persist"})
     * @joinColumns({
     *   @JoinColumn(name="individuals_id", referencedColumnName="id")
     * })
     */
    private $diagnosers;

  [...]
}

class Diagnosers
{
    /**
     * @var Users
     *
     * @OneToOne(targetEntity="Users", cascade={"persist","remove","detach","merge","refresh"})
     * @JoinColumns({
     *   @JoinColumn(name="users_id", referencedColumnName="id", unique=true)
     * })
     */
    private $users;

    /**
     * @var Pros
     *
     * @OneToOne(targetEntity="Pros", cascade={"persist","remove","detach","merge","refresh"})
     * @JoinColumns({
     *   @JoinColumn(name="pros_id", referencedColumnName="id", unique=true)
     * })
     */
    private $pros;

    /**
     * @var Reports
     *
     * @OneToMany(targetEntity="Reports", mappedBy="diagnosers", cascade={"refresh", "remove"})
     */
    private $reports;

    /**
     * @var IndividualsStatus
     *
     * @OneToMany(targetEntity="IndividualsStatus", mappedBy="diagnosers", cascade={"refresh", "remove", "persist"})
     * @joinColumns({
     *   @JoinColumn(name="diagnosers_id", referencedColumnName="id")
     * })
     */
    private $individuals;
}

Note that in individuals, the relation called "Diagnosers" refered to IndividualsStatus entity.
Note that in diagnosers, the relation called "Individuals" refered to IndividualsStatus entity.

When I execute this DQL request:
   $qb->select(array('i', 'iss', 'u')) 
           ->from('IndividualsStatus', 'iss') 
           ->join('iss.individuals', 'i') 
           ->join('i.users', 'u') 
           ->where('iss.diagnosers = ?1') 
           ->andWhere('iss.individuals = ?2') 
           ->setParameters(array(1 => $idDiag, 2 => $id)); 

I retrieve an IndividualsStatus entity:

object(stdClass)[149] 
  public '__CLASS__' => string 'IndividualsStatus' (length=37) 
  public 'individuals' => 
    object(stdClass)[148] 
      public '__CLASS__' => string 'Individuals' (length=31) 
      public 'reference' => string '451' (length=3) 
      public 'maxAdvertisements' => null 
      public 'role' => int 2 
      public 'id' => int 8 
      public 'users' => string 'Users' (length=25) 
      public 'advertisements' => string 'Array(0)' (length=8) 
      public 'diagnosers' => string 'Array(1)' (length=8) 
      public 'ownedReports' => string 'Array(0)' (length=8) 
      public 'reports' => string 'Array(0)' (length=8) 
      public '_em' => null 
  public 'diagnosers' => 
    object(stdClass)[154] 
      public '__CLASS__' => string 'Proxies 
\OpengroupeEntitiesDiagnosersProxy' (length=61) 
      public 'id' => string '19' (length=2) 
  public 'statusIndividuals' => int 1 
  public '_em' => null 

Now i want to access to the "Diagnosers" relation of the Individuals:
\Doctrine\Common\Util\Debug::dump($individualsStatus->getIndividuals()->getDiagnosers());

In my database, this individuals got 2 diagnosers attached, but only 1 is dumped.
For getting the 2, i have to select the Diagnosers relation into my Dql request:

   $qb->select(array('i', 'iss', 'u', 'd')) 
           ->from('IndividualsStatus', 'iss') 
           ->join('iss.individuals', 'i') 
           ->join('i.diagnosers', 'd') 
           ->join('i.users', 'u') 
           ->where('iss.diagnosers = ?1') 
           ->andWhere('iss.individuals = ?2') 
           ->setParameters(array(1 => $idDiag, 2 => $id)); 

Then if i do \Doctrine\Common\Util\Debug::dump($individualsStatus->getIndividuals()->getDiagnosers())
I have my 2 diagnosers display.



 Comments   
Comment by Jonathan Clus [ 27/May/11 ]

I test something more simple with the same entiies:

$diagnosers = $em->getRepository('Diagnosers')->find(19);
$listDiag = $diagnosers->getIndividuals();

In my database, the Diagnoser(19) got 20 individualsStatus(remember the relation called "Individuals" in "Diagnosers" return "IndividualsStatus" entities)
So this function return only 1 individualStatus(minor id in bdd).

I am completly blocked in my developpement. Did my entity annotation for the relation is bad ?

Comment by Benjamin Eberlei [ 05/Jun/11 ]

Formatting

Comment by Benjamin Eberlei [ 05/Jun/11 ]

This issue is related to foreign key identifiers, not using them will solve the problem. Your annotations are good.

However I fixed an issue of this kind some weeks ago. Are you using the Download of 2.1 Beta? Can you try to update to the latest version on Git?

Comment by Benjamin Eberlei [ 05/Jun/11 ]

Yes just seeing i fixed the bug AFTER releasing BEta 1. Please upgrade and verify!

Comment by Benjamin Eberlei [ 11/Jun/11 ]

Resolved





[DDC-1051] Generated SQL Query Missing Table/Join Constraint leading to SQL Syntax Error Created: 28/Feb/11  Updated: 28/Feb/11  Resolved: 28/Feb/11

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

Type: Bug Priority: Blocker
Reporter: Roger Webb Assignee: Benjamin Eberlei
Resolution: Invalid Votes: 0
Labels: None
Environment:

RedHat Enterprise, PHP 5.3.4, Symfony2 (Sandbox PR7)



 Description   

SELECT u, uc, ur
FROM ARN\EntityBundle\Entity\Users u
INNER JOIN u.contact_info uc
INNER JOIN u.user_roles ur
WHERE u.username = :username

Generates the following SQL Query

SELECT u0_.user_id AS user_id0, u0_.username AS username1, u0_.password AS password2, u0_.contact_info_id AS contact_info_id3, u0_.user_active AS user_active4, u0_.user_date AS user_date5, u0_.office_id AS office_id6, u0_.superuser AS superuser7, c1_.contact_info_id AS contact_info_id8, c1_.first_name AS first_name9, c1_.last_name AS last_name10, c1_.address AS address11, c1_.city_id AS city_id12, c1_.zip AS zip13, c1_.email AS email14, u2_.user_role_id AS user_role_id15, u2_.role AS role16, u0_.contact_info_id AS contact_info_id17, c1_.city_id AS city_id18 FROM users u0_ INNER JOIN contact_info c1_ ON u0_.contact_info_id = c1_.contact_info_id INNER JOIN WHERE u0_.user_id = ?')

Notice the "INNER JOIN WHERE", this is the problem.

The mapping is as follows:

Users->user_roles

/**

  • @orm:OneToMany(targetEntity="UserRoles", mappedBy="user")
    */
    protected $user_roles;

UserRoles->user

/**

  • @ManyToOne(targetEntity="Users", inversedBy="user_roles")
  • @JoinColumn(name="user_id", referencedColumnName="user_id")
    */
    protected $user;

Let me know if you need any more information. Happy to help. Thanks.



 Comments   
Comment by Roger Webb [ 28/Feb/11 ]

Problem was due to a missing "orm:" prefix for symfony annotations. Thanks.





[DDC-1453] YamlDriver calls Yaml::parse(), but only Yaml::load() exists Created: 25/Oct/11  Updated: 25/Oct/11  Resolved: 25/Oct/11

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

Type: Bug Priority: Blocker
Reporter: Karsten Dambekalns Assignee: Benjamin Eberlei
Resolution: Invalid Votes: 0
Labels: None


 Description   

As the subject says, this cannot work. Reported to me through http://forge.typo3.org/issues/31212. Looking at https://github.com/fabpot/yaml/blame/master/lib/sfYaml.php it even seems there never was a parse() method.



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

You are using the oldest possible version of YAML component, please use the right one: https://github.com/symfony/yaml

Comment by Karsten Dambekalns [ 25/Oct/11 ]

Heh, why on earth is the one we use then showing a last update in June 2011? I think all this forking on github is confusing... :/

Anyway, thanks for the pointer!

PS: source of the confusion is http://components.symfony-project.org/yaml/installation, which points to https://github.com/fabpot/yaml





[DDC-1410] leftJoin with condition WITH & Object Hydratation problem. Created: 10/Oct/11  Updated: 07/Jun/12  Resolved: 28/Oct/11

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

Type: Bug Priority: Blocker
Reporter: Thomas Tourlourat - Armetiz Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 2
Labels: None
Environment:

Debian 5 dotdeb
PHP 5.3
MySQL 5.0
Apache 2.2


Attachments: Text File ObjectHydrator_DDC-1410_v1.patch    

 Description   

Here an example of a simple QueryBuilder :

$queryBuilder = $entityManager->createQueryBuilder();
$queryBuilder->select ( "player, options" );
$queryBuilder->from ( "Player_Model_Entity_Player", "player");
$queryBuilder->where ("player.idPlayer = 12");
$queryBuilder->leftJoin ("player.options", "options", "WITH", "options.enabled = :enabled");
$queryBuilder->setParameter ("enabled", 1);

OptionA & OptionB & OptionC three entities.
User case :

  • OptionA.enabled = 1 & OptionB.enabled = 1 & OptionC.enabled = 1 : OK - All options are return.
  • OptionA.enabled = 1 & OptionB.enabled = 0 & OptionC.enabled = 0 : OK - only optionA is return.
  • OptionA.enabled = 1 & OptionB.enabled = 0 & OptionC.enabled = 1 : OK - only optionA & optionC is return.
  • OptionA.enabled = 0 & OptionB.enabled = 1 & OptionC.enabled = 1 : KO - no option return.
  • OptionA.enabled = 0 & OptionB.enabled = 0 & OptionC.enabled = 0 : OK - no option return.

I have test on OneToMany configuration and I have not problem. The problem only appear with ManyToMany relationships.

The problem seems to be on hydratation. The data return on SQL command seems to be correct.



 Comments   
Comment by Thomas Tourlourat - Armetiz [ 20/Oct/11 ]

I have made some other search about it.

On the queryBuilder described above, I was using getSingleResult / getResult.
When I'm using getScalarResult I can see data of every options.

Here the scalar result :

array(3) {
  [0]=>
  array(21) {
    ["player_id"]=>
    int(2)
    ["options_id"]=>
    NULL
    ["options_enabled"]=>
    NULL
  }
  [1]=>
  array(21) {
    ["player_id"]=>
    int(2)
    ["options_id"]=>
    int(2)
    ["options_enabled"]=>
    bool(true)
  }
  [2]=>
  array(21) {
    ["player_id"]=>
    int(2)
    ["options_id"]=>
    int(4)
    ["options_enabled"]=>
    bool(true)
  }
}

Do you have any clue ?

Comment by Thomas Tourlourat - Armetiz [ 20/Oct/11 ]

I think I have find the problem.

See patch.
I have test the modification, it seem to be okay.

In the 2.1.2 version, If the first related object wasn't a "nonemptyComponents", the ObjectHydrator initialized the collection by a specific way.

Comment by Thomas Tourlourat - Armetiz [ 20/Oct/11 ]

It's a patch for Doctrine/ORM/Internal/Hydration/ObjectHydrator.php version 2.1.2.

Comment by Thomas Tourlourat - Armetiz [ 20/Oct/11 ]

I have add a correction on Github : https://github.com/armetiz/doctrine2/commit/42d507632fd27a23220c38bb867b611c3caaab8e

Comment by Benjamin Eberlei [ 25/Oct/11 ]

Thanks for digging into that, I will evaluate this issue

Comment by Thomas Tourlourat - Armetiz [ 25/Oct/11 ]

No problem, It was blocking for me.
But I don't understand why this bug doesn't appear to other users. Because of that, I'm wondering if it's a real bug or a miss configuration on my app.

To be sure, the best will be to create a new test, but I'm not really familiar to create ORM test case..

Thomas.

Comment by Benjamin Eberlei [ 25/Oct/11 ]

can you post your mappings?

Comment by Thomas Tourlourat - Armetiz [ 26/Oct/11 ]

PlayerEntity :

<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
                    http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
	<entity name="PlayerEntity">
		<many-to-many field="options" target-entity="OptionEntity" mapped-by="players" />
	</entity>
</doctrine-mapping>
{/code}

<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd" >
<entity name="OptionEntity" table="options">
<many-to-many field="players" target-entity="PlayerEntity" inversed-by="options">
<cascade>
<cascade-merge />
</cascade>
<join-table name="compo_option_player" />
</many-to-many>
</entity>
</doctrine-mapping>

{/code}

I have post all the mapping, but it's Doctrine compliant.
PlayerEntity extends PlayerBaseEntity, and Option is a standalone Entity.
All define an auto generated identifier.
The join table is correctly configured.

Do you need this mapping to create tests ?
To sum-up, this is a simply ManyToMany relation between an inheritance Entity & a simple Entity.

Do you need any else ?

Thomas.

Comment by Benjamin Eberlei [ 28/Oct/11 ]

Fixed.

Comment by Benjamin Eberlei [ 08/Nov/11 ]

This issue is referenced in Github Pull-Request GH-161
https://github.com/doctrine/doctrine2/pull/161

Comment by Benjamin Eberlei [ 07/Jun/12 ]

A related Github Pull-Request [GH-161] was opened
https://github.com/doctrine/dbal/pull/161

Comment by Benjamin Eberlei [ 07/Jun/12 ]

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





[DDC-1360] Reserved words escaping fails when using multiple reserved words Created: 03/Sep/11  Updated: 03/Jan/12  Resolved: 31/Dec/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1.1
Fix Version/s: 2.2-BETA2, 2.2
Security Level: All

Type: Bug Priority: Blocker
Reporter: Elnur Abdurrakhimov Assignee: Guilherme Blanco
Resolution: Fixed Votes: 0
Labels: None
Environment:

Linux, PostgreSQL



 Description   

Everything works fine when I use the @Table annotation like this: @Table(name="`user`"). But when the user table is in the user schema and I try to use the annotion in this way: @Table(name="`user`.`user`") — everything falls apart.

A quick look into the code showed that it checks if the table name starts with `, and if it does, it sets the quoted parameter to true and removes the ` characters on the both sides. So, if I quote the both words like @Table(name="`user`.`user`"), the table name becomes "user`.`user" and it, of course, fails. If I quote it just like @Table(name="`user.user`"), the table name becomes "user.user", which fails too.

If Doctrine allows to escape the reserved words, it should take into account this kind of usage as well.



 Comments   
Comment by Guilherme Blanco [ 05/Sep/11 ]

By now, it's currently impossible to do cross database joins in an easy way.
We have planned it through the schema support in @Table.

I'll be working on this support for 2.2, but until there, my only recommendation is to not use a keyword as a table name.

Cheers,

Comment by Elnur Abdurrakhimov [ 05/Sep/11 ]

It's not cross database; it's just schema.table in PostgreSQL. It works when not using reserved words, but fails with them.

Comment by Benjamin Eberlei [ 28/Oct/11 ]

How much of this ticket does your commit from some weeks ago cover guilherme?

Comment by Benjamin Eberlei [ 16/Nov/11 ]

Fixed for 2.2

Comment by Elnur Abdurrakhimov [ 21/Dec/11 ]

It still doesn't work. Tried on master.

Comment by Benjamin Eberlei [ 21/Dec/11 ]

what kind of error do you get?

Comment by Benjamin Eberlei [ 28/Dec/11 ]

could reproduce the problem with table names and sequence names.

Comment by Benjamin Eberlei [ 28/Dec/11 ]

Fixed.

Comment by Elnur Abdurrakhimov [ 29/Dec/11 ]

I've just got fresh clones of doctrine-doctrine2, doctrine-dbal and doctrine-common — all on their master branches.

My entity has this annotation:

@ORM\Table(name="`user`.`user`")

I'm getting the following exception:

SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "user.user" 
does not exist LINE 1: ... is_private9,
u0_.created_at AS created_at10 FROM "user.user... 

So, it's translating `user`.`user` to "user.user", while it should be "user"."user".

Comment by Elnur Abdurrakhimov [ 29/Dec/11 ]

What changed is that earlier `user`.`user` was translated to "user`.`user", while now it's translated to "user.user", but should be to "user"."user".

I saw the commit related to this ticket (https://github.com/doctrine/doctrine2/commit/959a68694e5827a74ad5b8c8216996ffff6196ba) and I want to note that I'm getting this error not when creating a table, but when querying it. I don't use Doctrine for creating tables anyway — I do it via plain SQL.

Comment by Benjamin Eberlei [ 31/Dec/11 ]

I keep trying until i fixed this, now with a commit into DBAL: https://github.com/doctrine/dbal/commit/4cb8a99b65fb08e01fbc02cf9c0e07255e3f8463

Will be included in Beta 2

Comment by Elnur Abdurrakhimov [ 31/Dec/11 ]

Now `user`.user, `user`.`user` and `user.user` get escaped properly, ending up as "user"."user". Interestingly enough, even only the beginning tick like in `user.user ends up as "user"."user".

user.`user`, though, results in user.`user` — that is, nothing gets escaped. I don't think this is a big deal, because if I can escape both schema and table name parts, then I won't run into problems. I'm pointing this out in case it was intended to affect the escaping too.

Good job, thanks.





[DDC-1341] MultiTableUpdateExecutor does not bind parameters properly Created: 21/Aug/11  Updated: 28/Aug/11  Resolved: 28/Aug/11

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

Type: Bug Priority: Blocker
Reporter: Pavel Kučera Assignee: Guilherme Blanco
Resolution: Fixed Votes: 0
Labels: None


 Description   

Hi, I found really annoing bug in multi table update executor, it doesn't bind parameters properly. I have following structure of entities (afaik not really important, bug should appear with any class inheritance structure)

/**
* @entity
* @inheritanceType("JOINED")
* @discriminatorColumn(name="type", type="string")
* @discriminatorMap({"NodeEntity", forum = "ForumEntity"})
*/
class NodeEntity
{
  // ... some params
}

/**
* @entity
*/
class ForumEntity
{
/**
* @manyToOne(targetEntity="Author")
*/
private $lastPostAuthor;


/**
* @column(type="datetime")
*/
private $tLastPost;
// ... some params
}

And I'm trying to run following query

$qb = $this->entityManager->createQueryBuilder()
			->update('ForumEntity', 'f')
			->set('f.nPosts', 'f.nPosts + 1')
			->set('f.tLastPost', ':tLastPost')->setParameter('tLastPost', $post->getTCreation()) // $post->getTCreation() returns an instance of DateTime
			->set('f.lastPostAuthor', ':author')->setParameter('author', $post->getAuthor()) // $post->getAuthor() returns an instance of AuthorEntity

			->where('f.lft <= :left')->setParameter('left', $forum->getLft())
			->andWhere('f.rgt >= :right')->setParameter('right', $forum->getRgt())
			->andWhere('f.root = :root')->setParameter('root', $forum->getRoot());

		$qb->getQuery()->execute();

Which fails with "recoverable error", because Doctrine tries to convert value of parameter 'right' to datetime. I have learned why it does so, it is because of line 157 in already mentioned MultiTableUpdateExecutor - while parameters for the insert query are sliced of parameters from update clause, their types are not. And that is a bit problematic.

But that is not the only problem, if you look at line 161, the update query receives parameters as they were binded to QueryBuilder, so when I bind there an object, the update query receives the object instead of his identificator. That leads to error like "object ... could not be converted to string". And also, the update query does not receive any information about type of parameters, but I'm not sure if that is also a bug.

I'm not a native english speaker so if I explain things chaotically, just say so please, I'll try better .



 Comments   
Comment by Benjamin Eberlei [ 28/Aug/11 ]

Assigned to Guilherme

Comment by Guilherme Blanco [ 28/Aug/11 ]

Fixed since this commit: https://github.com/doctrine/doctrine2/commit/e7f471ef3e1ffa5e180623115a45f423572549e4

Comment by Benjamin Eberlei [ 28/Aug/11 ]

Merged into 2.1.x





[DDC-1302] orphan-removal does not work in XML Created: 29/Jul/11  Updated: 31/Jul/11  Resolved: 31/Jul/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: 2.1
Fix Version/s: 2.0.7, 2.1.1
Security Level: All

Type: Bug Priority: Blocker
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

The check for $oneToManyElement->

{'orphan-removal'}

returns false, the right check would be $oneToManyElement['orphan-removal']



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

Fixed and merged into 2.0.x and 2.1.x branches.





[DDC-2073] PersistentCollection::matching() always returns empty collection, when passed criteria's expression is created using ExpressionBuilder::isNull() Created: 12/Oct/12  Updated: 12/Nov/12  Resolved: 12/Nov/12

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

Type: Bug Priority: Blocker
Reporter: Pavol Kirschbaum Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 1
Labels: None


 Description   

This happens because expression created by ExpressionBuilder::isNull() is wrongly translated to SQL using '=' operator instead of 'IS NULL'.

If the collection is already loaded, result is as expected.



 Comments   
Comment by Matthieu Napoli [ 06/Nov/12 ]

Pull request: https://github.com/doctrine/doctrine2/pull/508





[DDC-1961] BC Break: Explicit parameter type definitions are discarded when using AbstractQuery::setParameter Created: 31/Jul/12  Updated: 31/Jul/12  Resolved: 31/Jul/12

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

Type: Bug Priority: Blocker
Reporter: Michael Moravec Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

In 2.2.x it was possible to explicitly specify a type of a parameter in query. In code below, I used a Type::DATE to explicitly say that it should be converted to date type rather than datetime. In 2.3-RC1, it is completely ignored.

// $query instanceof AbstractQuery
$query->setParameter('day', $date, Type::DATE)

Pull request: https://github.com/doctrine/doctrine2/pull/416



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

Fixed





[DDC-1668] bug with reading cached annotations in Annotation driver Created: 28/Feb/12  Updated: 03/Mar/12  Resolved: 03/Mar/12

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers
Affects Version/s: 2.2
Fix Version/s: 2.2.1
Security Level: All

Type: Bug Priority: Blocker
Reporter: victor Velkov Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

I had a problem with Class Table Inheritance on first call of a child entity it was working but if call another child in another instance it was not joining with the parent class. After some debugging i found the problem it was not detecting the annotation that is a parent entity to be joined in Doctrine\ORM\Mapping\Driver\AnnotationDriver when the function on line 479 isTransient($className) is called. So after more debugging i found the problem it is in

is_int(key($classAnnotations))

Looks like that after it is cached in and then the cache is read when it returns the array of annotations for the entity class the keys are returned as strings not as integer and if the key is '0' the the value that is_int returns is NULL so the check

 if ($classAnnotations && is_int(key($classAnnotations))) 

fails and it does not foreach the the array of annotations.
Also i found that you are making that check in a couple of places so I maid a quick fix for my self in the Doctrine\Common\Annotations\CachedReader which is if annotations are found that are cached before returning them i call array_values

// Attempt to grab data from cache
        if (($data = $this->cache->fetch($cacheKey)) !== false) {
            if (!$this->debug || $this->isCacheFresh($cacheKey, $class)) {
                return array_values($data);
            }
        }

I am using APC cache.



 Comments   
Comment by Benjamin Eberlei [ 03/Mar/12 ]

Fixed





[DDC-1620] Partial merge of PR261 Created: 25/Jan/12  Updated: 25/Jan/12  Resolved: 25/Jan/12

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Tools
Affects Version/s: 2.1, 2.1.1, 2.1.2, 2.1.3, 2.1.4, 2.1.5, 2.2-BETA1, 2.2-BETA2, 2.2.0-RC1
Fix Version/s: 2.1.6, 2.2
Security Level: All

Type: Bug Priority: Blocker
Reporter: Miha Vrhovnik Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

The PR261 [1] has two commits, but only one (the first one) was merged to 2.1 and 2.2

[1] - https://github.com/doctrine/doctrine2/pull/261



 Comments   
Comment by Benjamin Eberlei [ 25/Jan/12 ]

fixed

Comment by Miha Vrhovnik [ 25/Jan/12 ]

Hm github is still saying that this is not in 2.2 branch....

Comment by Benjamin Eberlei [ 25/Jan/12 ]

Cherrypick

Comment by Benjamin Eberlei [ 25/Jan/12 ]

ah no, now its up. thanks





[DDC-1607] Entity with eager loaded association is not found when association is null Created: 17/Jan/12  Updated: 21/Jan/12  Resolved: 21/Jan/12

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

Type: Bug Priority: Blocker
Reporter: Marcel Koonstra Assignee: Benjamin Eberlei
Resolution: Invalid Votes: 0
Labels: None

Attachments: File DDC1607Test.php    

 Description   

Two entities: A and B

A:
id PRIMARY
b NULLABLE

B:
id PRIMARY

Situation: A.b is null and set to eager loading (with fetch="EAGER"), find(id) is called for object A

Actual Behaviour: The record from A is not found (probably due to an INNER JOIN being used).

Expected behaviour: Entity A is loaded with b set to null (like during lazy loading).



 Comments   
Comment by Guilherme Blanco [ 18/Jan/12 ]

Increasing priority

Comment by Guilherme Blanco [ 18/Jan/12 ]

It seems to be associated with this commit:

https://github.com/doctrine/doctrine2/commit/68663fac4b5619643b8a140d6bbe7031e4fa2ad5#comments

Comment by Guilherme Blanco [ 18/Jan/12 ]

Since it's a crash between versions, I'm increasing priority and also marking as regression.

Comment by Benjamin Eberlei [ 18/Jan/12 ]

A blocker indeed, reschedulding RC1 release until this is fixed.

Comment by Benjamin Eberlei [ 18/Jan/12 ]

Can you show us the mappings, specifically how you map A#b? Are you setting nullable=false on the join columns?

You problem could be related to:

https://github.com/doctrine/doctrine2/pull/180
https://github.com/doctrine/doctrine2/pull/182/files

Comment by Guilherme Blanco [ 19/Jan/12 ]

Hi,

I was unable to reproduce your issue with the comments you made so far.
Are you able to modify the attached test file into a failure state that represents your problem?

It may be easier for us to track down your problem after that.

Comment by Marcel Koonstra [ 19/Jan/12 ]

Trying the test case on master, but can't seem to be able to reproduce the bug (same goes for the actual problem case)

Maybe some code has changed allready? I will investigate further if I can reproduce the bug in master.

Comment by Benjamin Eberlei [ 21/Jan/12 ]

Closing as invalid, please reopen if you can reproduce, but it seems this is fixed.





[DDC-1587] Foreign key as Primary does not work as intended Created: 08/Jan/12  Updated: 17/Jan/12  Resolved: 17/Jan/12

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

Type: Bug Priority: Blocker
Reporter: Presteus Assignee: Guilherme Blanco
Resolution: Invalid Votes: 0
Labels: None

Attachments: File AgentDdc1587.php     File IdentifierDdc1587.php    

 Description   

Hi,

In first time, sorry for my bad english.

The feature Foreign key as Primary does not work as intended.

The CLI tool report an error on validating mapping:
The referenced column name 'pk_agent' does not have a corresponding field with this column name on the class 'BddP\Model\Entity\Sd\Contact'.

If I run the application, many features works: querying, entity population.
But for persist a new Agent without associated entities for OneToOne; the ORM report :
PDOException: SQLSTATE[23502]: Not null violation on "pk" column

And If I comment all OneToOne, the persist work.

Thank you in advance for your response.

Agent.php
/**
 * @Entity(repositoryClass="BddP\Model\Entity\Repository\Sd\Agent")
 * @Table(name="agent")
 */
class Agent extends AEntity
{
    /**
     * Agent ID
     * @var int
     *
     * @Id
     * @GeneratedValue
     * @Column(name="pk", type="integer", nullable=false)
     */
    private $pk;
    /**
     * @var BddP\Model\Entity\Sd\Contact
     *
     * @OneToOne(targetEntity="BddP\Model\Entity\Sd\Contact", cascade={"remove,merge,detach"}, mappedBy="agent")
     * @JoinColumn(name="pk", referencedColumnName="pk_agent")
     */
    private $contact;

    [...]

}

Contact.php
/**
 * @Table(name="contact")
 */
class Contact extends AEntity
{
    /**
     * The agent
     * @var BddP\Model\Entity\Sd\Agent
     *
     * @Id
     * @OneToOne(targetEntity="BddP\Model\Entity\Sd\Agent", inversedBy="contact")
     * @JoinColumn(name="pk_agent", referencedColumnName="pk")
     */
    private $agent;

    [...]

}



 Comments   
Comment by Presteus [ 08/Jan/12 ]

In addition,
1. The generated SQL from CLI tool is correct.
2. I think the problem is located when the associated entity request the Primary Key.

Comment by Presteus [ 08/Jan/12 ]

After some dumping. I found a strange state :

BasicEntityPersister : $this->_getInsertSQL() returns
INSERT INTO agent (pk, name, firstname, birthday, email, address, city, postcode, phone, mobile) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

And the PK parameter in $insertData has null value

array
  'agent' => 
    array
      'pk' => null
      'name' => string 'XXX' (length=7)
      'firstname' => string 'YYY' (length=8)
      'birthday' => 
        object(DateTime)[283]
          public 'date' => string '1970-01-01 00:00:00' (length=19)
          public 'timezone_type' => int 3
          public 'timezone' => string 'Europe/Paris' (length=12)
      'email' => string 'email@domain.tdl' (length=16)
      'address' => null
      'city' => null
      'postcode' => null
      'phone' => null
      'mobile' => null

But the variable $idGen constains the right value...

object(Doctrine\ORM\Id\SequenceGenerator)[335]
  private '_allocationSize' => int 1
  private '_sequenceName' => string 'agent_pk_seq' (length=12)
  private '_nextValue' => int 451
  private '_maxValue' => int 451

What have I misunderstood?

Comment by Presteus [ 08/Jan/12 ]

After some test, other entity do not reproduce this error.

So the only one reason for this bug: The mapping is incorrect.

And I find... This annotation @JoinColumn(name="pk_agent", referencedColumnName="pk") add a foreign key on agent primary key.

But in the documentation the default value are `id` for PK and `table_id`for FK.

Then my question is still open: What have I misunderstood?

Comment by Guilherme Blanco [ 13/Jan/12 ]

Hi,

Can you please try to wrap your issue into a test case?
I could not reproduce here.

Regards,

Comment by Benjamin Eberlei [ 15/Jan/12 ]

First, schema validator had a bug that reported this errors in mapping although it was correct.

Second, I think your mapping is wrong. In this case you cannot have a bidirectional OneToOne.

Comment by Presteus [ 15/Jan/12 ]

Thanks for our response and your time, especially Guilherme for my no response.

I'm right with you Benjamin, it is my responsability to determinate wich field do not need to create a FK...

This is the point of my misunderstood.

Comment by Presteus [ 16/Jan/12 ]

Hi,

I reopen this issue because the problem still alive, not totally the same but it's a side effect due to the removal of the @JoinColumn.

Without the annotation my Agent do not retrieve the Identifier if and only if the Identifier have all fields with null value (except PK of course).
With the annotation my Agent retrieve the Identifier but the valide-schema returns:

[Mapping]  FAIL - The entity-class 'Entity\Agent' mapping is invalid:
* The referenced column name 'pk_agent' does not have a corresponding field with this column name on the class 'Entity\Identifier'.

And the dump for schema-tool returns

ALTER TABLE agent ADD CONSTRAINT FK_268B9C9DB486D3D9 FOREIGN KEY (pk) REFERENCES identifier(pk_agent) NOT DEFERRABLE INITIALLY IMMEDIATE;

For the moment, I do not trace inside the core of framework but i think the problem turn around the @JoinColum and custom name for primary key.

If i do not use the join colum, how the framework retrieve pk name ?
But if I provide the join column, Doctrine create a FK (without considering mapping error).

Comment by Presteus [ 16/Jan/12 ]

Basic Agent and Identifier entities.

Comment by Guilherme Blanco [ 17/Jan/12 ]

Hi,

I added coverage for your issue in master.
It seems the issue have been addressed already. Are you able to upgrade?

Commit reference: https://github.com/doctrine/doctrine2/commit/0f070448367f90dffb81225c680ef9b3490a3f0a

@beberlei He's still able to make a bidirectional association, there's not restriction for that code-wise.

Closing the issue as invalid, since recent versions have already addressed the issue.





[DDC-1509] Issue when merging entity with several associations to inherited classes Created: 23/Nov/11  Updated: 15/Dec/11  Resolved: 23/Nov/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1.3, Git Master
Fix Version/s: 2.1.4
Security Level: All

Type: Bug Priority: Blocker
Reporter: Aigars Gedroics Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None

Attachments: File DDC1509Test.php    

 Description   

When merging entity with several associations to inherited classes update data gathering is broken after first inheritance processing because $entity variable is overwritten with another object.

The problem is in the line

https://github.com/doctrine/doctrine2/commit/08716d9f72996bab8c71a8cc8bda72d3925e8fb1#commitcomment-741698

Test case will be attached shortly,



 Comments   
Comment by Benjamin Eberlei [ 23/Nov/11 ]

Raised to blocker.

I will fix that tonight and release a new ORM 2.1.* branch.

Comment by Benjamin Eberlei [ 23/Nov/11 ]

Fixed

Comment by Wandrille M [ 15/Dec/11 ]

Hey I have something similar with one-to-one, can you tell me which git commit this relates to so I can investigate?

And i think it worked fine on 2.1.3 and not anymore

Comment by Aigars Gedroics [ 15/Dec/11 ]

It's https://github.com/doctrine/doctrine2/commit/80fae20f749f8db95156e333c430780a0717002f I guess.





[DDC-1492] Fatall error: Cannot use object as array in ORM\Internal\Hydration\ObjectHydrator.php on line 314 Created: 13/Nov/11  Updated: 15/Nov/11  Resolved: 15/Nov/11

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

Type: Bug Priority: Blocker
Reporter: Konstantin Assignee: Guilherme Blanco
Resolution: Fixed Votes: 0
Labels: None
Environment:

Symfony2, Doctrine 2.1.1 (also bug present on 2.1.3-dev - latest revison of 2.1.x branch)



 Description   

My entities

event
eveht.event_area_id=event_area.id (1:1)
event_area.event_id=event.id (1:1)
event_area.area.id=area.id (one area has many event_area's)
area.parent_id=area_id (hierarchial)
event.author_id=user.id (one user has many events)

area - STI: District/City/Region/Country/etc.

SELECT
	r, ra, a, ap, au, DATE(r.eventTime) AS event_date
FROM OloloEventsBundle:Event r
	LEFT JOIN r.eventArea ra
		LEFT JOIN ra.area a
			LEFT JOIN a.parent ap
	INNER JOIN r.author au WHERE r.eventTime <= :r_eventtime AND ra.area IN(:ra_area)
GROUP BY r
ORDER BY event_date DESC

This DQL caused an error "Cannot use object of type District as array in ORM\Internal\Hydration\ObjectHydrator.php on line 314". When I'm removing `ap` friom fetching - it works. Mapping are correct - there are many other places where it works correctly.



 Comments   
Comment by Benjamin Eberlei [ 13/Nov/11 ]

On 2.1.1 line 314 is a "}". Can you restate the line and add a stack trace if possible (xdebug or phpunit can help there).

Comment by Konstantin [ 13/Nov/11 ]

Sorry, line was changed cause I've updated to 2.1.3-dev.

( ! ) Fatal error: Cannot use object of type Ololo\Bundle\TerritorialBundle\Entity\District as array in Z:\home\dev\Ololo\code\vendors\Doctrine\Orm\lib\Doctrine\ORM\Internal\Hydration\ObjectHydrator.php on line 308
Call Stack
#	Time	Memory	Function	Location
1	0.0006	333520	{main}( )	..\index_dev.php:0
2	0.0254	1435584	Symfony\Component\HttpKernel\Kernel->handle( )	..\index_dev.php:20
3	0.2454	3634168	Symfony\Bundle\FrameworkBundle\HttpKernel->handle( )	..\Kernel.php:171
4	0.2454	3634576	Symfony\Component\HttpKernel\HttpKernel->handle( )	..\HttpKernel.php:44
5	0.2454	3634576	Symfony\Component\HttpKernel\HttpKernel->handleRaw( )	..\HttpKernel.php:71
6	0.3589	5534264	call_user_func_array ( )	..\HttpKernel.php:117
7	0.3590	5534448	Ololo\Bundle\DistrictsBundle\Controller\DistrictController->EventsPastAction( )	..\HttpKernel.php:0
8	1.1606	13782464	Ololo\Bundle\EventsBundle\Entity\EventRepository->getPastEventsByAreasIds( )	..\DistrictController.php:145
9	1.1607	13783520	Ololo\Bundle\EventsBundle\Entity\EventRepository->getEventsSliceBySpecification( )	..\EventRepository.php:385
10	1.2010	14224216	Doctrine\ORM\AbstractQuery->getResult( )	..\EventRepository.php:477
11	1.2010	14224368	Doctrine\ORM\AbstractQuery->execute( )	..\AbstractQuery.php:392
12	3.3409	14781264	Doctrine\ORM\Internal\Hydration\AbstractHydrator->hydrateAll( )	..\AbstractQuery.php:594
13	3.3412	14785824	Doctrine\ORM\Internal\Hydration\ObjectHydrator->_hydrateAll( )	..\AbstractHydrator.php:99
14	3.3413	14798576	Doctrine\ORM\Internal\Hydration\ObjectHydrator->_hydrateRow( )	..\ObjectHydrator.php:140
                    $parentObject = $this->_resultPointers[$parentAlias][key($first)]; // trouble here, $this->_resultPointers[$parentAlias] is object of District
Comment by Guilherme Blanco [ 14/Nov/11 ]

Hi.

If you change this line:

$parentObject = $this->_resultPointers[$parentAlias][key($first)];

To this:

$parentObject = $first[key($first)];

Does it work for you?

Comment by Konstantin [ 14/Nov/11 ]

yes, with this line of code this query works.

Comment by Guilherme Blanco [ 15/Nov/11 ]

https://github.com/doctrine/doctrine2/commit/77e076f1fdbe24fdb2f5a1fb1842c0b9cb7d95a4

This issue was fixed in master.
I requested Benjamin to merge this with 2.1 branch.

Thanks





[DDC-1871] Create a relation between two Entities in different EntityManager Created: 12/Jun/12  Updated: 16/Jun/12  Resolved: 16/Jun/12

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

Type: Bug Priority: Blocker
Reporter: Tibec Assignee: Benjamin Eberlei
Resolution: Can't Fix Votes: 0
Labels: None
Environment:

Symfony2 with Doctrine2 using MySQL



 Description   

Hello,

I'm working on a Symfony based CMS for a game server. The game server use two databases (the `auth` database and `characters` database) and i've created a new one for the CMS named `site`.

Currently my News entity must have a relation with the Account entity but the News entity come from the Site EntityManager (who manage the `site` database) and the Account entity come from the Auth EntityManager (who manage the `auth` database).

So, when I prompt the command "php app/console doctrine:schema:update --em="site" --force" I got the error "Class Eluna\MemberBundle\Entity\Account is not a valid entity or mapped super class." But if I join an entity who is in the same EntityManager it work perfectly.

My code :

    /**
     * @var object $author
     *
     * @ORM\ManyToOne(targetEntity="Eluna\MemberBundle\Entity\Account")
     * @ORM\JoinColumn(name="author", referencedColumnName="id")
     */
    private $author;


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

Unless the entities are in the same database server (MySQL) but just in different databses you can use the syntax "database.table" in the @Table. Otherwise there is no nice solution, you have to save the foreign key manually in an integer column and maybe use an event listener to fetch a proxy of the related object. But that has to be coded manually.





[DDC-1824] Native Query fail Created: 17/May/12  Updated: 27/May/12  Resolved: 27/May/12

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

Type: Bug Priority: Blocker
Reporter: Moritz Assignee: Benjamin Eberlei
Resolution: Invalid Votes: 0
Labels: None
Environment:

XAMPP on Windows 7
Doctrine in Combination with Symfony



 Description   

I keep getting an error while I'm trying to perfom an native query.
If there is no result then everything is fine and I don't get any errors.

Notice: Undefined index: id in C:\xampp\htdocs\Symfony\vendor\doctrine\lib\Doctrine\ORM\UnitOfWork.php line 1949

 
$sql = "SELECT q.question FROM question q WHERE MATCH (q.question) AGAINST (?)";

$rsm = new \Doctrine\ORM\Query\ResultSetMapping;
$rsm->addEntityResult('WWMGameBundle:Question', 'q');
$rsm->addFieldResult('q', 'question', 'question');

$em = $this->getDoctrine()->getEntityManager();
$query = $em->createNativeQuery($sql, $rsm);
$query->setParameter(1, $request->request->get('q'));

$search = $query->getResult();
 
/**
* WWM\Entity\Question
*
* @ORM\Entity(repositoryClass="WWM\Entity\QuestionsRepository")
* @ORM\Table(name="question")
*/
class Question
{
    /**
     * @var integer $id
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var integer $level
     *
     * @ORM\Column(name="level", type="integer", nullable=false)
     */
    private $level;

    /**
     * @var string $question
     *
     * @ORM\Column(name="question", type="string", length=255, nullable=false)
     */
    private $question;



    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set level
     *
     * @param integer $level
     */
    public function setLevel($level)
    {
        $this->level = $level;
    }

    /**
     * Get level
     *
     * @return integer
     */
    public function getLevel()
    {
        return $this->level;
    }

    /**
     * Set question
     *
     * @param string $question
     */
    public function setQuestion($question)
    {
        $this->question = $question;
    }

    /**
     * Get question
     *
     * @return string
     */
    public function getQuestion()
    {
        return $this->question;
    }
}


 Comments   
Comment by Benjamin Eberlei [ 17/May/12 ]

You have to add the id as field aswell using $rsm->addFieldResult()

Comment by Moritz [ 17/May/12 ]

It doesn't matter if I use the id as well. I keep getting the same error message:

$sql = "SELECT q.question FROM question q WHERE MATCH (q.question) AGAINST (?)";

$rsm = new \Doctrine\ORM\Query\ResultSetMapping;
$rsm->addEntityResult('WWMGameBundle:Question', 'q');
$rsm->addFieldResult('q', 'question', 'question');
$rsm->addFieldResult('q', 'id', 'id');

$em = $this->getDoctrine()->getEntityManager();
$query = $em->createNativeQuery($sql, $rsm);
$query->setParameter(1, $request->request->get('q'));

$search = $query->getResult();
Comment by Moritz [ 20/May/12 ]

It doesn't matter if I use the id as well. I keep getting the same error message.

Comment by Benjamin Eberlei [ 27/May/12 ]

Do you want to fetch the whole Question Entity? Or just the question as string? Since you only do q.question i suppose using a scalar result instead of the entity works.

$sql = "SELECT q.question FROM question q WHERE MATCH (q.question) AGAINST (?)";

$rsm = new \Doctrine\ORM\Query\ResultSetMapping;
$rsm->addScalarResult('question', 'question');

$em = $this->getDoctrine()->getEntityManager();
$query = $em->createNativeQuery($sql, $rsm);
$query->setParameter(1, $request->request->get('q'));

$search = $query->getResult();

However if you want the whole entity, then you have to fetch the ID from sql as well:

$sql = "SELECT q.id, q.question FROM question q WHERE MATCH (q.question) AGAINST (?)";

$rsm = new \Doctrine\ORM\Query\ResultSetMapping;
$rsm->addEntityResult('WWMGameBundle:Question', 'q');
$rsm->addFieldResult('q', 'question', 'question');
$rsm->addFieldResult('q', 'id', 'id');

$em = $this->getDoctrine()->getEntityManager();
$query = $em->createNativeQuery($sql, $rsm);
$query->setParameter(1, $request->request->get('q'));

$search = $query->getResult();
Comment by Moritz [ 27/May/12 ]

Now it works perfectly fine. Thank you





[DDC-1784] Error on generate entities: 'Attribute "allocationSize" of @ORM\SequenceGenerator' Created: 18/Apr/12  Updated: 27/May/12  Resolved: 20/Apr/12

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Tools
Affects Version/s: 2.2.2
Fix Version/s: 2.2.3, 2.3
Security Level: All

Type: Bug Priority: Blocker
Reporter: Augusto Ximenes de Souza Assignee: Fabio B. Silva
Resolution: Fixed Votes: 0
Labels: None


 Description   

When I generated my entities on version 2.2.2 through "orm:convert-mapping", the sequence has a value ' allocationSize="1", initialValue="1" ' with quotes.

So I received an error:

Attribute "allocationSize" of @ORM\SequenceGenerator declared on property entities\Test::$id expects a integer, but got string.

To fix, I removed the quotes. is It a bug?

Part of entity generated:

/**

  • @var integer $id
    *
  • @ORM\Column(name="id", type="integer", precision=0, scale=0, nullable=false, unique=false)
  • @ORM\Id
  • @ORM\GeneratedValue(strategy="SEQUENCE")
  • @ORM\SequenceGenerator(sequenceName="test_id_seq", allocationSize="1", initialValue="1") /* SEE QUOTES ON allocationSize="1", initialValue="1" */
    */
    private $id;


 Comments   
Comment by Augusto Ximenes de Souza [ 18/Apr/12 ]

I think the problem is on the line 1037 to 1042 of Class Doctrine \ ORM \ Tools \ EntityGenerator:

if (isset($metadata->sequenceGeneratorDefinition['allocationSize']))

{ $sequenceGenerator[] = 'allocationSize="' . $metadata->sequenceGeneratorDefinition['allocationSize'] . '"'; }

if (isset($metadata->sequenceGeneratorDefinition['initialValue']))

{ $sequenceGenerator[] = 'initialValue="' . $metadata->sequenceGeneratorDefinition['initialValue'] . '"'; }

Replace to:

if (isset($metadata->sequenceGeneratorDefinition['allocationSize']))

{ $sequenceGenerator[] = 'allocationSize=' . $metadata->sequenceGeneratorDefinition['allocationSize']; }

if (isset($metadata->sequenceGeneratorDefinition['initialValue']))

{ $sequenceGenerator[] = 'initialValue=' . $metadata->sequenceGeneratorDefinition['initialValue']; }
Comment by Fabio B. Silva [ 20/Apr/12 ]

Fixed by : https://github.com/doctrine/doctrine2/commit/d5d47222c1dc5ea97ebd8f4c68834fbe4abeb238

Comment by Benjamin Eberlei [ 27/May/12 ]

Merged into 2.2





[DDC-2199] Yaml driver does not take into account field @Version attribute Created: 14/Dec/12  Updated: 16/Dec/12  Resolved: 16/Dec/12

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers
Affects Version/s: Git Master
Fix Version/s: 2.3.2
Security Level: All

Type: Bug Priority: Blocker
Reporter: Georgy Galakhov Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: mapping, yaml


 Description   

Even if field has version: true attribute, Yaml driver does not set class metadata isVersioned and versionField properties. As a result optimistic lock cannot be used.



 Comments   
Comment by Benjamin Eberlei [ 16/Dec/12 ]

Fixed





[DDC-1063] Yaml mapping driver cant find Symfony/Component/Yaml/Yaml.php Created: 08/Mar/11  Updated: 14/Mar/11  Resolved: 14/Mar/11

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

Type: Bug Priority: Blocker
Reporter: Nikola Petkanski Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

Ubuntu 10.10; PHP 5.3;



 Description   

As of the release of Doctrine ORM 2.0.2 I cannot seem to be able to use the Yaml mapping driver.

PHP Warning: require(/usr/share/php/Doctrine/Symfony/Component/Yaml/Yaml.php): failed to open stream: No such file or directory in /usr/share/php/Doctrine/Common/ClassLoader.php on line 148

I do have the Doctrine 2.0.2 packages installed, here's the output from my console:

Installed packages, channel pear.doctrine-project.org:
======================================================
Package Version State
DoctrineCommon 2.0.1 stable
DoctrineDBAL 2.0.2 stable
DoctrineORM 2.0.2 stable
DoctrineSymfonyConsole 2.0.2 stable
DoctrineSymfonyYaml 2.0.2 stable

It is all up to date, so I am not missing anything.

root@nikola-pc:/usr/share/php# pear upgrade-all
Nothing to upgrade-all

Navigating to the /usr/share/php folder, where the PEAR and all other stuff is located I can't seem to find the Yaml.php file, which should be distributed by some of the newly formed packages.

root@nikola-pc:/usr/share/php# find -iname 'yaml*'
./Doctrine/ORM/Mapping/Driver/YamlDriver.php
./Doctrine/ORM/Tools/Export/Driver/YamlExporter.php
./.registry/.channel.pear.symfony-project.com/yaml.reg
./data/DoctrineSymfonyYaml/Doctrine/Symfony/Component/Yaml
./PHPUnit/Extensions/Database/DataSet/YamlDataSet.php
./PHPUnit/Extensions/Database/DataSet/Persistors/Yaml.php
./PHPUnit/Extensions/Database/DataSet/Specs/Yaml.php
./SymfonyComponents/YAML

root@nikola-pc:/usr/share/php# find -iname 'yaml.php'
./PHPUnit/Extensions/Database/DataSet/Persistors/Yaml.php
./PHPUnit/Extensions/Database/DataSet/Specs/Yaml.php
root@nikola-pc:/usr/share/php#

root@nikola-pc:/usr/share/php/data/DoctrineSymfonyYaml# find
.
./LICENSE
./Doctrine
./Doctrine/Symfony
./Doctrine/Symfony/Component
./Doctrine/Symfony/Component/Yaml
./Doctrine/Symfony/Component/Yaml/LICENSE
./bin
./bin/doctrine.bat
./bin/doctrine
root@nikola-pc:/usr/share/php/data/DoctrineSymfonyYaml#

Please advise me what the possible solution would be in this case?



 Comments   
Comment by Benjamin Eberlei [ 10/Mar/11 ]

What Files are in the ./Doctrine/Symfony/Component/YAML Directory? Only LICENSE? Then maybe my build failed somehow.

Comment by Nikola Petkanski [ 10/Mar/11 ]

Yes, only the LICENSE file is present.

root@nikola-pc:~# ls -lha /usr/share/php/data/DoctrineSymfonyYaml/Doctrine/Symfony/Component/Yaml/
total 12K
drwxr-xr-x 2 root root 4.0K 2011-03-07 14:21 .
drwxr-xr-x 3 root root 4.0K 2011-03-07 14:21 ..
-rw-r--r-- 1 root root 1.1K 2011-03-07 14:21 LICENSE
root@nikola-pc:~# 

P.S It would be nice for the documentation to be updated with recommendations on how to setup the autoloader for versions 2.0.2+.
http://www.doctrine-project.org/docs/orm/2.0/en/reference/configuration.html#additional-symfony-components

Comment by Benjamin Eberlei [ 13/Mar/11 ]

It works for me, i have installed DoctrineSYmfonyYaml on another machine and it contains all the relevant contents.

Have you tried uninstall and install the package again?

pear uninstall doctrine/DoctrineSymfonyYaml
pear install doctrine/Doctrine/SymfonyYaml
Comment by Nikola Petkanski [ 14/Mar/11 ]

I cannot understand the commands you've gave me - utilizing phpunit to uninstall PEAR component? Really?

Anyway.. I've tried to uninstall and re-install, but it does not seem to be fixed.

Please, check the output from my console and inform me if I am doing something wrong.

root@nikola-pc:~# pear list -a | grep Doctrine
DoctrineCommon         2.0.1   stable
DoctrineDBAL           2.0.2   stable
DoctrineORM            2.0.2   stable
DoctrineSymfonyConsole 2.0.2   stable
DoctrineSymfonyYaml    2.0.2   stable
root@nikola-pc:~# pear uninstall Doctrine/DoctrineSymfonyYaml 
doctrine/DoctrineSymfonyYaml (version >= 2.0.0) is required by installed package "doctrine/DoctrineORM"
doctrine/DoctrineSymfonyYaml cannot be uninstalled, other installed packages depend on this package
root@nikola-pc:~# pear uninstall Doctrine/DoctrineORM
uninstall ok: channel://pear.doctrine-project.org/DoctrineORM-2.0.2
root@nikola-pc:~# pear list -a | grep Doctrine
DoctrineCommon         2.0.1   stable
DoctrineDBAL           2.0.2   stable
DoctrineSymfonyConsole 2.0.2   stable
DoctrineSymfonyYaml    2.0.2   stable
root@nikola-pc:~# pear uninstall Doctrine/DoctrineSymfonyYaml 
uninstall ok: channel://pear.doctrine-project.org/DoctrineSymfonyYaml-2.0.2
root@nikola-pc:~# pear list -a | grep Doctrine
DoctrineCommon         2.0.1   stable
DoctrineDBAL           2.0.2   stable
DoctrineSymfonyConsole 2.0.2   stable
root@nikola-pc:~# pear upgrade-all
Nothing to upgrade-all
root@nikola-pc:~# pear update-channels
Updating channel "components.ez.no"
Channel "components.ez.no" is up to date
Updating channel "doc.php.net"
Channel "doc.php.net" is up to date
Updating channel "pear.doctrine-project.org"
Channel "pear.doctrine-project.org" is up to date
Updating channel "pear.pdepend.org"
Channel "pear.pdepend.org" is up to date
Updating channel "pear.phing.info"
Channel "pear.phing.info" is up to date
Updating channel "pear.php.net"
Channel "pear.php.net" is up to date
Updating channel "pear.phpunit.de"
Channel "pear.phpunit.de" is up to date
Updating channel "pear.symfony-project.com"
Channel "pear.symfony-project.com" is up to date
Updating channel "pecl.php.net"
Channel "pecl.php.net" is up to date
root@nikola-pc:~# pear install Doctrine/DoctrineORM
downloading DoctrineORM-2.0.2.tgz ...
Starting to download DoctrineORM-2.0.2.tgz (194,608 bytes)
.........................................done: 194,608 bytes
downloading DoctrineSymfonyYaml-2.0.2.tgz ...
Starting to download DoctrineSymfonyYaml-2.0.2.tgz (19,883 bytes)
...done: 19,883 bytes
install ok: channel://pear.doctrine-project.org/DoctrineSymfonyYaml-2.0.2
install ok: channel://pear.doctrine-project.org/DoctrineORM-2.0.2
root@nikola-pc:~# ls -lha /usr/share/php/data/DoctrineSymfonyYaml/Doctrine/Symfony/Component/Yaml/
total 12K
drwxr-xr-x 2 root root 4.0K 2011-03-14 11:15 .
drwxr-xr-x 3 root root 4.0K 2011-03-14 11:15 ..
-rw-r--r-- 1 root root 1.1K 2011-03-14 11:15 LICENSE
root@nikola-pc:~# 
Comment by Nikola Petkanski [ 14/Mar/11 ]

It seems to be fixed. Perhaps you've fixed the package and during my uninstall-install it was set properly.

root@nikola-pc:/usr/share/php# find -iname 'yaml.php'
./Doctrine/Symfony/Component/Yaml/Yaml.php
./PHPUnit/Extensions/Database/DataSet/Persistors/Yaml.php
./PHPUnit/Extensions/Database/DataSet/Specs/Yaml.php

Thanks for fixing it up

P.S I was having the same issue with the symfony console, but re-installing the ORM and the DBAL packages helped.

Comment by Benjamin Eberlei [ 14/Mar/11 ]

lol, i got confsued. I meant "pear" of course. Fixed my previous comment.

Comment by Benjamin Eberlei [ 14/Mar/11 ]

I had the packages built wrong right after the 2.0.2 release, but only for 2-4 hours. After that they were complete. Good it works for you now, sorry for the difficulties





[DDC-1695] SQLs for PostgreSQL case sensite tables/fields are wrongly generated Created: 09/Mar/12  Updated: 11/Mar/12  Resolved: 11/Mar/12

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: 2.1.6
Fix Version/s: 2.1.7, 2.2.2
Security Level: All

Type: Bug Priority: Blocker
Reporter: Ignacio Larranaga Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

PostgreSQL 9.x, Symfony 2


Attachments: Text File doctrine-2.1.6.patch     Text File SqlWalker.patch    

 Description   

The SQLs for case sensitive schemas in postgreSQL are wronly generated.

Example:
Schema:

CREATE TABLE "News" (
  "IdNews" serial NOT NULL,
  "IdUser" bigint NOT NULL,
  "IdLanguage" integer NOT NULL,
  "IdCondition" integer,
  "IdHealthProvider" integer,
  "IdSpeciality" integer,
  "IdMedicineType" integer,
  "IdTreatment" integer,
  "Title" character varying,
  "SmallText" character varying,
  "LongText" character varying,
  "PublishDate" timestamp with time zone,
  "IdxNews" tsvector,
  "Highlight" boolean NOT NULL DEFAULT false,
  "Order" integer NOT NULL DEFAULT 0,
  "Deleted" boolean NOT NULL DEFAULT false,
  "Active" boolean NOT NULL DEFAULT false,
  "UpdateToHighlighted" boolean DEFAULT false,
  CONSTRAINT "News_pkey" PRIMARY KEY ("IdNews" ));

Object (I added quotes trying to generate the SQLs quoted.:

<?php

namespace GlobalTreatments\ApplicationBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Table(name="""News""")
 * @ORM\Entity
 */
class News
{
    /**
     * @var integer $idNews
     *
     * @ORM\Column(name="""IdNews""", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="SEQUENCE")
     * @ORM\SequenceGenerator(sequenceName="""News_IdNews_seq""", allocationSize="1", initialValue="1")
     */
    private $idNews;

    /**
     * @var bigint $iduser
     *
     * @ORM\Column(name="""IdUser""", type="bigint", nullable=false)
     */
    private $idUser;

    /**
     * @var integer $idLanguage
     *
     * @ORM\Column(name="""IdLanguage""", type="integer", nullable=false)
     */
    private $idLanguage;

    /**
     * @var integer $idCondition
     *
     * @ORM\Column(name="""IdCondition""", type="integer", nullable=true)
     */
    private $idCondition;

    /**
     * @var integer $idHealthProvider
     *
     * @ORM\Column(name="""IdHealthProvider""", type="integer", nullable=true)
     */
    private $idHealthProvider;

    /**
     * @var integer $idSpeciality
     *
     * @ORM\Column(name="""IdSpeciality""", type="integer", nullable=true)
     */
    private $idSpeciality;

    /**
     * @var integer $idMedicineType
     *
     * @ORM\Column(name="""IdMedicineType""", type="integer", nullable=true)
     */
    private $idMedicineType;

    /**
     * @var integer $idTreatment
     *
     * @ORM\Column(name="""IdTreatment""", type="integer", nullable=true)
     */
    private $idTreatment;

    /**
     * @var string $title
     *
     * @ORM\Column(name="""Title""", type="string", nullable=true)
     */
    private $title;

    /**
     * @var string $smallText
     *
     * @ORM\Column(name="""SmallText""", type="string", nullable=true)
     */
    private $smallText;

    /**
     * @var string $longText
     *
     * @ORM\Column(name="""LongText""", type="string", nullable=true)
     */
    private $longText;

    /**
     * @var datetimetz $publishDate
     *
     * @ORM\Column(name="""PublishDate""", type="datetimetz", nullable=true)
     */
    private $publishDate;

    /**
     * @var tsvector $idxNews
     *
     * @ORM\Column(name="""IdxNews""", type="tsvector", nullable=true)
     */
    private $idxNews;

    /**
     * @var boolean $highlight
     *
     * @ORM\Column(name="""Highlight""", type="boolean", nullable=false)
     */
    private $highlight;

    /**
     * @var integer $order
     *
     * @ORM\Column(name="""Order""", type="integer", nullable=false)
     */
    private $order;

    /**
     * @var boolean $deleted
     *
     * @ORM\Column(name="""Deleted""", type="boolean", nullable=false)
     */
    private $deleted;

    /**
     * @var boolean $active
     *
     * @ORM\Column(name="""Active""", type="boolean", nullable=false)
     */
    private $active;

    /**
     * @var boolean $updateToHighlighted
     *
     * @ORM\Column(name="""UpdateToHighlighted""", type="boolean", nullable=true)
     */
    private $updateToHighlighted;

    /**
     * @var condition
     *
     * @ORM\ManyToOne(targetEntity="Condition")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="""IdCondition""", referencedColumnName="""IdCondition""")
     * })
     */
    private $condition;

    /**
     * @var healthProvider
     *
     * @ORM\ManyToOne(targetEntity="HealthProvider")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="""IdHealthProvider""", referencedColumnName="""IdHealthProvider""")
     * })
     */
    private $healthProvider;

    /**
     * @var language
     *
     * @ORM\ManyToOne(targetEntity="Language")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="""IdLanguage""", referencedColumnName="""IdLanguage""")
     * })
     */
    private $language;

    /**
     * @var medicineType
     *
     * @ORM\ManyToOne(targetEntity="MedicineType")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="""IdMedicineType""", referencedColumnName="""IdMedicineType""")
     * })
     */
    private $medicineType;

    /**
     * @var speciality
     *
     * @ORM\ManyToOne(targetEntity="Speciality")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="""IdSpeciality""", referencedColumnName="""IdSpeciality""")
     * })
     */
    private $speciality;

    /**
     * @var treatment
     *
     * @ORM\ManyToOne(targetEntity="Treatment")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="""IdTreatment""", referencedColumnName="""IdTreatment""")
     * })
     */
    private $treatment;

    /**
     * @var user
     *
     * @ORM\ManyToOne(targetEntity="User")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="""IdUser""", referencedColumnName="""IdUser""")
     * })
     */
    private $user;

    ....

}

DQL:

'SELECT n.smallText, n.publishDate ' .
'FROM News n ' .
	'INNER JOIN n.language la ' .
'WHERE la.languageCode = :languageCode ' .
'ORDER BY n.publishDate DESC'

Generated SQL:

SELECT "0_."SmallText" AS "SmallText"0, "0_."PublishDate" AS "PublishDate"1 FROM "News" "0_ INNER JOIN "Language" "1_ ON "0_."IdLanguage" = "1_."IdLanguage" WHERE "1_."LanguageCode" = ? ORDER BY "0_."PublishDate" DESC LIMIT 6

Notice there are unmattched " in the SQL.



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

If there is another approach to specify the table/column names are case sensitive in PGSQL please let me know.

Comment by Ignacio Larranaga [ 09/Mar/12 ]

Just to comment. I also tried the normal quoting.

Example: @ORM\Column(name="`IdNews`", type="integer", nullable=false)

And does not work too because of the same reason.

Comment by Ignacio Larranaga [ 09/Mar/12 ]

Hi, I generate this patch and seems to be working for me (at least what I'm testing right now).

I used ´ to quote tables and single attributes (not relationships) and the SQLs are correctly generated.

Comment by Ignacio Larranaga [ 09/Mar/12 ]

Adding a new patch for another files I need to change.

Comment by Benjamin Eberlei [ 11/Mar/12 ]

Formatted code

Comment by Benjamin Eberlei [ 11/Mar/12 ]

Fixed and merged into 2.1.x and 2.2 branches





[DDC-231] YAML isn't persisting correcty Created: 30/Dec/09  Updated: 30/Dec/09  Resolved: 30/Dec/09

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

Type: Bug Priority: Blocker
Reporter: Henrique Girardi dos Santos Assignee: Roman S. Borschel
Resolution: Invalid Votes: 0
Labels: None
Environment:

Ubuntu 9.04 -
PHP 5.3.1-0.dotdeb.0 with Suhosin-Patch (cli) (built: Nov 28 2009 13:18:25)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2009 Zend Technologies
with Xdebug v2.0.5, Copyright (c) 2002-2008, by Derick Rethans
with Suhosin v0.9.29, Copyright (c) 2007, by SektionEins GmbH
-
PostgreSQL 8.3



 Description   

I'm have some problems when I try to persist..
I've created these classes:

class Customer
{
    public $id;
    public $users;

    public function __construct()
    {
        $this->users = new \Doctrine\Common\Collections\ArrayCollection();
    }
}

class User
{
    public $id;
    public $customer;
}

And then I make the mappers with YAML

Ciutat\DomainModel\Customer:
  type: entity
  table: customer
  fields:
    id:
      type: integer
      id: true
      generator:
        strategy: auto
      sequenceGenerator:
        sequenceName: customer_id_seq
        allocationSize: 1
        initialValue: 1
  oneToMany:
    users:
      targetEntity: User
      mappedBy: customer
      cascade: cascadePersist

Ciutat\DomainModel\User:
  type: entity
  table: user1
  fields:
    id:
      type: integer
      id: true
      generator:
        strategy: auto
      sequenceGenerator:
        sequenceName: user1_id_seq
        allocationSize: 1
        initialValue: 1
  manyToOne:
    customer:
      targetEntity: Customer
      joinColumn:
        name: customerId
        referencedColumnName: id

And when I try to persist some data

$costumer = new DomainModel\Customer();
$user = new DomainModel\User();
$user2 = new DomainModel\User();
$user3 = new DomainModel\User();

$costumer->users->add($user);
$costumer->users->add($user2);
$costumer->users->add($user3);
    
$em->persist($costumer);
$em->flush();

the result in my database is not what I think it must be expected

select * from customer;
 id 
----
  1

elect * from user1;
 id | customerid 
----+------------
  1 |           
  2 |           
  3 |           

I would like to know if have some mistake with my code or is there a problem with YAML? 'cause I think there should be some data on 'customerId', don't I ?



 Comments   
Comment by Roman S. Borschel [ 30/Dec/09 ]

This is expected behavior. You must maintain the bidirectional association properly. Doctrine only looks at the "owning side" of a bidirectional association. In the case of a bidirectional one-to-many, like in your case, the owning side is always the many-side. Since you only add the elements to the collection, but dont set the customer property pointing back to the customer, the association does not exist for Doctrine.

Change your code to:

$costumer = new DomainModel\Customer();
$user = new DomainModel\User();
$user2 = new DomainModel\User();
$user3 = new DomainModel\User();

$costumer->users->add($user);
$user->customer = $costumer;
$costumer->users->add($user2);
$user2->customer = $costumer;
$costumer->users->add($user3);
$user3->customer = $costumer;

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

And it should work.

Please read this section carefully: http://www.doctrine-project.org/documentation/manual/2_0/en/association-mapping#owning-side-and-inverse-side

Its a simple, yet essential concept to understand.

Hope that helps.

Comment by Henrique Girardi dos Santos [ 30/Dec/09 ]

I did this way sometime ago but I thought I was a mistake mine..but I see i was correct..
I created a prePersist method where I did it automatic and a postPersist to unset after that, cause I dont see any another reason to keep all my object customer inside the User class if inside Customer I have a User collection, so I know which Users belong to Customer..

why I need to set

oneToMany:
    users:
      targetEntity: User
      mappedBy: customer
      cascade: cascadePersist

in Customer?? I thought if I set the target and the mappedBy it would be enough..can't it be automatic? Or it's impossible?

Comment by Roman S. Borschel [ 30/Dec/09 ]

You dont need prePersist or postPersist. You just need to maintain your bidirectional associations properly. This is nothing doctrine specific, basic OOP.

And it is not automatic because this would break transparency. Its not the task of the ORM to fix your broken associations. Then your object model is suddenly broken without the persistence layer.

If you want a unidirectional one-to-many, you must map it through a join table. Its all in the documentation.

The behavior is very consistent and predictable (compared to what D1 does, for example...)

Comment by Henrique Girardi dos Santos [ 30/Dec/09 ]

I know I dont need prePersist or postPersist, It was just my choice, I just created them to make it automaticaly..
and I don't want a unidirectional..there's no reason to have another table to join them..
but now I understood why it's not automatic..

thanks man!





[DDC-188] Collections are not hydrated properly Created: 02/Dec/09  Updated: 02/Dec/09  Resolved: 02/Dec/09

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

Type: Bug Priority: Blocker
Reporter: Nico Kaiser Assignee: Roman S. Borschel
Resolution: Invalid Votes: 0
Labels: None


 Description   

The following example has User and Address entities, where User has many Addresses (ArrayCollection).

http://pastebin.com/f1f065cb0

$u = $em->find('Entity\User', $id);
$addresses = $u->getAddresses();
foreach ($addresses as $a) { }  // This line breaks!

The script runs until the foreach loop, then it breaks with a fatal error:

PHP Notice:  Undefined variable: owningAssoc in /home/kaiser/doctrine/doctrine/lib/Doctrine/ORM/Persist
ers/StandardEntityPersister.php on line 545
PHP Fatal error:  Uncaught exception 'Doctrine\ORM\ORMException' with message 'Unrecognized field: user
Id' in /home/kaiser/doctrine/doctrine/lib/Doctrine/ORM/ORMException.php:14
Stack trace:
#0 /home/kaiser/doctrine/doctrine/lib/Doctrine/ORM/Persisters/StandardEntityPersister.php(660): Doctrin
e\ORM\ORMException::unrecognizedField('userId')
#1 /home/kaiser/doctrine/doctrine/lib/Doctrine/ORM/Persisters/StandardEntityPersister.php(545): Doctrin
e\ORM\Persisters\StandardEntityPersister->_getSelectEntitiesSql(Array, NULL)
#2 /home/kaiser/doctrine/doctrine/lib/Doctrine/ORM/Mapping/OneToManyMapping.php(133): Doctrine\ORM\Pers
isters\StandardEntityPersister->loadOneToManyCollection(Array, Object(Doctrine\ORM\PersistentCollection
))
#3 /home/kaiser/doctrine/doctrine/lib/Doctrine/ORM/PersistentCollection.php(244): Doctrine\ORM\Mapping\
OneToManyMapping->load(Object(Entity\User), Object(Doctrine\ORM\PersistentCollection), Object(Doctrine\
ORM\EntityManager))
#4 /home/kaiser/doctrine/doctrine/lib/Doctrine/ORM/PersistentCollection.php(549): Doc in /home/kaiser/d
octrine/doctrine/lib/Doctrine/ORM/ORMException.php on line 14

If I uncomment the user creation code in my pastebin example (i.e. create User, Address first), it works as expected (assumingly because everything is in the EM already).

So this bug probably breaks all select-only use cases with collections (which makes it a Blocker in my opinion).



 Comments   
Comment by Roman S. Borschel [ 02/Dec/09 ]

Hm, this is dubious as this is directly and indirectly tested all over the place.

I was unable to reproduce it as of yet. Will keep you updated.

Comment by Roman S. Borschel [ 02/Dec/09 ]

Are you sure you dont have local modifications? The notice looks suspicious and _getSelectEntitiesSql(Array, NULL) does not look correct either. The association should be passed in.

Comment by Roman S. Borschel [ 02/Dec/09 ]

Your patch in DDC-162 is what breaks it.





[DDC-25] Boolean type does not work Created: 01/Oct/09  Updated: 14/Jun/10  Resolved: 01/Oct/09

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

Type: Bug Priority: Blocker
Reporter: Ismo Toijala Assignee: Roman S. Borschel
Resolution: Fixed Votes: 0
Labels: None


 Description   

The boolean type does not work. The method used by BooleanType does not exist. It should probably use getBooleanTypedeclarationSql(array $field).

In Doctrine\DBAL\Types\BooleanType:

OLD:
public function getSqlDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getBooleanDeclarationSql();
}

NEW:
public function getSqlDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getBooleanTypeDeclarationSql($fieldDeclaration);
}



 Comments   
Comment by Roman S. Borschel [ 01/Oct/09 ]

Just checked and this has already been fixed in HEAD and is therefore already fixed for the next release.

Thanks!





[DDC-491] Quoting Patch completly wrecked OCI8 support Created: 02/Apr/10  Updated: 02/Apr/10  Resolved: 02/Apr/10

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

Type: Bug Priority: Blocker
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

The quoting issue broke the OCI8 Driver, there is a fatal because of changes in the interface, and fixting that there are 160 test-failures



 Comments   
Comment by Benjamin Eberlei [ 02/Apr/10 ]

Failure is always something like:

164) Doctrine\Tests\ORM\Functional\Ticket\Ticket2481Test::testEmptyInsert
Exception: [PHPUnit_Framework_Error_Warning] Invalid argument supplied for foreach()

With queries:
4. SQL: 'INSERT INTO ticket_2481_products (id) VALUES (?)' Params: '1'
3. SQL: 'SELECT ticket_2481_products_id_seq.nextval FROM DUAL' Params: 
2. SQL: 'CREATE SEQUENCE ticket_2481_products_id_seq START WITH 1 MINVALUE 1 INCREMENT BY 10' Params: 

Trace:
/home/benny/code/php/wsnetbeans/Doctrine/trunk/lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php:138
/home/benny/code/php/wsnetbeans/Doctrine/trunk/lib/Doctrine/DBAL/Statement.php:130
/home/benny/code/php/wsnetbeans/Doctrine/trunk/lib/Doctrine/ORM/Persisters/StandardEntityPersister.php:187
/home/benny/code/php/wsnetbeans/Doctrine/trunk/lib/Doctrine/ORM/UnitOfWork.php:698
/home/benny/code/php/wsnetbeans/Doctrine/trunk/lib/Doctrine/ORM/UnitOfWork.php:291
/home/benny/code/php/wsnetbeans/Doctrine/trunk/lib/Doctrine/ORM/EntityManager.php:281
/home/benny/code/php/wsnetbeans/Doctrine/trunk/tests/Doctrine/Tests/ORM/Functional/Ticket/Ticket2481Test.php:27
Comment by Benjamin Eberlei [ 02/Apr/10 ]

Fixed





[DDC-427] DoctrineException.php is an empty file! Created: 16/Mar/10  Updated: 14/Jun/10  Resolved: 16/Mar/10

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

Type: Bug Priority: Blocker
Reporter: Mario Weidler Assignee: Roman S. Borschel
Resolution: Fixed Votes: 0
Labels: None


 Description   

http://svn.doctrine-project.org/trunk/lib/Doctrine/Common/DoctrineException.php is an empty file after rev 7313. in rev 7312 it is ok.



 Comments   
Comment by Roman S. Borschel [ 16/Mar/10 ]

It is removed now. Thanks for the notice.





[DDC-309] ReflectionException when using AbstractQuery::iterate() Created: 09/Feb/10  Updated: 09/Feb/10  Resolved: 09/Feb/10

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

Type: Bug Priority: Blocker
Reporter: Nico Kaiser Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None

Attachments: Text File ddc309.patch    

 Description   

When I use two Queries and iterate() over the results, the second one fails with a PHP Fatal error (ReflectionException). It has a strange message ('Class does not exist').
This happens with any two different entities. The error seems to occur when next() is called (directly or via foreach) and the objects are being created.

$q = $em->createQuery('SELECT c FROM Entity\Country c');
$q->iterate()->next();

$q = $em->createQuery('SELECT u FROM Entity\User u');
$q->iterate()->next(); // FAILS

Entities:
http://pastie.org/816374

Example code:
http://pastie.org/816377



 Comments   
Comment by Benjamin Eberlei [ 09/Feb/10 ]

It seems IterableResult does not support two iterators at once, because it re-uses the hydrator for both queries - effectivly deleting the information from the previous query and destroying the call.

Comment by Benjamin Eberlei [ 09/Feb/10 ]

Suggested patch

Comment by Benjamin Eberlei [ 09/Feb/10 ]

Fixed!





[DDC-765] \Symfony\Components renamed to \Symfony\Component (singular) ... refactoring unfinished. console cannot be invoked Created: 25/Aug/10  Updated: 30/Aug/10  Resolved: 29/Aug/10

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Tools
Affects Version/s: 2.0-BETA3
Fix Version/s: 2.0-BETA4
Security Level: All

Type: Bug Priority: Blocker
Reporter: Radomirs Cirskis Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

winXP, PHP 5.3.3



 Description   

I pulled from github the whole thing, but still stuck with sandbox:

\doctrine\tools\sandbox>php doctrine.php
.PHP Warning: require(doctrine\lib\vendor\Symfony\Components\Console\Helper\Helper.php): failed to open st
ream: No such file or directory in C:\Inetpub\wwwroot\BugTrackerORM\doctrine\lib\vendor\doctrine-common\lib\Doctrine\Common\ClassLoader.php
on line 148
PHP Stack trace:
PHP 1.

{main}

() ..... doctrine\tools\sandbox\doctrine.php:0
PHP 2. require() .... doctrine\tools\sandbox\doctrine.php:21
PHP 3. Doctrine\Common\ClassLoader->loadClass() ... doctrine\lib\vendor\doctrine-common\lib\Doctrine\Common\C
lassLoader.php:0
PHP 4. require() ... doctrine\lib\vendor\doctrine-common\lib\Doctrine\Common\ClassLoader.php:148
PHP 5. Doctrine\Common\ClassLoader->loadClass() C:\Inetpub\wwwroot\BugTrackerORM\doctrine\lib\vendor\doctrine-common\lib\Doctrine\Common\C
lassLoader.php:0

Warning: require(.... doctrine\lib\vendor\Symfony\Components\Console\Helper\Helper.php): failed to open stream:
No such file or directory in.... doctrine\lib\vendor\doctrine-common\lib\Doctrine\Common\ClassLoader.php on lin
e 148

well, it seams that at some stage Symfony\Components got renamed to Symfony\Coponet:

$ git log Component
commit 4a9f36800e3f55bc2cf61033573e1103594b4742
Author: S<C3><A9>bastien HOUZE <sebastienhouze@mbash.livebox.home>
Date: Mon Aug 23 08:21:41 2010 +0200
Symfony/Components renamed into Symfony/Component

When I copied Component into Componets I got:
.PHP Fatal error: Cannot redeclare class Symfony\Component\Console\Helper\Helper in doctrine\lib\vendor\Sy
mfony\Components\Console\Helper\Helper.php on line 21



 Comments   
Comment by Nico Kaiser [ 27/Aug/10 ]

Same for me, even worse, despite git submodule dependencies, the submodules (and their submodules) have different versions of "Components" vs. "Component", so the CLI is broken now.

Comment by Benjamin Eberlei [ 29/Aug/10 ]

Yes this sucks, unfortunately for ORM depending on DBAL Beta 3 we cannot easily change this.

Workaround until the next release of DBAL is uncommenting the following two lines instantiating DBAL Commands from your doctrine.php:

$cli->addCommands(array(
    // DBAL Commands
    //new \Doctrine\DBAL\Tools\Console\Command\RunSqlCommand(),
    //new \Doctrine\DBAL\Tools\Console\Command\ImportCommand(),

For the next release this week this will be resolved.

Comment by Sherri Flemings [ 30/Aug/10 ]

I came across this issue today. I installed Doctrine via PEAR and had to do a few things to get the sandbox example working, which might help as a workaround until the next release:

1. make sure the PEAR directory is part of your php.ini include path
2. move the Symfony directory from 'PEAR/Doctrine/Symfony' to 'PEAR/Symfony'
3. update the paths to Doctrine & Symfony inside 'tools/sandbox/doctrine.php' & 'tools/sandbox/cli-config.php'

I can now work with the sandbox examples.

As a reference, this is what my cli-config.php source looks like now: (sorry for the unformatted code <pre> tag & [code] weren't recognized.)

<?php

require_once 'Doctrine/Common/ClassLoader.php';

$classLoader = new \Doctrine\Common\ClassLoader('Doctrine\ORM', realpath(_DIR_ . 'Doctrine/ORM'));
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine\DBAL', realpath(_DIR_ . 'Doctrine/DBAL'));
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine\Common', realpath(_DIR_ . 'Doctrine/Common'));
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Symfony', realpath(_DIR_ . 'Symfony'));
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Entities', _DIR_);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Proxies', _DIR_);
$classLoader->register();

$config = new \Doctrine\ORM\Configuration();
$config->setMetadataCacheImpl(new \Doctrine\Common\Cache\ArrayCache);
$driverImpl = $config->newDefaultAnnotationDriver(array(_DIR_."/Entities"));
$config->setMetadataDriverImpl($driverImpl);

$config->setProxyDir(_DIR_ . '/Proxies');
$config->setProxyNamespace('Proxies');

$connectionOptions = array(
'driver' => 'pdo_sqlite',
'path' => 'database.sqlite'
);

$em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config);

$helpers = array(
'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()),
'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em)
);





[DDC-714] Fix of DDC-167 creates FatalError when persisting a new entity Created: 22/Jul/10  Updated: 25/Jul/10  Resolved: 25/Jul/10

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0-BETA3, 2.0-BETA4
Fix Version/s: 2.0-BETA3
Security Level: All

Type: Bug Priority: Blocker
Reporter: Michael Zach Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

Debian 5 (64bit), Postgresql 8.3, ZendServer 5.0.2, PHP 5.3.2, Doctrine-HEAD


Attachments: File uow.diff    

 Description   

The resolution of DDC-167 introduced a new problem in UnitOfWork on line 612 (function persistNew()) as well - when I try to save an entity, I get an Exception from my error handler (who captues php errors):

ErrorException with Argument 2 passed to Doctrine\ORM\Mapping\ClassMetadata::setIdentifierValues() must be an array, integer given, called in /var/www/svn/cWorld_ZF/branches/devel-trunk/library/Doctrine/ORM/UnitOfWork.php on line 612 and defined
Backtrace: #0: Doctrine\ORM\Mapping\ClassMetadata->setIdentifierValues at /var/www/svn/cWorld_ZF/branches/devel-trunk/library/Doctrine/ORM/UnitOfWork.php:612
#1: Doctrine\ORM\UnitOfWork->persistNew at /var/www/svn/cWorld_ZF/branches/devel-trunk/library/Doctrine/ORM/UnitOfWork.php:1247
#2: Doctrine\ORM\UnitOfWork->doPersist at /var/www/svn/cWorld_ZF/branches/devel-trunk/library/Doctrine/ORM/UnitOfWork.php:1210
#3: Doctrine\ORM\UnitOfWork->persist at /var/www/svn/cWorld_ZF/branches/devel-trunk/library/Doctrine/ORM/EntityManager.php:438

The relevant code in UoW is:

            $idValue = $idGen->generate($this->em, $entity);
            if ( ! $idGen instanceof \Doctrine\ORM\Id\AssignedGenerator) {
                $this->entityIdentifiers[$oid] = array($class->identifier[0] => $idValue);
                $class->setIdentifierValues($entity, $idValue);

We're using the SequenceGenerator

@SequenceGenerator(allocationSize=1,sequenceName="address_id_seq")

which doesn't return an array, so the array typehint fails and generates an error.

The fix, which worked for me, is attached.



 Comments   
Comment by Benjamin Eberlei [ 25/Jul/10 ]

This bug also leads to about 400 test failures in the Postgres ORM Testsuite

Comment by Benjamin Eberlei [ 25/Jul/10 ]

Fixed! Thanks for reporting.





[DDC-646] Missing inclusion of namespace Created: 19/Jun/10  Updated: 19/Jun/10  Resolved: 19/Jun/10

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Tools
Affects Version/s: 2.0-BETA2
Fix Version/s: 2.0-BETA3
Security Level: All

Type: Bug Priority: Blocker
Reporter: Antoine Hedgecock Assignee: Roman S. Borschel
Resolution: Fixed Votes: 0
Labels: None


 Description   

ORM\Tools\Console\Command\ConvertDoctrine1SchemaCommand.php requires that you include the following namespace

Doctrine\ORM\Tools\EntityGenerator,

else the following error is thrown

PHP Warning:  require(Doctrine/ORM/Tools/Console/Command/EntityGenerator.php): failed to open stream: No such file or directory in /usr/local/zend/share/pear/Doctrine/Common/ClassLoader.php on line 148
PHP Fatal error:  require(): Failed opening required 'Doctrine/ORM/Tools/Console/Command/EntityGenerator.php' (include_path='/Users/antoine/Sites/startaeget-3.3/application/library:.:/usr/local/zend/share/ZendFramework/library:/usr/local/zend/share/pear') in /usr/local/zend/share/pear/Doctrine/Common/ClassLoader.php on line 148


 Comments   
Comment by Benjamin Eberlei [ 19/Jun/10 ]

fixed.





[DDC-2328] [GH-597] use the extended proxy interface in the same namespace Created: 01/Mar/13  Updated: 03/Mar/13  Resolved: 03/Mar/13

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

Type: Bug Priority: Blocker
Reporter: Benjamin Eberlei Assignee: Guilherme Blanco
Resolution: Fixed Votes: 0
Labels: None


 Description   

This issue is created automatically through a Github pull request on behalf of MDrollette:

Url: https://github.com/doctrine/doctrine2/pull/597

Message:

Fix for this error:

FatalErrorException: Compile Error: Cannot use Doctrine\Common\Proxy\Proxy as Proxy because the name is already in use in .../vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/ProxyFactory.php line 26



 Comments   
Comment by Marco Pivetta [ 03/Mar/13 ]

Marking as blocker - has to go in before 2.4

Comment by Benjamin Eberlei [ 03/Mar/13 ]

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

Comment by Marco Pivetta [ 03/Mar/13 ]

merged





[DDC-2229] Undefined method Created: 09/Jan/13  Updated: 22/Apr/13  Resolved: 08/Apr/13

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

Type: Bug Priority: Blocker
Reporter: Karma Dordrak (Drak) Assignee: Benjamin Eberlei
Resolution: Invalid Votes: 0
Labels: None

Attachments: Text File SqlWalker.patch     File SqlWalkerTest.php    

 Description   

There is an undefined method called in Doctrine\ORM\Query\SqlWalker

Fatal error: Call to undefined method Doctrine\ORM\Query\AST\PathExpression::isSimpleArithmeticExpression() in vendor\doctrine\orm\lib\Doctrine\ORM\Query\SqlWalker.php on line 2091



 Comments   
Comment by Fabio B. Silva [ 12/Jan/13 ]

Hi Karma

Could you provide the failing DQL ?

Cheers

Comment by Karma Dordrak (Drak) [ 18/Jan/13 ]

It's generating SQL from a Doctrine Collection in a proxy class. Here is a link to the example: https://github.com/zikula/core/pull/674#discussion_r2696186

The SQL being generated is

`SELECT t0.name AS name1, t0.value AS value2, t0.user_id AS user_id3 FROM users_attributes t0 WHERE t0.user_id = ?`

The ? should be the value 2, but for some reason it's not being added. I've checked the files in the stack-trace below and the right values are entering into the process, just the wrong SQL seems to be generated.

Exception Trace
#0 Exception thrown in C:\xampp\htdocs\core13\src\vendor\doctrine\dbal\lib\Doctrine\DBAL\DBALException.php, line 47.
#1 C:\xampp\htdocs\core13\src\vendor\doctrine\orm\lib\Doctrine\ORM\Persisters\BasicEntityPersister.php(1599): Doctrine\DBAL\Connection->executeQuery('SELECT t0.name ...', Array, Array)
#2 C:\xampp\htdocs\core13\src\vendor\doctrine\orm\lib\Doctrine\ORM\Persisters\BasicEntityPersister.php(1558): Doctrine\ORM\Persisters\BasicEntityPersister->getOneToManyStatement(Array, Object(Users\Entity\User))
#3 C:\xampp\htdocs\core13\src\vendor\doctrine\orm\lib\Doctrine\ORM\UnitOfWork.php(2673): Doctrine\ORM\Persisters\BasicEntityPersister->loadOneToManyCollection(Array, Object(Users\Entity\User), Object(Doctrine\ORM\PersistentCollection))
#4 C:\xampp\htdocs\core13\src\vendor\doctrine\orm\lib\Doctrine\ORM\PersistentCollection.php(224): Doctrine\ORM\UnitOfWork->loadCollection(Object(Doctrine\ORM\PersistentCollection))
#5 C:\xampp\htdocs\core13\src\vendor\doctrine\orm\lib\Doctrine\ORM\PersistentCollection.php(576): Doctrine\ORM\PersistentCollection->initialize()
#6 C:\xampp\htdocs\core13\src\lib\util\UserUtil.php(1152): Doctrine\ORM\PersistentCollection->getIterator()
#7 C:\xampp\htdocs\core13\src\lib\util\UserUtil.php(2007): UserUtil::getVars('admin', false, 'uname', false)

Comment by Fabio B. Silva [ 20/Jan/13 ]

Hi Drak,

Could you try to write a failing test case please ?

Cheers

Comment by Alexander [ 10/Feb/13 ]

ping!

Comment by Daniel Huss [ 14/Feb/13 ]

SqlWalker::walkInExpression() does this:

$sql = $this->walkArithmeticExpression($inExpr->expression)

However, $inExpr->expression could be an instance of PathExpression. The grammar allows this case:

InExpression             ::= SingleValuedPathExpression ["NOT"] "IN" "(" (InParameter {"," InParameter}* | Subselect) ")"

PathExpression and ArithmeticExpression both extend Node, but a PathExpression is not an ArithmeticExpression, and therefore it has no method isSimpleArithmeticExpression.

If you still need a failing test case, I'll write one when I get home from work.

Comment by Fabio B. Silva [ 14/Feb/13 ]

Please Daniel Huss, A test case will be very useful..

Comment by Daniel Huss [ 15/Feb/13 ]

failing test case

Comment by Daniel Huss [ 02/Apr/13 ]

Bug still present in release 2.3.3

Is someone taking care of this? It seems easy enough to fix.

Comment by Marco Pivetta [ 02/Apr/13 ]

Daniel Huss you can open a PR with the attached patch + test. Can you do it or should I take care of it?

Comment by Daniel Huss [ 02/Apr/13 ]

Please take care of it for me this time. I'd rather avoid the git setup until I have a significant contribution to make.

Comment by Benjamin Eberlei [ 08/Apr/13 ]

This is invalid, you need to set the path expression differently, this is pseudo code:

new ArtihmeticExpression(new SimpleArithmeticExpression(arithmeticsTerms => new PathExpression)));
Comment by Daniel Huss [ 22/Apr/13 ]

Could this be bug in the DQL grammar, then? If I'm not mistaken, the resolution of an InExpression cannot involve an ArithmeticPrimary non-terminal. I find the correct solution as shown by Benjamin Eberlei to be quite astonishing, since a path expression like "alias.field" is not something I'd associate with the term "arithmetic".





[DDC-842] spl_object_hash tries to get hash from array - fails Created: 19/Oct/10  Updated: 24/Oct/10  Resolved: 24/Oct/10

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

Type: Bug Priority: Critical
Reporter: Sebastian Hoitz Assignee: Roman S. Borschel
Resolution: Invalid Votes: 0
Labels: None


 Description   

I have a model which looks like this:

Class A
protected $collectionB = array(); // Holds many Class B instances
protected $collectionC = array(); // Holds many Class C instances

Class B
protected $classC; // Holds one Class C instance

Class C
protected $attributes; // Holds many attributes which are stored in another entitty with SINGLE_TABLE discriminator

When I try to persist my object to the database, Doctrine causes this error:

Message: spl_object_hash() expects parameter 1 to be object, array given
File: C:\Users\Sebastian Hoitz\Documents\Entwicklung\kt_api\trunk\library\Doctrine\ORM\UnitOfWork.php
Line: 2043
Trace:

#0 [internal function]: PHPUnit_Util_ErrorHandler::handleError(2, 'spl_object_hash...', 'C:\Users\Sebast...', 2043, Array)
#1 C:\Users\Sebastian Hoitz\Documents\Entwicklung\kt_api\trunk\library\Doctrine\ORM\UnitOfWork.php(2043): spl_object_hash(Array)
#2 C:\Users\Sebastian Hoitz\Documents\Entwicklung\kt_api\trunk\library\Doctrine\ORM\Persisters\ManyToManyPersister.php(110): Doctrine\ORM\UnitOfWork->getEntityIdentifier(Array)
#3 C:\Users\Sebastian Hoitz\Documents\Entwicklung\kt_api\trunk\library\Doctrine\ORM\Persisters\ManyToManyPersister.php(92): Doctrine\ORM\Persisters\ManyToManyPersister->_collectJoinTableColumnParameters(Object(Doctrine\ORM\PersistentCollection), Array)
#4 C:\Users\Sebastian Hoitz\Documents\Entwicklung\kt_api\trunk\library\Doctrine\ORM\Persisters\AbstractCollectionPersister.php(124): Doctrine\ORM\Persisters\ManyToManyPersister->_getInsertRowSQLParameters(Object(Doctrine\ORM\PersistentCollection), Array)
#5 C:\Users\Sebastian Hoitz\Documents\Entwicklung\kt_api\trunk\library\Doctrine\ORM\Persisters\AbstractCollectionPersister.php(104): Doctrine\ORM\Persisters\AbstractCollectionPersister->insertRows(Object(Doctrine\ORM\PersistentCollection))
#6 C:\Users\Sebastian Hoitz\Documents\Entwicklung\kt_api\trunk\library\Doctrine\ORM\UnitOfWork.php(303): Doctrine\ORM\Persisters\AbstractCollectionPersister->update(Object(Doctrine\ORM\PersistentCollection))
#7 C:\Users\Sebastian Hoitz\Documents\Entwicklung\kt_api\trunk\library\Doctrine\ORM\EntityManager.php(320): Doctrine\ORM\UnitOfWork->commit()
#8 C:\Users\Sebastian Hoitz\Documents\Entwicklung\kt_models\trunk\library\App\Model\Service\Dao\Doctrine.php(26): Doctrine\ORM\EntityManager->flush()
#9 C:\Users\Sebastian Hoitz\Documents\Entwicklung\kt_models\trunk\library\App\Model\Service\Abstract.php(54): App_Model_Service_Dao_Doctrine->save(Object(App_Model_Ticket))
#10 C:\Users\Sebastian Hoitz\Documents\Entwicklung\kt_models\trunk\library\App\Model\Abstract.php(264): App_Model_Service_Abstract->save(Object(App_Model_Ticket))
#11 C:\Users\Sebastian Hoitz\Documents\Entwicklung\kt_models\trunk\library\App\Model\Ticket.php(75): App_Model_Abstract->save()
#12 C:\Users\Sebastian Hoitz\Documents\Entwicklung\kt_api\trunk\application\controllers\TicketController.php(69): App_Model_Ticket->save()
#13 C:\Users\Sebastian Hoitz\Documents\Entwicklung\kt_api\trunk\library\Zend\Controller\Action.php(513): TicketController->putAction()
#14 C:\Users\Sebastian Hoitz\Documents\Entwicklung\kt_api\trunk\library\Zend\Controller\Dispatcher\Standard.php(295): Zend_Controller_Action->dispatch('putAction')
#15 C:\Users\Sebastian Hoitz\Documents\Entwicklung\kt_api\trunk\library\Zend\Controller\Front.php(954): Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_HttpTestCase), Object(Zend_Controller_Response_HttpTestCase))
#16 C:\Users\Sebastian Hoitz\Documents\Entwicklung\kt_api\trunk\library\Zend\Test\PHPUnit\ControllerTestCase.php(199): Zend_Controller_Front->dispatch()
#17 C:\Users\Sebastian Hoitz\Documents\Entwicklung\kt_api\trunk\tests\application\controllers\TicketControllerTest.php(220): Zend_Test_PHPUnit_ControllerTestCase->dispatch('/ticket/1')
#18 [internal function]: TicketControllerTest->testUpdateTicketWithoutInvolvedContactsDoesNotCauseException()
#19 C:\Program Files (x86)\PHP\PEAR\pear\PHPUnit\Framework\TestCase.php(769): ReflectionMethod->invokeArgs(Object(TicketControllerTest), Array)
#20 C:\Program Files (x86)\PHP\PEAR\pear\PHPUnit\Framework\TestCase.php(659): PHPUnit_Framework_TestCase->runTest()
#21 C:\Program Files (x86)\PHP\PEAR\pear\PHPUnit\Framework\TestResult.php(617): PHPUnit_Framework_TestCase->runBare()
#22 C:\Program Files (x86)\PHP\PEAR\pear\PHPUnit\Framework\TestCase.php(607): PHPUnit_Framework_TestResult->run(Object(TicketControllerTest))
#23 C:\Program Files (x86)\PHP\PEAR\pear\PHPUnit\Framework\TestSuite.php(751): PHPUnit_Framework_TestCase->run(Object(PHPUnit_Framework_TestResult))
#24 C:\Program Files (x86)\PHP\PEAR\pear\PHPUnit\Framework\TestSuite.php(727): PHPUnit_Framework_TestSuite->runTest(Object(TicketControllerTest), Object(PHPUnit_Framework_TestResult))
#25 C:\Program Files (x86)\PHP\PEAR\pear\PHPUnit\Framework\TestSuite.php(687): PHPUnit_Framework_TestSuite->run(Object(PHPUnit_Framework_TestResult), false, Array, Array, false)
#26 C:\Program Files (x86)\PHP\PEAR\pear\PHPUnit\TextUI\TestRunner.php(305): PHPUnit_Framework_TestSuite->run(Object(PHPUnit_Framework_TestResult), false, Array, Array, false)
#27 C:\Program Files (x86)\PHP\PEAR\pear\PHPUnit\TextUI\Command.php(188): PHPUnit_TextUI_TestRunner->doRun(Object(PHPUnit_Framework_TestSuite), Array)
#28 C:\Program Files (x86)\PHP\PEAR\pear\PHPUnit\TextUI\Command.php(129): PHPUnit_TextUI_Command->run(Array, true)
#29 C:\Program Files (x86)\PHP\PEAR\phpunit(53): PHPUnit_TextUI_Command::main()
#30 {main}

I assume that this might happen, because of the Class B holding one Class C, and Class A also holding some Class C instances.

Those are, in some cases, the same. So when a new Class B is added, together with a new Class C, this new Class C is also added to Class A.
And somehow internally the already persisted Class C (Class B is getting persisted first) transforms the Class C instance into an array, and Doctrine can't save it anymore.

This is my guess of what happens. When I skip adding all the Class C instances to Class A, I don't get this error.



 Comments   
Comment by Marc Hodgins [ 19/Oct/10 ]

Do you get the same error if the collections are defined as ArrayCollections instead of PHP arrays ? Not sure if it is supported to use pure PHP arrays for collections.

See http://www.doctrine-project.org/projects/orm/2.0/docs/reference/association-mapping/en#collections

/** @Entity */
class A {
   /* ... */
   public function __construct() {
        $this->collectionB = new \Doctrine\Common\Collections\ArrayCollection;
   }

   /** @OneToMany(targetEntity="B", mappedBy="a") */
   protected $collectionB;
}

/** @Entity */
class B {
    /* ... */
    /** @ManyToOne(targetEntity="A", inversedBy="collectionB") */
    protected $a;
}  
Comment by Sebastian Hoitz [ 21/Oct/10 ]

I change the definition inside of my constructor method to ArrayCollection.

It's just that I write array() when I define the properties to that it's easier for the developers to tell which properties are collections or not.

So they actually are ArrayCollections.

Comment by Christian Heinrich [ 22/Oct/10 ]

Please post your entity mappings and some code.

It would be highly appreciated if you could also provide a test case so that we can confirm easily. Thank you!

Comment by Sebastian Hoitz [ 24/Oct/10 ]

This was a very stupid issue on my side which I wasn't even thinking about:

I have my own "ModelCollection" class in which I store my models. This class extends Doctrines ArrayCollection class and overwrites the toArray function. It changed its behavior so that the toArray was called recursively also on all child elements.
This caused the PersistentCollection to return an array on the getInsertDiff method.

Long story short: Maybe we should think about making the toArray method on the ArrayCollection class final, since Doctrines ORM relies on its behavior.





[DDC-832] Not quoted class name when updating entity Created: 07/Oct/10  Updated: 30/Oct/10  Resolved: 30/Oct/10

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

Type: Bug Priority: Critical
Reporter: Paul Fariello Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

postgresql 8.4 php 5.3.2


Issue Links:
Reference
relates to DBAL-57 Handling of Quoted Elements Open

 Description   

When trying to update an entity which have a reserved name. Doctrine doesn't quoted its name.

On Doctrine\ORM\Persisters\BasicEntityPersister, _updateTable, $tableName is directly used to create the sql. We may use $this->_class->getQuotedTableName($this->_platform) instead ?

I'm going to propose a merge for that on github.



 Comments   
Comment by Paul Fariello [ 08/Oct/10 ]

Here is a test case

Mapping
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

    <entity name="Like" table="`like`">
        <id name="id" type="integer" column="id">
            <generator strategy="SEQUENCE"/>
            <sequence-generator sequence-name="like_id_seq" allocation-size="1" initial-value="1"/>
        </id>

        <field name="value" column="value" type="string" />
    </entity>
</doctrine-mapping>
SQL
CREATE TABLE "like"
(
  id serial NOT NULL,
  "value" character varying,
  CONSTRAINT like_pkey PRIMARY KEY (id)
);
Class
class Like {

  private $id;
  public  $value;
}
Test case
$entity = new Like();
$entity->value = 'toto';

$doctrineEntityManager->persist($entity);
$doctrineEntityManager->flush();

$entity->value = 'tata';
$doctrineEntityManager->flush();
Comment by Benjamin Eberlei [ 30/Oct/10 ]

This issue partly depends on DBAL-57 (otherwise the testsuite keeps failing)

Comment by Benjamin Eberlei [ 30/Oct/10 ]

There is really no simple fix for this issue, your proposed one breaks joined table inheritance.

Comment by Benjamin Eberlei [ 30/Oct/10 ]

Found a way! fixed.





[DDC-827] Class Table Inheritance is broken when child classes have the same properties Created: 06/Oct/10  Updated: 05/Nov/10  Resolved: 06/Oct/10

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

Type: Bug Priority: Critical
Reporter: Nico Kaiser Assignee: Roman S. Borschel
Resolution: Invalid Votes: 0
Labels: None


 Description   

I create one Superclass and several Subclasses. The subclasses have properties with the same name (but as I also want to have Subclasses without these properties, this is the only elegant construction), in this example "name".

Now when I select the Superclass, I get all Subclass entities, but the "name" property is not hydrated correctly:

<?php

namespace Entities;

/**
 * @Entity
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="type", type="integer")
 * @DiscriminatorMap({ "1" = "Subclass1", "2" = "Subclass2" })
 */
class Superclass
{
    /** @Id @Column(type="integer") @GeneratedValue(strategy="AUTO") */
    public $id;
}

/** @Entity */
class Subclass1 extends Superclass
{
    /** @Column(type="string") */
    public $name;
}

/** @Entity */
class Subclass2 extends Superclass
{
    /** @Column(type="string") */
    public $name;
}

/* */

$sub1 = new Subclass1;
$sub1->name = 'sub1name';
$em->persist($sub1);

$sub2 = new Subclass2;
$sub2->name = 'sub2name';
$em->persist($sub2);

$em->flush();
$em->clear();

$query = $em->createQuery('SELECT s FROM Entities\Superclass s');
foreach ($query->execute() as $s) {
	echo 'name = ' . $s->name . PHP_EOL;
}

Output:

name = sub2name
name = 

The SQL however seems correct, both "name" columns are selected. This seems to be a bug in hydration.



 Comments   
Comment by Benjamin Eberlei [ 06/Oct/10 ]

Quoting from the Docs, chapter "Architecture" on the requirements of entities (and inheritance):

Any two entity classes in a class hierarchy that inherit directly or indirectly from one another must not have a mapped property with the same name. That is, if B inherits from A then B must not have a mapped field with the same name as an already mapped field that is inherited from A.
Comment by Stan Imbt [ 05/Nov/10 ]

Please reopen this issue. I can can confirm it and Benjamin's reason for rejecting it is invalid.

The two classes in the example are in neither directly nor indirectly inheriting from one another. They just happen to be siblings, i. e. they have the same superclass.

And to pre-empt the argument: It is not always bad design to have two classes in a hierarchy that have an identically named property. At least as long as PHP does not allow for horizontal re-use via traits or such.

Take this scenario:

 
SuperClass
|
+- SubClassA
|  +- SubSubClass1
|  +- SubSubClass2
|
+- SubClassB
   +- SubSubClass3
   +- SubSubClass4

Now if the need arises to have a property 'foo' on both SubSubClass1 and SubSubClass4, and 'foo' shall not be part of the top-most super class, because it makes no sense in any of the other classes, then we unfortunately have to repeat ourselves or employ some bad magic which certainly cannot be mapped with Doctrine anyway.

Comment by Benjamin Eberlei [ 05/Nov/10 ]

There is another open issue that handles this issue. Its indeed a bug.





[DDC-824] EntityManager::remove($entity), EntityManager::flush() does not remove the entity from DB Created: 02/Oct/10  Updated: 05/Nov/10  Resolved: 05/Nov/10

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

Type: Bug Priority: Critical
Reporter: Petr Motejlek Assignee: Benjamin Eberlei
Resolution: Invalid Votes: 0
Labels: None
Environment:

PgSQL 8.4, current Doctrine 2 from Git



 Description   
Test.php
/* 
 * @Entity
 * @Table(indexes={@Index(name="name", columns={"name"})})
 */
class ProductAttribute
{

    /**
     * ID
     * 
     * @Id @Column(type="integer") @GeneratedValue
     *
     * @var integer
     */
    protected $id;
    /**
     * Name
     *
     * @Column
     *
     * @var string
     */
    protected $name;
    /**
     * Values
     *
     * @OneToMany(targetEntity="ProductAttributeValue", mappedBy="attribute")
     *
     * @var array
     */
    protected $values;

    /**
     * Gets ID
     *
     * @return integer ID
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Sets ID
     *
     * @param integer $id ID
     *
     * @return void
     */
    public function setId($id = null)
    {
        $this->id = $id;
    }

    /**
     * Gets name
     *
     * @return string Name
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Sets name
     *
     * @param string $name Name
     *
     * @return void
     */
    public function setName($name = null)
    {
        $this->name = $name;
    }

    /**
     * Gets product attribute values
     *
     * @return array Product attribute values
     */
    public function getValues()
    {
        return $this->values;
    }

    /**
     * Adds product attribute value
     *
     * @param ProductAttributeValue $value Product attribute value
     * 
     * @return void
     */
    public function addValue(ProductAttributeValue $value)
    {
        $value->setAttribute($this);
        $this->values[] = $value;
    }

}

$attribute = $em->find('ProductAttribute', 1);
$em->remove($attribute);
$em->flush();

The upper code won't remove the entity from the database.... Corresponding DQL (DELETE ProductAttribute a WHERE a.id = 1) will remove it from the database...



 Comments   
Comment by Petr Motejlek [ 03/Oct/10 ]

I just found out, that when I have an entity containing a *ToMany column with cascade=

{"remove"}

set, all the entities are removed, except for the one...

Comment by Benjamin Eberlei [ 31/Oct/10 ]

I cannot reproduce this issue. Can you try to build a reproducible test-case? Have a look at tests/Doctrine/Tests/ORM/Functional/Ticket/* and build a test-case like this one here:

<?php

namespace Doctrine\Tests\ORM\Functional\Ticket;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Tests\Models\CMS\CmsUser;
use Doctrine\Tests\Models\CMS\CmsGroup;

require_once __DIR__ . '/../../../TestInit.php';

class DDC824Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
    public function setUp()
    {
        $this->useModelSet('cms');
        parent::setUp();
    }

    public function testRemoveWithCascade()
    {
        $user = new CmsUser();
        $user->username = "beberlei";
        $user->name = "Benjamin";
        $user->status = "active";

        $phone1 = new \Doctrine\Tests\Models\CMS\CmsPhonenumber();
        $phone1->phonenumber = "1234";
        $phone2 = new \Doctrine\Tests\Models\CMS\CmsPhonenumber();
        $phone2->phonenumber = "1235";

        $user->addPhonenumber($phone1);
        $user->addPhonenumber($phone2);

        $this->_em->persist($user);
        $this->_em->flush();
        $this->_em->clear();

        $user = $this->_em->find(get_class($user), $user->id);
        $phone1 = $user->phonenumbers[0];
        $phone2 = $user->phonenumbers[1];

        $this->assertTrue($this->_em->contains($user));
        $this->assertTrue($this->_em->contains($phone1));
        $this->assertTrue($this->_em->contains($phone2));

        $this->_em->remove($user);

        $this->assertFalse($this->_em->contains($user));
        $this->assertFalse($this->_em->contains($phone1));
        $this->assertFalse($this->_em->contains($phone2));
    }
}
Comment by Petr Motejlek [ 04/Nov/10 ]

I found out that I cannot reproduce the same behaviour with different project of mine either. It seems there's simply something rotten inside the one. I'll try investigating it a bit farther, but I think you can close this issue for now. Thanks for your time .





[DDC-809] ArrayHydrator and ObjectHydrator return different result sets for the same query Created: 16/Sep/10  Updated: 20/Sep/10  Resolved: 20/Sep/10

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

Type: Bug Priority: Critical
Reporter: Andriy Savchenko Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 1
Labels: None
Environment:

Ubuntu 8.04.3, php 5.3.3, mysql 5.1



 Description   

I have many to many relation for 2 entities.

ArrayHydrator and ObjectHydrator return different result sets for the same query. Because of some reasons ObjectHydrator mises 2 records.

Code snippet and SQL to create database structure:

CREATE TABLE IF NOT EXISTS `specification_value_test` (
  `specification_value_id` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`specification_value_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=96058 ;

INSERT INTO `specification_value_test` (`specification_value_id`) VALUES
(94506),
(94526),
(94564),
(94589),
(94593),
(94606),
(94607),
(94609),
(94711),
(94712),
(94780);


CREATE TABLE IF NOT EXISTS `variant_specification_value_test` (
  `variant_id` int(11) NOT NULL,
  `specification_value_id` int(11) NOT NULL,
  PRIMARY KEY (`variant_id`,`specification_value_id`),
  KEY `specification_value_id` (`specification_value_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `variant_specification_value_test` (`variant_id`, `specification_value_id`) VALUES
(545208, 94506),
(545209, 94506),
(545208, 94526),
(545209, 94526),
(545208, 94564),
(545209, 94564),
(545209, 94589),
(545209, 94593),
(545208, 94606),
(545209, 94606),
(545208, 94607),
(545209, 94607),
(545208, 94609),
(545209, 94609),
(545208, 94711),
(545208, 94712),
(545208, 94780),
(545209, 94780);

CREATE TABLE IF NOT EXISTS `variant_test` (
  `variant_id` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`variant_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT AUTO_INCREMENT=545210 ;

INSERT INTO `variant_test` (`variant_id`) VALUES
(545208),
(545209);
/**
 * @Table(name="variant_test")
 * @Entity
 */
class Variant extends Base
{
    /**
     * @Column(name="variant_id", type="integer")
     * @Id
     * @GeneratedValue(strategy="AUTO")
     */
    protected $variantId;
    
    /**
     * @ManyToMany(targetEntity="SpecificationValue", inversedBy="Variants")
     * @JoinTable(name="variant_specification_value_test",
     *   joinColumns={
     *     @JoinColumn(name="variant_id", referencedColumnName="variant_id")
     *   },
     *   inverseJoinColumns={
     *     @JoinColumn(name="specification_value_id", referencedColumnName="specification_value_id")
     *   }
     * )
     */
    protected $SpecificationValues;
}

/**
 * @Table(name="specification_value_test")
 * @Entity
 */
class SpecificationValue
{
    /**
     * @Column(name="specification_value_id", type="integer")
     * @Id
     * @GeneratedValue(strategy="AUTO")
     */
    protected $specificationValueId;
    
    /**
     * @var Variant
     *
     * @ManyToMany(targetEntity="Variant", mappedBy="SpecificationValues")
     */
    protected $Variants;
}



$result = $em->createQueryBuilder()
    ->select('Variant, SpecificationValue')
    ->from('Variant', 'Variant')
    ->leftJoin('Variant.SpecificationValues', 'SpecificationValue')
    ->getQuery()
    ->getResult();
	
// returns 9 specification values for first variant and 7 specification values for second variant
\Doctrine\Common\Util\Debug($result, 4);

$em->createQueryBuilder()
    ->select('Variant, SpecificationValue')
    ->from('Variant', 'Variant')
    ->leftJoin('Variant.SpecificationValues', 'SpecificationValue')
    ->getQuery()
    ->getArrayResult();

// returns 9 specification values for first variant and 9 specification values for second variant
\Doctrine\Common\Util\Debug($result);


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

Fixed formatting

Comment by Benjamin Eberlei [ 20/Sep/10 ]

Verified and updated priority, has to be in RC1

Comment by Benjamin Eberlei [ 20/Sep/10 ]

Fixed the issue, thank you very much for reporting





[DDC-1274] there is no way to set collate of the table charset ! Created: 13/Jul/11  Updated: 12/Nov/12  Resolved: 13/Jul/11

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

Type: Bug Priority: Critical
Reporter: sina miandashti Assignee: Benjamin Eberlei
Resolution: Invalid Votes: 0
Labels: charset, collate, collation, mysql
Environment:

zend frame work 1.10 with doctrine orm 2 and dbal



 Description   

i searched a lot for this

there is no way to set the collate of table fields to for ex. utf8_persian_ci in doctrine settings



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

This is not a supported feature, if you set the collation in the CREATE DATABASE statement this will inherit to all fields automatically.

Comment by William Knak [ 12/Nov/12 ]

Actually Doctrine 2.3.0 does not allow inheritance. Please look at Issue #DDC-2139 . At least, if there's an option to set a global default collation (wich I didn't find), the problem will occurs every time a table of string/varchar field was created by Symfony2 Doctrine Command.





[DDC-1254] EntityGenerator does not respect Class Inheritance properly Created: 06/Jul/11  Updated: 14/Jul/11  Resolved: 12/Jul/11

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

Type: Bug Priority: Critical
Reporter: Daniel Reiche Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

Symfony2 RC4, PHP 5.3., Fedora 15


Issue Links:
Dependency
is required for DDC-1243 Problem to generate code for subclass... Resolved

 Description   

Hi,
as mentioned here DDC-904, https://github.com/symfony/symfony/issues/1550# and https://github.com/stof/StofDoctrineExtensionsBundle/issues/47
The Doctrine2 EntityGenerator does not respect inheritance of Models correctly, especially when inheriting the primary field from an abstract base class as done by Symfony2's StofDoctrineExtensionsBundle.

This is extremly annoying since it renders the generator unusable when aforementioned bundle is active. It always fails with this message:

[Doctrine\ORM\Mapping\MappingException]

No identifier/primary key specified for Entity 'Stof\DoctrineExtensionsBundle\Entity\Translation'. Every Entity must have an
identifier/primary key.

DDC-904 mentioned this should be fixed, but this is not true: bug is still found in latest Symfony2 git.
The docs only refer to using a single mapping format inside a bundle, but this does not work. Stof... uses xml mappings and it does not matter if i use yml or annotiations in a different bundle - the above error is still present.



 Comments   
Comment by venimus [ 11/Jul/11 ]

I already reported this issue, but it was not fixed http://www.doctrine-project.org/jira/browse/DDC-1177

Comment by Benjamin Eberlei [ 12/Jul/11 ]

Fixed

@venimius: You didn't say a word about EntityGenerator in your ticket, which was the critical information that helped me solve this issue.

Comment by Daniel Reiche [ 13/Jul/11 ]

THANKS!

Comment by venimus [ 14/Jul/11 ]

@Benajmin, sorry but wasn't sure where is the problem i thought it might be me, that is why i simply stated that it is a schema-tool problem.





[DDC-1225] Invalid SQL generated (extra comma) when joining to entity with composite PK Created: 23/Jun/11  Updated: 29/Aug/11  Resolved: 15/Aug/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1
Fix Version/s: 2.1.2, 2.2
Security Level: All

Type: Bug Priority: Critical
Reporter: Glen Ainscow Assignee: Guilherme Blanco
Resolution: Fixed Votes: 1
Labels: None

Attachments: Zip Archive models.zip     Zip Archive models.zip    

 Description   
            $qb->from('Tournaments_Model_StageBracketTeamRegistration', 'r')
               ->innerJoin('r.teamSelection', 'ts')
               ->innerJoin('ts.players', 'tsp')
               ->select('r, ts, tsp')
               ->where('r.stageBracket = ?1')
               ->andWhere('r.opponentIsReserve = false')
               ->orderBy('r.registrationDateTime')
               ->setParameter(1, $bracket);

Generates:

SELECT s0_.id AS id0, s0_.opponent_is_reserve AS opponent_is_reserve1, s0_.opponent_checked_in AS opponent_checked_in2, s0_.registration_date_time AS registration_date_time3, t1_.id AS id4,, s0_.type AS type5, s0_.stage_bracket_id AS stage_bracket_id6, s2_.team_selection_id AS team_selection_id7, t1_.team_id AS team_id8, t3_.team_selection_id AS team_selection_id9, t3_.player_id AS player_id10
FROM stage_bracket_team_registrations s2_
INNER JOIN stage_bracket_registrations s0_ ON s2_.id = s0_.id
INNER JOIN team_selections t1_ ON s2_.team_selection_id = t1_.id
INNER JOIN team_selection_players t3_ ON t1_.id = t3_.team_selection_id
WHERE s0_.stage_bracket_id = 22 AND s0_.opponent_is_reserve = 0
ORDER BY s0_.registration_date_time ASC

Note the 2nd comma after "t1_.id AS id4". TeamSelectionPlayer uses a composite PK. I have attached the relevant entity classes.



 Comments   
Comment by Benjamin Eberlei [ 28/Jul/11 ]

Fixed

Comment by Glen Ainscow [ 12/Aug/11 ]

Where can I find the changeset? Would it be easy for me to apply the changes to 2.1.0?

Comment by Glen Ainscow [ 12/Aug/11 ]

No worries, found the changes here: https://github.com/doctrine/doctrine2/commit/196632978cf39bc3914e14739767cb5b72a8df9d

Comment by Glen Ainscow [ 13/Aug/11 ]

This is still an issue:

            $qb->from('Tournaments_Model_StageBracketRegisteredPlayer', 'p')
               ->select('p')
               ->where('p.stageBracket = ?1')
               ->andWhere('p.player = ?2')
               ->setParameter(1, $bracket)
               ->setParameter(2, $player)
               ->getQuery()
               ->getOneOrNullResult();

Results in:

SELECT , s0_.stage_bracket_id AS stage_bracket_id0, s0_.player_id AS player_id1, s0_.game_account_id AS game_account_id2 FROM stage_bracket_registered_players s0_ WHERE s0_.stage_bracket_id = 14 AND s0_.player_id = 5
Comment by Guilherme Blanco [ 14/Aug/11 ]

Hi,

I attempted to create a failing test case for this issue, but either the provided entities are not enough or the issue is not reproducible anymore (it was already fixed in latest 2.2-DEV).

Could you please try to compile everything into a test case?

Cheers,

Comment by Glen Ainscow [ 15/Aug/11 ]

Hi Guilherme,

I'll attach 2 simple entities for testing. You can run the following query:

        $qb->from('App_Model_TestEntity1', 'te1')
           ->select('te1')
           ->where('te1.testEntity2 = ?1')
           ->setParameter(1, 0)
           ->getQuery()
           ->getOneOrNullResult();

I'm running this against 2.1.0 + this change.

Thanks.

Comment by Guilherme Blanco [ 15/Aug/11 ]

Fixed in this commit https://github.com/doctrine/doctrine2/commit/6857134f36097187ab2f0d932f4f1d9ffab12854

Thanks for the report!

Comment by Benjamin Eberlei [ 29/Aug/11 ]

Merged into 2.1.x





[DDC-1204] Single Table Inheritance - Columns of one hierarchy are dropped Created: 13/Jun/11  Updated: 15/Jun/11  Resolved: 15/Jun/11

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

Type: Bug Priority: Critical
Reporter: Johannes Schmitt Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

In the following example, the columns of the classes B, C, D are not in the database schema. Only those of the classes A and E.

/**
 * @ORM\Entity
 * @ORM\Table(name = "a")
 * @ORM\ChangeTrackingPolicy("DEFERRED_EXPLICIT")
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="type", type="string", length=20)
 * @ORM\DiscriminatorMap({
 *     "c"   = "C",
 *     "d"   = "D",
 *     "e"   = "E"
 * })
 */
abstract class A { }

/**
 * @ORM\Entity
 */
abstract class B extends A { }

/**
 * @ORM\Entity
 */
class C extends B { }

/**
 * @ORM\Entity
 */
class D extends B { }

/**
 * @ORM\Entity
 */
class E extends A { }


 Comments   
Comment by Johannes Schmitt [ 13/Jun/11 ]

The problem here is that class B is not part of the discriminator map which was necessary due to issue #DDC-1203. So, once that is resolved this can likely be closed as well.

Comment by Benjamin Eberlei [ 15/Jun/11 ]

Fixed





[DDC-1203] Single Table Inheritance - Discriminator Column is not populated Created: 12/Jun/11  Updated: 30/Jun/11  Resolved: 18/Jun/11

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

Type: Bug Priority: Critical
Reporter: Johannes Schmitt Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None

Attachments: JPEG File graph.jpg    

 Description   

I have the following class inheritance; if I have the mapped super class in there, the discriminator column is not populated; if I remove it, it is correctly set.

/**
 * @ORM\Entity
 * @ORM\Table(name = "a")
 * @ORM\ChangeTrackingPolicy("DEFERRED_EXPLICIT")
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="type", type="string", length=20)
 * @ORM\DiscriminatorMap({
 *     "c"   = "C",
 *     "d"   = "D"
 * })
 */
abstract class A { }

/**
 * @ORM\MappedSuperClass
 */
abstract class B extends A { }

/**
 * @ORM\Entity
 */
class C extends B { }

/**
 * @ORM\Entity
 */
class D extends B { }


 Comments   
Comment by Benjamin Eberlei [ 18/Jun/11 ]

This was fixed or something.

Comment by Nikolai Spassoff [ 30/Jun/11 ]

The following hierarchy doesn't work after commit 5ff44b5ec75f6d716ec3.

The thrown exception is:
'Entity\AbstractMaschine' has to be part of the descriminator map of 'Entity\Inventory'

Inventory is just a plain abstract class which contains the @Id field and a few methods used by all subclasses.

Comment by Benjamin Eberlei [ 30/Jun/11 ]

Yes, please add it to the discriminator map, it is necessary for internal algorithms that this class is in the map.

Comment by Benjamin Eberlei [ 30/Jun/11 ]

Ok this has been changed, its not necessary for abstract classes anymore.





[DDC-1190] Update the doctrine mapping schma in such way it will allow extending the final xml with data from different vendors Created: 03/Jun/11  Updated: 15/Jun/11  Resolved: 15/Jun/11

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

Type: Bug Priority: Critical
Reporter: Miha Vrhovnik Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

I've already made a PR
https://github.com/doctrine/doctrine2/pull/64



 Comments   
Comment by Benjamin Eberlei [ 15/Jun/11 ]

This was implemented.





[DDC-1163] entity persister gets superclasses' metadata for proxied subclass entity Created: 20/May/11  Updated: 05/Jun/11  Resolved: 05/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0.3, 2.0.4, 2.0.5
Fix Version/s: 2.0.6, 2.1
Security Level: All

Type: Bug Priority: Critical
Reporter: Stan Imbt Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

PHP 5.3.6 on Debian Lenny & WinXP, PostgreSQL 8.4 & SQLite 3


Attachments: Zip Archive testcase.zip    

 Description   

Using class table inheritance:

When a proxy for a subclass-entity is registered at the unit of work and another entity, which references that entities' superclass, is added or removed, the employed entity persister gets/uses the superclasses' metadata.

If the change-set of the referenced entity contains fields only defined in the subclass, the persister will create bogus SQL because it has no column names or data types: UPDATE table SET = ? WHERE id = ?

The attached test case is stand-alone, creating an SQLite in-memory DB (sorry, I'm not familiar with your test suite).

Only the path to Doctrine must be adapted at the top of 'run_test.php'.
The file 'SubclassPropertyBugTest.php' also contains a more detailed description.



 Comments   
Comment by Benjamin Eberlei [ 05/Jun/11 ]

Verified on 2.0.5, interestingly this bug seems to have vanished in 2.1 / master. I will investigate whats wrong.

Comment by Benjamin Eberlei [ 05/Jun/11 ]

Found the problem and fixed it. Very nasty timing error with inheritance and a false check.





[DDC-1113] getCommitOrder misses some relations when used with Inheritance and self-referencing field Created: 12/Apr/11  Updated: 27/Aug/11  Resolved: 27/Aug/11

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

Type: Bug Priority: Critical
Reporter: Illya Klymov Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

Let's assume we have an Entity class "ParentClass", which uses a single table inheritance with child classes "ChildOne" and "ChildTwo".
"ParentClass" also have one-to-one unidirectional association with "FooBar" class named "foobar", and a self-referencing association called "parent"

We construct entity of "ChildOne" type, filling "foobar" link with new FooBar object. The same action is made for entity of "ChildTwo" type.
Entity of "ChildOne" type is persisted and flushed.

At this point getCommitOrder builds a commit order. ChildOne <---> FooBar link appears in dependency graph because of "foobar" association.
While processing assocs it reveals "parent" assoc in parent class and builds following links in dependency graph:
ChildOne <---> ChildOne
ChildOne <---> ChildTwo

After that "ChildTwo" entity is persisted and flushed. At this point commit calculator thinks it already have "ChildTwo" in it's storage so no assoc calculation are made for "childTwo" class

If we attemp to delete "ChildTwo" class flush() will fail because of missing link "ChildTwo <-----> Foobar" assoc



 Comments   
Comment by Illya Klymov [ 12/Apr/11 ]

I've opened pull request https://github.com/doctrine/doctrine2/pull/47 with my fix to this issue. I'm new to doctrine development so feel free to make any suggestions how to improve it

Comment by Benjamin Eberlei [ 26/Jul/11 ]

Increased priority, i should really look at this one soon!

Comment by Benjamin Eberlei [ 06/Aug/11 ]

The test with this pull request does not fail even without the applied patch.

Comment by Benjamin Eberlei [ 06/Aug/11 ]

sorry my bad, ran this with SQLite (Which has no FKs)

Comment by Benjamin Eberlei [ 27/Aug/11 ]

Fixed, simplifed a bit since one part was not necessary and this hits performance quite significantly





[DDC-1105] Unable to persist entities implemented using Class Table Inheritance(CTI) strategy across multiple database tables Created: 07/Apr/11  Updated: 01/May/11  Resolved: 01/May/11

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

Type: Bug Priority: Critical
Reporter: Ire Ogunsina Assignee: Benjamin Eberlei
Resolution: Won't Fix Votes: 0
Labels: None
Environment:

zend framework, Doctrine 2, Apache, MySQL, Windows



 Description   

I have 2 classes, a Parent class, Person and a Child class Employee using Class Table Inheritance mapping strategy. The classes' corresponding tables exist in 2 separate database: Person table exists in database: dbOne and Employee table is in dbTwo.

The classes are like:

/**

  • @Entity
  • @InheritanceType("JOINED")
  • @DiscriminatorColumn(name="discr", type="string")
  • @DiscriminatorMap( {"person" = "Person", "employee" = "Employee"}

    )

  • @Table(name="Person")
    */
    class Person
    {
    and the child class

/**

  • @Entity
  • @Table(name="Employee")
    */
    class Employee extends Person
    {
    The schema for the Employee table looks like so:

CREATE TABLE Employee (
id INT NOT NULL,
department VARCHAR(50) NOT NULL,
PRIMARY KEY(id)
) ENGINE = InnoDB;
ALTER TABLE Employee ADD FOREIGN KEY (id) REFERENCES dbOne.Person(id) ON DELETE CASCADE

where the reference table name is prefixed with the database name.

The main problem is that when I call

$this->entityManager->flush();

On Person object, it flags an error:

Message: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'dbOne.Employee' doesn't exist . Apparently, the expectation is for the base class to persist its instance and be able to automatically persist the sub class as well. This problem is absent when the tables are in the same database- which indicates that the CTI structure expects the entity tables to be within the same database. The reverse is true if I call the entity manager (for dbTwo) to save an Employee object.

Is there a workaround for this bug/feature?



 Comments   
Comment by Ire Ogunsina [ 07/Apr/11 ]

It appears that ORM technologies are limited in their ability to generate SQL queries that interrogate multiple databases in a single SQL statement (unit of work). This largely may be due to the fact that the entity manager is restricted to one database. This limitation may be responsible for this behavior.

Comment by Benjamin Eberlei [ 01/May/11 ]

Yes, the EntityManager is focused on one database, not multiple.

There are two workarounds:

1. @Table(name="dbOne.foo")
2. Create a View in the database.





[DDC-1047] Combining explicit join syntax with multiple from-clause argument-list entries will generate broken SQL on MySQL Created: 26/Feb/11  Updated: 29/Sep/11  Resolved: 29/Sep/11

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

Type: Bug Priority: Critical
Reporter: Daniel Alvarez Arribas Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None

Attachments: File SQLWalker for Doctrine 2.03, always generating join expressions at the end of the FROM clause.php     File SQLWalker.php     File SqlWalker.php     File SqlWalker.php    

 Description   

When using explicit join syntax, MySQL requires the from-clause argument-list to have either only one entry, or, if it contains multiple entries, it requires that the complete argument-list be surrounded by parantheses. Currently, Doctrine 2 does not respect this requirement when compiling DQL statements, and produces broken SQL in some situations.

Consider the following example of a legitimate DQL query.

SELECT vendorListXMLRow
                        FROM \persistentData\model\import\vendorListXML\VendorListXMLRow vendorListXMLRow,
                             \persistentData\model\import\parameterListXML\ParameterListXMLRow parameterListXMLRow
       			        JOIN vendorListXMLRow.vendorListXML vendorListXML
       			        JOIN vendorListXML.inputComponentDataVersion vendorListXMLInputComponentDataVersion
                        JOIN parameterListXMLRow.parameterListXML parameterListXML
       			        JOIN parameterListXML.inputComponentDataVersion parameterListXMLInputComponentDataVersion
                       WHERE :dataVersion MEMBER OF vendorListXMLInputComponentDataVersion.dataVersions
                         AND vendorListXMLRow.ID = parameterListXMLRow.WERT
                         AND :dataVersion MEMBER OF parameterListXMLInputComponentDataVersion.dataVersions
                         AND parameterListXMLRow.ID = :parameterID

This will be compiled down to:

SELECT v0_.ID AS ID0, v0_.DEBITORENSAMMELKONTENLISTEN_DATEINAME AS DEBITORENSAMMELKONTENLISTEN_DATEINAME1, v0_.RECHNUNGS_KONFIGURATION_DATEINAME AS RECHNUNGS_KONFIGURATION_DATEINAME2, v0_.RECHNUNGS_LAYOUT_DATEINAME AS RECHNUNGS_LAYOUT_DATEINAME3, v0_.dbID AS dbID4, v0_.vendorListXML_dbID AS vendorListXML_dbID5
FROM VendorListXMLRow v0_, ParameterListXMLRow p1_
INNER JOIN VendorListXML v2_ ON v0_.vendorListXML_dbID = v2_.dbID LEFT JOIN VersionedDataObject v3_ ON v2_.dbID = v3_.dbID INNER JOIN InputComponentDataVersion i4_ ON v3_.inputComponentDataVersion_dbID = i4_.dbID INNER JOIN ParameterListXML p5_ ON p1_.parameterListXML_dbID = p5_.dbID
LEFT JOIN VersionedDataObject v6_ ON p5_.dbID = v6_.dbID
INNER JOIN InputComponentDataVersion i7_ ON v6_.inputComponentDataVersion_dbID = i7_.dbID
WHERE EXISTS
 (SELECT 1 FROM DataVersion_inputComponentDataVersions d8_ INNER JOIN DataVersion d9_ ON d8_.inputComponentDataVersion_dbID = d9_.dbID WHERE d8_.dataVersion_dbID = i4_.dbID AND d9_.dbID = '1') AND v0_.ID = p1_.WERT AND EXISTS
 (SELECT 1 FROM DataVersion_inputComponentDataVersions d8_ INNER JOIN DataVersion d9_ ON d8_.inputComponentDataVersion_dbID = d9_.dbID WHERE d8_.dataVersion_dbID = i7_.dbID AND d9_.dbID = '1') AND p1_.ID = 'Mandant zur Zuordnung von Analogaufträgen' LIMIT 1

This SQL query can't be executed, because MySQL will complain. The error message is "SQLSTATE[42S22]: Column not found: 1054 Unknown column 'v0_.vendorListXML_dbID' in 'on clause".

The resulting error gives no sensible error message, and is a pain to debug, because obviously, the column mentioned does exist. The real cause of the error is that MySQL will cease to correctly interpret the aliases given, as long as parantheses not are used. I acknowledge that the MySQL behavior is downright stupid. This might well be considered a bug in MySQL, but unfortunately, the parantheses are documented in their syntax docs (http://dev.mysql.com/doc/refman/5.0/en/join.html), though I could not find any official statement regarding the use.

Fortunately it is easy to patch Doctrine to support it.

Now, let's add parantheses around the from clause argument list of the generated SQL statement:

SELECT v0_.ID AS ID0, v0_.DEBITORENSAMMELKONTENLISTEN_DATEINAME AS DEBITORENSAMMELKONTENLISTEN_DATEINAME1, v0_.RECHNUNGS_KONFIGURATION_DATEINAME AS RECHNUNGS_KONFIGURATION_DATEINAME2, v0_.RECHNUNGS_LAYOUT_DATEINAME AS RECHNUNGS_LAYOUT_DATEINAME3, v0_.dbID AS dbID4, v0_.vendorListXML_dbID AS vendorListXML_dbID5
 FROM (VendorListXMLRow v0_, ParameterListXMLRow p1_) 
INNER JOIN VendorListXML v2_ ON v0_.vendorListXML_dbID = v2_.dbID LEFT JOIN VersionedDataObject v3_ ON v2_.dbID = v3_.dbID
INNER JOIN InputComponentDataVersion i4_ ON v3_.inputComponentDataVersion_dbID = i4_.dbID INNER JOIN ParameterListXML p5_ ON p1_.parameterListXML_dbID = p5_.dbID 
LEFT JOIN VersionedDataObject v6_ ON p5_.dbID = v6_.dbID
INNER JOIN InputComponentDataVersion i7_ ON v6_.inputComponentDataVersion_dbID = i7_.dbID
WHERE EXISTS 
(SELECT 1 FROM DataVersion_inputComponentDataVersions d8_ INNER JOIN DataVersion d9_ ON d8_.inputComponentDataVersion_dbID = d9_.dbID WHERE d8_.dataVersion_dbID = i4_.dbID AND d9_.dbID = '1') AND v0_.ID = p1_.WERT AND EXISTS
 (SELECT 1 FROM DataVersion_inputComponentDataVersions d8_ INNER JOIN DataVersion d9_ ON d8_.inputComponentDataVersion_dbID = d9_.dbID WHERE d8_.dataVersion_dbID = i7_.dbID AND d9_.dbID = '1') AND p1_.ID = 'Mandant zur Zuordnung von Analogaufträgen' LIMIT 1

This works without complaints.

The example query is a bit peculiar in that it uses both explicit join syntax and various from-clause entries. But according to DQL's EBNF definition, there is nothing that should prevent Doctrine 2 users from doing it. And it must work this way, because anyway else it would be impossible to specify join criteria that are no declared relationships (using explicit join-syntax only), and the other way around (using from-clause entries only, i. e. no explicit join syntax, and specifying the join conditions in the where clause) makes it impossible to join on foreign keys. Hence, under such circumstances, combining both approaches is a requirement if joins should be fully expressive.

It is possible to completely work around these issues by sticking to a single from-clause entry, using explicit join syntax, and adding all further joins that require non-foreign-key join expressions into correlated subqueries. However, this is not straightforward and forces users into a workaround for what joins are intended for in the first place.

This scenario is annoying, because if you were to suppress that use case completely, the EBNF would have to be significantly rewritten (and it would be the wrong thing to do IMO anyway).

I believe the most straightforward solution is to always add parantheses around the from-clause argument-list for the MySQL dialect.

I found this web page, which might be worth reading to get an understanding of the problem, as it describes the exact same issue (though with Hibernate):

http://www.thinkplexx.com/learn/article/db/quer/joinwhere



 Comments   
Comment by Daniel Alvarez Arribas [ 26/Feb/11 ]

Here's a patched Doctrine\ORM\Query\SqlWalker that implements the additional parantheses around the from-clause argument-list.

Consider this prototype quality, for testing and verification purposes. I am sure it could be implemented more cleanly.

I have not yet taken the time to get the big picture of where this can be sustainably implemented in Doctrine 2 (specially being probably MySQL-specific), but I needed this to work quickly, so this is a first shot at it.

Comment by Benjamin Eberlei [ 01/Mar/11 ]

Fixed formating

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

It actually seems to be an SQL 2003 compliance thing.

http://bugs.mysql.com/bug.php?id=13551

See post from 8 Oct 2005 12:12.

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

It's becoming even worse since the problem is actually more general. Consider this query:

SELECT wpomOrder.documentDate, wpomOrder.documentID,
                                SUM(orderLine.value), SUM(orderLine.totalValue), SUM(orderLine.purchaseValue), SUM(orderLine.totalPurchaseValue)
                           FROM \persistentData\model\import\webProductionOrderManager\WPOMOrder wpomOrder,
                                \persistentData\model\import\webProductionOrderManager\XMLDocument xmlDocument
                           JOIN wpomOrder.inputComponentDataVersion webProductionOrderManagerInputComponentDataVersion
                           JOIN wpomOrder.orderLines orderLine
                          WHERE :dataVersion MEMBER OF webProductionOrderManagerInputComponentDataVersion.dataVersions
                            AND wpomOrder.destinationOutlet = :outlet
                            AND xmlDocument.wpomOrder = wpomOrder
                            AND wpomOrder.orderCreatorListXMLRow IN (SELECT orderCreatorListXMLRow
                                                                       FROM \persistentData\model\import\orderCreatorListXML\OrderCreatorListXMLRow orderCreatorListXMLRow
                                                                       JOIN orderCreatorListXMLRow.orderCreatorListXML orderCreatorListXML
                                                                       JOIN orderCreatorListXML.inputComponentDataVersion orderCreatorListXMLInputComponentDataVersion
                                                                      WHERE :dataVersion MEMBER OF orderCreatorListXMLInputComponentDataVersion.dataVersions
                                                                        AND orderCreatorListXMLRow.ABRECHNUNGSTYP = \'' . self::$creatorModeInvoices . '\')
                          
                          ORDER BY wpomOrder.documentDate

I do not want to bother you with the details of this data model. Suffices to say that WPOMOrder inherits from VersionedDataObject.

This will be compiled down to:

SELECT w0_.documentDate AS documentDate0, w0_.documentID AS documentID1, SUM(o1_.value) AS sclr2, SUM(o1_.totalValue) AS sclr3, SUM(o1_.purchaseValue) AS sclr4, SUM(o1_.totalPurchaseValue) AS sclr5
 FROM (WPOMOrder w0_) INNER JOIN VersionedDataObject v2_ ON w0_.dbID = v2_.dbID, XMLDocument x3_ INNER JOIN Document d4_ ON x3_.dbID = d4_.dbID
 INNER JOIN InputComponentDataVersion i5_ ON v2_.inputComponentDataVersion_dbID = i5_.dbID INNER JOIN OrderLine o1_ ON w0_.dbID = o1_.wpomOrder_dbID
 WHERE EXISTS (SELECT 1 FROM DataVersion_inputComponentDataVersions d6_ INNER JOIN DataVersion d7_ ON d6_.inputComponentDataVersion_dbID = d7_.dbID WHERE d6_.dataVersion_dbID = i5_.dbID AND d7_.dbID = '1') AND
 w0_.destinationOutlet_dbID = '1' AND d4_.wpomOrder_dbID = v2_.dbID AND w0_.orderCreatorListXMLRow_dbID IN (SELECT o8_.dbID FROM OrderCreatorListXMLRow o8_ INNER JOIN OrderCreatorListXML o9_ ON o8_.orderCreatorListXML_dbID = o9_.dbID LEFT JOIN VersionedDataObject v10_ ON o9_.dbID = v10_.dbID INNER JOIN InputComponentDataVersion i11_ ON v10_.inputComponentDataVersion_dbID = i11_.dbID
 WHERE EXISTS (SELECT 1 FROM DataVersion_inputComponentDataVersions d6_ INNER JOIN DataVersion d7_ ON d6_.inputComponentDataVersion_dbID = d7_.dbID WHERE d6_.dataVersion_dbID = i11_.dbID AND d7_.dbID = '1') AND o8_.ABRECHNUNGSTYP = 'Rechnungen')
 ORDER BY w0_.documentDate ASC

... which introduces ambiguity, because the inheritance is inserted before the second FROM-clause entry is added. Which means, the "first shot" fix I attached will not work for this case.

The solution would have to make sure that this kind of ambiguity on SQL 2003-compliant systems is generally eliminated from the generated queries, by proper use of parantheses in all situations.

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

Note that the second example runs on the patched SQLWalker, which still does not cover the inheritance declaration properly.
Without the patch, it would already produce wrong SQL in the first example, of course.

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

The query shown above needlessly queries the entity XMLDocument, which, fortunately, is no longer needed in this use case. This being fixed, to me it is no blocker bug, but there are cases where inheritance will actually be used in conjunction with multiple from-clause entries, and I am pretty sure such scenarios will arise, so I leave this query here in the comments to illustrate the problem.

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

Increased priority to critical.

Mind you, this bug causes Doctrine to regularly generate broken queries on MySQL. Without my local patch, it would be unusable for my use case.

I believe a fix for this would be crucial. Doctrine absolutely needs to generate SQL 2003 compatible FROM clauses.

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

Attached new patched SQLWalker, now extended to add parantheses around FROM clauses within subqueries. Again, this is prototype quality, but it apparently fixes the problem.

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

Increased priority to blocker.

Now I have a query that relies on multiple FROM-clause argument-list entries, combined with JOIN expressions, that relies on an inheritance join as well. This is the type of query I described in my comment from 01/Mar/11 05:56 PM. In such a case, Doctrine 2 will generate invalid code leading to the following MySQL Server Error:

SQLSTATE[42S22]: Column not found: 1054 Unknown column [...] in 'on clause.

The column mentioned exists, though, MySQL Server just can not properly understand the aliases given, because the generated query is ambiguous, and MySQL Server is smart enough to complain about it.

A quick fix would be to generally move inheritance join expressions past the regular FROM-clause entries, and use proper parantheses around the list of regular (i . e. non-join table-reference) FROM-clause argument-list entries.

Please fix this ASAP. This is fundamental.

Comment by Benjamin Eberlei [ 20/Mar/11 ]

This fails on PostgreSQL aswell, not on SQLite however. I cant run Oracle currently as my machine with that is broken.

The problem here is twofold:

1. Joins generated for inheritance hierachies have to always be wrapped in parenthesis.
2. Support for explicit parenthesis in FROM and JOIN has to be supported.

Support for SQL 2003 is not about magic parenthis work magically for use-case 2, it should just be possible to do:

SELECT p FROM (Doctrine\Tests\Models\Company\CompanyPerson p, Doctrine\Tests\Models\Company\CompanyEmployee s)
JOIN p.spouse s2
WHERE p.spouse = s.id
Comment by Benjamin Eberlei [ 20/Mar/11 ]

It is already possible to do this:

SELECT p FROM Doctrine\Tests\Models\Company\CompanyPerson p
JOIN p.spouse s2, Doctrine\Tests\Models\Company\CompanyEmployee s
WHERE p.spouse = s.id
Comment by Benjamin Eberlei [ 20/Mar/11 ]

Just tested a bit, it is not even possible to do automatic parenthesis around inheritance hierachies as the aliases go out of scope for the WHERE clause, in PostgreSQL there are other scoping errors with your patch. This all has to be explicit, which makes a fix for this more complicated.

Comment by Benjamin Eberlei [ 20/Mar/11 ]

Wrapped SQL Codes new, very annoying that they dont overflow (Jira annoyances)

Comment by Benjamin Eberlei [ 20/Mar/11 ]

Changed back to critical, this is not a blocker, you can always use Native SQL to get around limitations of DQL. Its not pretty, but its not a blocker to usage, given that you can rearrange the FROM and JOIN clauses one of your issues should be solved by existing code, only the inheritance persists (not sure if that not goes away also).

Comment by Daniel Alvarez Arribas [ 20/Mar/11 ]

Thanks for taking care.

This way you should never have to deal with blockers, just by providing a way to directly use PDO, which you always should be able to use directly anyway.

My query is quite complex because I had to replicate certain sections to compensate for the lack of support for CASE expressions. So it would be a pain to translate it to SQL, not even talking of maintaining it. But yes, technically nothing is really a blocker, though it is fair to say that workarounds can be impractical.

I will have a try at the solution you proposed in your comment from 20/Mar/11 05:43 AM. The basic parantheses problem is solved by the local SQLWalker patch. But it does not cover the inheritance join, which gets generated right amid the regular FROM-clause entries, instead of at the end with the other JOIN expressions, thus generating broken SQL.
So a sustainable fix would have to fix the inheritance join problem. My guess is it would help to handle the JOIN expression of the inheritance join the same way as other JOIN expressions, and render the statements for both after the regular FROM-clause entries.

Comment by Benjamin Eberlei [ 20/Mar/11 ]

The complexity of this query does not stem from the select clause, but from the query and matching logic. That is not much more complicated in plain sql than in DQL. The complexity of using NativeSQL over DQL is imho complex fetch join or inheritance scenarios.

I consider something a blocker only if its a bug that has no temporary workaround.

Your SQL Walker patch breaks the testsuite (not the sql generation queries, but real functional tests), so i cannot apply it.

Inheritance i think cannot just be put to the end of all from clauses, i'd rather have explicit mechanisms such as:

FROM (InheritedEntity) a
FROM (InheritedEntity a JOIN a.related b)
FROM (InheritedEntity a, OtherEntity b) JOIN a.related c

I also have to check how JPQL or HQL solves this issue.

Comment by Daniel Alvarez Arribas [ 20/Mar/11 ]

Hey, you have not seen the query yet...

But yes, I agree it would be possible, though annoying, to write any query in plain-SQL.

The "patch" is just a prototype, to illustrate the issue. For me it works. It could be, of course, that it breaks some other feature my application does not use.

As for the inheritance joins, I do not yet understand why they should be handled differently than any other joins. The RDBMS should be agnostic to the reason a join is done, it just knows the basic mechanism, which should be the same.

Comment by Daniel Alvarez Arribas [ 21/Mar/11 ]

Changed affected Version to 2.0.2. Actually, 2.0.3 is affected too, but I cannot select it.

Comment by Daniel Alvarez Arribas [ 21/Mar/11 ]

Same SQLWalker first-shot concept patch, now based on Version 2.0.3

Comment by Daniel Alvarez Arribas [ 21/Mar/11 ]

Ben,

is it possible to just generate the code for the inheritance joins at the end of the FROM clause?

Combined with always adding parantheses around the list of regular FROM clause entries, I believe, this could very well solve the problem. And it could turn out to be just a little manageable change.
There would not be any need for explicitly adding parantheses then, from a user-programmer perspective.

Comment by Daniel Alvarez Arribas [ 22/Mar/11 ]

I uploaded a new SQLWalker.

This is a first shot at handling inheritance joins just like regular joins (generating an expression after the non-join table references, rather than between them). On MySQL 5.0, the patched code seems to generate valid SQL for all the use cases of my application.

Could you please run the unit tests against it, to see if the changes break anything?

Comment by Daniel Alvarez Arribas [ 24/Mar/11 ]

I just gave the patched SQLWalker a try on PostgreSQL 8.4, and it did not work. PostgreSQL would complain about syntax errors, as the parantheses are not expected. I will see later this day if PostgreSQL requires the additional parantheses at all. Maybe on PostgreSQL the queries work fine without the parantheses in the first place. Given that PostgreSQL complains about syntax errors when provided with the additional parantheses, this is to be expected, but I will let you know as soon as I know for sure.

Comment by Daniel Alvarez Arribas [ 28/Mar/11 ]

Sorry for the late update. I had to fix a RDBMS-dependent UTF-8 issue in my application before being able to fully test the relevant queries with PostgreSQL

Now that I did, PostgreSQL seems to have the same problem like MySQL Server.

Take this DQL query for example:

SELECT vendorListXMLRow
  FROM \persistentData\model\import\vendorListXML\VendorListXMLRow vendorListXMLRow,
       \persistentData\model\import\parameterListXML\ParameterListXMLRow parameterListXMLRow
  JOIN vendorListXMLRow.vendorListXML vendorListXML
  JOIN vendorListXML.inputComponentDataVersion vendorListXMLInputComponentDataVersion
  JOIN parameterListXMLRow.parameterListXML parameterListXML
  JOIN parameterListXML.inputComponentDataVersion parameterListXMLInputComponentDataVersion
  WHERE :dataVersion MEMBER OF vendorListXMLInputComponentDataVersion.dataVersions
    AND vendorListXMLRow.ID = parameterListXMLRow.WERT
    AND :dataVersion MEMBER OF parameterListXMLInputComponentDataVersion.dataVersions
    AND parameterListXMLRow.ID = :parameterID

On PostgreSQL 8.4.7, it will get compiled down to:

SELECT v0_.ID AS ID0, v0_.DEBITORENSAMMELKONTENLISTEN_DATEINAME AS DEBITORENSAMMELKONTENLISTEN_DATEINAME1,
       v0_.RECHNUNGSKONFIGURATIONS_DATEINAME_INLAND AS RECHNUNGSKONFIGURATIONS_DATEINAME_INLAND2,
       v0_.RECHNUNGSKONFIGURATIONS_DATEINAME_AUSLAND AS RECHNUNGSKONFIGURATIONS_DATEINAME_AUSLAND3,
       v0_.dbID AS dbID4,
       v0_.vendorListXML_dbID AS vendorListXML_dbID5
  FROM VendorListXMLRow v0_, ParameterListXMLRow p1_
 INNER JOIN VendorListXML v2_ ON v0_.vendorListXML_dbID = v2_.dbID
  LEFT JOIN VersionedDataObject v3_ ON v2_.dbID = v3_.dbID
 INNER JOIN InputComponentDataVersion i4_ ON v3_.inputComponentDataVersion_dbID = i4_.dbID
 INNER JOIN ParameterListXML p5_ ON p1_.parameterListXML_dbID = p5_.dbID
  LEFT JOIN VersionedDataObject v6_ ON p5_.dbID = v6_.dbID
 INNER JOIN InputComponentDataVersion i7_ ON v6_.inputComponentDataVersion_dbID = i7_.dbID
 WHERE EXISTS (SELECT 1 FROM DataVersion_inputComponentDataVersions d8_ 
                INNER JOIN DataVersion d9_ ON d8_.inputComponentDataVersion_dbID = d9_.dbID
                WHERE d8_.dataVersion_dbID = i4_.dbID
                  AND d9_.dbID = $1)
   AND v0_.ID = p1_.WERT
   AND EXISTS (SELECT 1 FROM DataVersion_inputComponentDataVersions d8_
                INNER JOIN DataVersion d9_ ON d8_.inputComponentDataVersion_dbID = d9_.dbID
                WHERE d8_.dataVersion_dbID = i7_.dbID
                  AND d9_.dbID = $2)
   AND p1_.ID = $3 LIMIT 

... which will not work, because v0 can not be referenced by the first JOIN expression.

Here is the log:

2011-03-28 12:17:03 CEST ERROR:  invalid reference to FROM-clause entry for table "v0_" at character 440
2011-03-28 12:17:03 CEST HINT:  There is an entry for table "v0_", but it cannot be referenced from this part of the query.
2011-03-28 12:17:03 CEST STATEMENT: [same as above]

Adding parantheses around the non-join FROM clause argument-list entries the way it worked for MySQL 5.0 will not work here. PostgreSQL will complain about a syntax error:

ERROR:  syntax error at or near ", " LINE 6:    FROM (VendorListXMLRow v0_, ParameterListXMLRow p1_)

So the bottom line is that the problem does exist on PostgreSQL as well, but the quick fix that apparently worked for MySQL 5.0 will not work here.

Comment by Daniel Alvarez Arribas [ 28/Mar/11 ]

Note that PostgreSQL claims very specific compliance with the relevant packages of the SQL 2008 standard, while the MySQL documentation is, as usual, broadly inaccurate and amateurish about that topic. It does not matter here, if version 5.0 or 5.1 of MySQL is concerned.

http://www.postgresql.org/docs/8.4/static/features.html

http://dev.mysql.com/doc/refman/5.0/en/standards.html

When in doubt, I would suggest to simply aim for SQL 2008 compliance (as later versions of the standard supersede the older ones), so as to not risk optimizing for MySQL peculiarities rather than for general compatibility. This should make it possible to define a single level of compliance, independent of the specific RDBMS.

Comment by Daniel Alvarez Arribas [ 28/Mar/11 ]

Removed long PostgreSQL log line...

Comment by Daniel Alvarez Arribas [ 02/Apr/11 ]

Are you still with me?

Comment by Benjamin Eberlei [ 02/Apr/11 ]

I am just super busy right now. Doing my best..

Comment by Daniel Alvarez Arribas [ 03/Apr/11 ]

OK!

Comment by Benjamin Eberlei [ 03/Apr/11 ]

Hm, just tried a little bit. What about:

diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php
index a14987e..0fb3e80 100644
--- a/lib/Doctrine/ORM/Query/SqlWalker.php
+++ b/lib/Doctrine/ORM/Query/SqlWalker.php
@@ -621,11 +621,15 @@ class SqlWalker implements TreeWalker
             $this->_rootAliases[] = $dqlAlias;
 
             $class = $this->_em->getClassMetadata($rangeDecl->abstractSchemaName);
+            if ($class->isInheritanceTypeJoined()) {
+                $sql .= '(';
+            }
+
             $sql .= $class->getQuotedTableName($this->_platform) . ' '
                   . $this->getSQLTableAlias($class->table['name'], $dqlAlias);
 
             if ($class->isInheritanceTypeJoined()) {
-                $sql .= $this->_generateClassTableInheritanceJoins($class, $dqlAlias);
+                $sql .= $this->_generateClassTableInheritanceJoins($class, $dqlAlias).')';
             }
 
             foreach ($identificationVariableDecl->joinVariableDeclarations as $joinVarDecl) {
Comment by Benjamin Eberlei [ 03/Apr/11 ]

I think this query will work for you without any changes to the SQLWalker:

SELECT vendorListXMLRow
FROM
    \persistentData\model\import\vendorListXML\VendorListXMLRow vendorListXMLRow
        JOIN vendorListXMLRow.vendorListXML vendorListXML
        JOIN vendorListXML.inputComponentDataVersion vendorListXMLInputComponentDataVersion,
    \persistentData\model\import\parameterListXML\ParameterListXMLRow parameterListXMLRow
        JOIN parameterListXMLRow.parameterListXML parameterListXML
        JOIN parameterListXML.inputComponentDataVersion parameterListXMLInputComponentDataVersion
WHERE :dataVersion MEMBER OF vendorListXMLInputComponentDataVersion.dataVersions
 AND vendorListXMLRow.ID = parameterListXMLRow.WERT
 AND :dataVersion MEMBER OF parameterListXMLInputComponentDataVersion.dataVersions
 AND parameterListXMLRow.ID = :parameterID
Comment by Daniel Alvarez Arribas [ 04/Apr/11 ]

Hey thanks, I'll try doing it that way.

Right now everything works fine with the local patch, at least on MySQL 5.0.

As for PostgreSQL, I will give it a run in a spare minute and let you know.

Comment by Benjamin Eberlei [ 31/Jul/11 ]

Any feedback on this issue?

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

I have not yet managed to change and test the queries of the application, because it is a major change affecting lots of complex queries that span literally several dozen pages each (we had to emulate the unsupported CASE statements with conditional logic and joins, which multiplied the lines of code in many queries).
I have postponed changing the queries until next week, when I will upgrade the application to Doctrine 2.1 after finishing some due tasks. Afterwards I will run the application code with changed queries according to the pattern described in your comment above, and let you know. I will give it a try on PostgreSQL then, too. Last time I checked, my local patch did not work on PostgreSQL. I hope the rewritten queries will.

Comment by Benjamin Eberlei [ 06/Aug/11 ]

I think your local patch is not necessary, you have to order the from and join clauses correctly (as required when writing SQL itself). This problem is "handled" by DQL by delegating the error handling to the SQL level as we don't evaluate semantical errors of SQL in DQL.

Comment by Daniel Alvarez Arribas [ 07/Aug/11 ]

Sure, with the latest version it could work that way. I'll try, as I said.

The local SQLWalker patch was just a temporary measure. I hope it will become unnecessary after rewriting the queries the way you proposed.

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

Sorry for the delay. I am now upgrading to Doctrine 2.1 and rewriting the application's queries according to the way you explained. I will let you know about results within the next couple of days, after performing test runs based on the reworked queries.

Comment by Daniel Alvarez Arribas [ 22/Sep/11 ]

I rewrote all queries to match the basic form you showed in your comment from April, 3rd.

Using the basic form

SELECT x
FROM drivingTable1 alias1
JOIN alias1.otherTable1 alias2,
drivingTable 2 alias3
JOIN alias3.otherTable2 alias4
...

the queries now work on MySQL Server without any local modifications of Doctrine 2.

I tested it with MySQL Server version 5.0.51a, and Doctrine version 2.1.1.

So far everything seems to be good.

I will try it on PostgreSQL, too, and let you know about that.

Comment by Daniel Alvarez Arribas [ 29/Sep/11 ]

I tried a complex sample query on PostgreSQL using the same join syntax, and it worked like a charm.

I'll close the issue as fixed.

Thanks a lot.

Comment by Daniel Alvarez Arribas [ 29/Sep/11 ]

Issue closed.

I don't know about the DQL validation part, though. The fact that DQL can or could compile to something that is not valid SQL could be considered symptomatic of a bug by itself. Don't know about the state of that, maybe it's more robust by now.





[DDC-1041] UnitOfWork tryGetById method is always called with the rootEntityName Created: 24/Feb/11  Updated: 04/Mar/11  Resolved: 04/Mar/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0
Fix Version/s: 2.0.2, 2.1
Security Level: All

Type: Bug Priority: Critical
Reporter: Couragier Sébastien Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

LAMP



 Description   

My problem : i have a class table inheritance, with only 3 class, one abstract and two concrete.
says AbstractClass, ConcretClassA and ConcreteClassB
All three are declared with @entity

if i already have in my identity map the ConcretClassA with id = 1
when i do an entityManager->find('ConcreteClassB', 1) the identityMap returns me the ConcretClassA with id = 1
that's not correct !
it should return a null value instead

That's because the entityRepository (and all the other doctrine class) call the UnitOfWork tryGetById with the rootEntityName, which in my case is AbstractClass.
See the first line of the entityRepository's find method :

$this->_em->getUnitOfWork()->tryGetById($id, $this->_class->rootEntityName)

if i change this line to :

$this->_em->getUnitOfWork()->tryGetById($id, $this->_class->name)

the find method return the expected null value.

So, why the UnitOfWork tryGetById method is always called with the rootEntityName ?



 Comments   
Comment by Benjamin Eberlei [ 25/Feb/11 ]

The identity map HAS to work by root entity name.

Otherwise think of an inheritance hierachy A > B. Then both $em>find('A', 1); and $em->find('B', 1); should return the same instance.

If this does not hold you are screwed.

Your problem is more subtle, i am not sure what the expected behavior should be here.

Comment by Couragier Sébastien [ 28/Feb/11 ]

In my sense, the client code should exactly knows the inheritance hierachy, and exactly know what it wants too, so if it asks for an 'A' instance, you can't return a 'B' instance, although A inherit from B.

Comment by Benjamin Eberlei [ 28/Feb/11 ]

I agree with you except for the last sentence part.

If A->B and you query for B with Id 1 it should treturn an A if it exists. But if B->C and A->C then find(A) should only ever return As or Cs never, Bs.

Comment by Couragier Sébastien [ 28/Feb/11 ]

I agree.
Perhaps my problem is more specific to the class table inheritance strategy with an abstract class at the top of it.
Here's my identityMap's dump (with my first comment inheritance example) at the time the problem occurs :

'AbstractClass' =>
array
1 => string 'ConcretClassA'
2 => string 'ConcretClassA'
3 => string 'ConcretClassA'
367 => string 'ConcretClassB'
368 => string 'ConcretClassB'
369 => string 'ConcretClassB'

And, at this time, in my code, i would like to know if the id 1 is a ConcretClassB. If the id 1 is a ConcretClassA, i must throw an exception.
So, how could i test if the id 1 is a ConcretClassB or not, if the find('ConcretClassB', 1) method returns me the ConcretClassA 1 ?

thx for your help

Comment by Benjamin Eberlei [ 28/Feb/11 ]

Cant you just check instanceof?

$a = $em->find('ConcretClassA', $aId);
if ($a instanceof ConcretClassB) {
   throw new Exception();
}
Comment by Couragier Sébastien [ 28/Feb/11 ]

Of course i can.
But i thought Doctrine should already have to do this check internally for us. Because we must now be very careful with the find method's returns...

Nevermind, i don't have all the uses case Doctrine have to handle with inheritance in mind; so if you say it is to the client code to check, and it is a completely normal behavior, then it's okay for me.

Comment by Benjamin Eberlei [ 28/Feb/11 ]

i will change this behavior in the future, i am just making suggestions for you to fix it now. Using instanceof will also be forwards compatible since "null instanceof Class" is always false.

In any case the level of having to be careful is the same, using null instead of an object can get you into troubles aswell.

Comment by Couragier Sébastien [ 03/Mar/11 ]

Perhaps throw a \Doctrine\ORM\EntityNotFoundException would be a better option than return a null value ?

Comment by Benjamin Eberlei [ 04/Mar/11 ]

Fixed.





[DDC-1033] Cloned proxies show unexpected behavior when initialized Created: 14/Feb/11  Updated: 26/Feb/11  Resolved: 26/Feb/11

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

Type: Bug Priority: Critical
Reporter: Karsten Dambekalns Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

When a proxy has been loaded and is cloned before being initialized, it will behave unexpectedly.

_load() in the proxy starts a chain of method calls that end up loading the data and putting it into the proxy being in the identity map inside UoW. Now the registered proxy will be updated, but the cloned copy will of course not be changed - except it will behave as if it was initialized. This leads (at least in my case) to changes not being picked up after merge() has been called.

In my case I could work around this if I could ask the proxy to initialize itself (DDC-733). More transparent would be a __clone() method in the proxy that initializes the proxy. This might also be related to DDC-18.



 Comments   
Comment by Benjamin Eberlei [ 18/Feb/11 ]

This issue is rather tricky, since __clone is called AFTER the actual clone, on the CLONED object. What we need is before the clone on the original object. This is pretty problematic to solve, i have to wrap my head around it.

Comment by Benjamin Eberlei [ 26/Feb/11 ]

Fixed.





[DDC-1026] Doctrine Cache Created: 10/Feb/11  Updated: 25/Feb/11  Resolved: 25/Feb/11

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

Type: Bug Priority: Critical
Reporter: Bertrand Zuchuat Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None

Attachments: Text File AbstractQuery.php.patch     File apctest.tgz     Text File yay-caching-works-again.patch    

 Description   

I find a problem with doctrine cache key.

It use a namespace and key to save the value and never use the namespace to get it.

I checked that on AbstractQuery::getResultCacheId().

AbstractCache::save > use $this>_getNamespacedId($id)



 Comments   
Comment by Benjamin Eberlei [ 12/Feb/11 ]

AbstractQuery::getResultCacheId() does not append the namespace. The Cache functions fetch() and contains() do.

Comment by Alex Woods [ 24/Feb/11 ]

Actually, I think ALL result caching may be broken since the fix for DDC-892 landed. The code is expecting to fetch an array from the cache with an element in it thats key is $id. Presumably, this is to cater for cases where the hash clashes for different ids. However, the query result is not being inserted into the cache in this format!

This patch should fix the issue.

There's still a less serious issue - and that's that if there are two ids with clashing hashes that are being called repeatedly in quick succession, they're going to keep displacing each other from the cache. An alternative patch could bundle both ids them into the same cache entry:

if ($cached === false)
$cached = array();
$cached[$id] = $result;
$cacheDriver->save($id, $cached, $this->_resultCacheTTL);

However, I think displacing is better than running the risk of having a TTL that is too long be applied as the result of a clash!

EDIT: I'm also wondering why $hash isn't used as the cache key. It looks like the intention was that it should be, but it isn't..

Comment by Benjamin Eberlei [ 25/Feb/11 ]

Fixed, the DDC-892 patch was pretty borked. This does now work





[DDC-982] Make SQLWalker::getSQLTableAlias() more unique with dql aliases Created: 13/Jan/11  Updated: 20/Feb/11  Resolved: 20/Feb/11

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

Type: Improvement Priority: Critical
Reporter: Benjamin Eberlei Assignee: Guilherme Blanco
Resolution: Fixed Votes: 0
Labels: None


 Description   

getSqlTableAlias: $tableName .= $dqlAlias;

say there is a guy who has two tables "user" and "users" and he does SELECT * FROM User s



 Comments   
Comment by Guilherme Blanco [ 19/Feb/11 ]

Fixed in trunk

Comment by Benjamin Eberlei [ 20/Feb/11 ]

Reopened, because i cant change variables in a closed vs a resolved ticket anymore.





[DDC-978] Many-To-Many relations are removed after Flush() Created: 12/Jan/11  Updated: 23/Jan/11  Resolved: 23/Jan/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0
Fix Version/s: 2.0.1, 2.1
Security Level: All

Type: Bug Priority: Critical
Reporter: Thomas G. Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 2
Labels: None

Attachments: File sandbox.rar    
Issue Links:
Duplicate
is duplicated by DDC-983 Creating new collection for manyToMan... Resolved

 Description   

Let's say we have three entities: User, Channel, and Log

Every time a User is created or updated, Channels are assigned to a Many-To-Many collection.
This action gets logged in the Log entity.

I have reproduced the bug in the Doctrine sandbox (see attachment). It's a fully working example.
This is a summary:

This works
// Fetch two channels in an array
$channels = .......

// create a new user and assign channels
$user = new User();
$user->setName('FooBar');
$user->setChannels($channels);

//save the user
$em->persist($user);
$em->flush();

// log it
$log = new Log();
$log->setMessage('User created with two channels');
$log->setItem($user);

$em->persist($log);
$em->flush();
This also works
// Fetch two channels in an array
$channels = .......

// fetch an existing user, *change something to the user*, and assign channels
$user = .............
$user->setName('Gaz');
$user->setChannels($channels);

//save the user
$em->persist($user);
$em->flush();

// log it
$log = new Log();
$log->setMessage('User created with two channels');
$log->setItem($user);

$em->persist($log);
$em->flush();
This does not work (channels are removed)
// Fetch two channels in an array
$channels = .......

// fetch an existing user and only assign channels, change nothing else
$user = .............
$user->setChannels($channels);

//save the user
$em->persist($user);
$em->flush();

// log it
$log = new Log();
$log->setMessage('User created with two channels');
$log->setItem($user);

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

This last piece of code generates following SQL code (summarized):

DELETE FROM user_channels WHERE userId = 1
INSERT INTO user_channels (userId, channelId) VALUES (1, 2);
DELETE FROM user_channels WHERE userId = 1

If you remove the $em->flush() after $em->persist($user); in the last example, the code works (channels are persisted).

I did not have this problem with Doctrine2 Alpha4.



 Comments   
Comment by Benjamin Eberlei [ 12/Jan/11 ]

What do you do in "setChannels"? Do you completly overwrite the previous content of the association variable "User::$channels" ?

Comment by Thomas G. [ 12/Jan/11 ]

I have reproduced the bug in a fully working example. See attachment. Just read instructions in comment and execute each step seperately.

But yes, I overwrite the previous content of the association variable "User::$channels" with a Doctrine ArrayCollection.

User Entity
/** @Entity @Table(name="users") */
class User
{
    /**
     * @Id @Column(type="integer")
     * @GeneratedValue(strategy="AUTO")
     */
    private $id;
    /** @Column(type="string", length=50) */
    private $name;

    /**
     * @ManyToMany(targetEntity="Channel")
     * @JoinTable(name="users_channels",
     *          joinColumns={@JoinColumn(name="userId",
                referencedColumnName="id")},
     *          inverseJoinColumns={@JoinColumn(name="channelId",
     *          referencedColumnName="id")}
     *      )
     * @var ArrayCollection
     */
    protected $channels;

    public function __construct(){
        $this->channels = new \Doctrine\Common\Collections\ArrayCollection();
    }

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

    public function getName()
    {
        return $this->name;
    }

    public function setName($name)
    {
        $this->name = $name;
    }

    public function getChannels() {
        return $this->channels;
    }

    public function setChannels($channels) {
        $channels =  new \Doctrine\Common\Collections\ArrayCollection($channels);
       
        $this->channels = $channels;
    }
}
Comment by Benjamin Eberlei [ 23/Jan/11 ]

Fixed.





[DDC-973] Undefined indexes of $tableColumn in MySqlSchemaManager.php Created: 09/Jan/11  Updated: 31/Jul/11  Resolved: 31/Jul/11

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

Type: Bug Priority: Critical
Reporter: Michael Spiller Assignee: Benjamin Eberlei
Resolution: Invalid Votes: 0
Labels: None
Environment:

PHP Version 6.0.0-dev
System Linux infong 2.4 #1 SMP Wed Nov 4 21:12:12 UTC 2009 i686 GNU/Linux
Build Date Mar 12 2010 17:51:30

MySQL version 5.0.91-log



 Description   

I wanna setup my Doctrine system by running the following PHP code:

require_once 'config.inc.php';
$schemaTool = new \Doctrine\ORM\Tools\SchemaTool($em);

$metadata = $em->getMetadataFactory()->getAllMetadata();

$schemaTool->updateSchema($metadata);

But I get the following error:

Notice: Undefined index: type in XXX/Doctrine/DBAL/Schema/MySqlSchemaManager.php on line 90

Fatal error: Uncaught exception 'Doctrine\DBAL\DBALException' with message 'Unknown database type requested, Doctrine\DBAL\Platforms\MySqlPlatform may not support it.' in XXX/Doctrine/DBAL/Platforms/AbstractPlatform.php:192 Stack trace: #0 XXX/Doctrine/DBAL/Schema/MySqlSchemaManager.php(109): Doctrine\DBAL\Platforms\AbstractPlatform->getDoctrineTypeMapping(false) #1 XXX/Doctrine/DBAL/Schema/AbstractSchemaManager.php(624): Doctrine\DBAL\Schema\MySqlSchemaManager->_getPortableTableColumnDefinition(Array) #2 XXX/Doctrine/DBAL/Schema/AbstractSchemaManager.php(152): Doctrine\DBAL\Schema\AbstractSchemaManager->_getPortableTableColumnList(Array) #3 XXX/Doctrine/DBAL/Schema/AbstractSchemaManager.php(222): Doctrine\DBAL\Schem in XXX/Doctrine/DBAL/Platforms/AbstractPlatform.php on line 192

I edited MySqlSchemaManager.php by adding print_r($tableColumn); just behind line 90, so the code looks like:

$tableColumn = array_change_key_case($tableColumn, CASE_LOWER);

$dbType = strtolower($tableColumn['type']);
print_r($tableColumn);
$dbType = strtok($dbType, '(), ');

and PHP returns the values of the array correctly:

Array
(
[field] = ar_namespace
[type] = int(11)
[null] = NO
[key] = MUL
[default] = 0
[extra] =

)

I also tried echo $tableColumn['type']; without success (result is an additional "Notice: Undefined index: type")



 Comments   
Comment by Benjamin Eberlei [ 23/Jan/11 ]

Can you verify the same fails on PHP 5.3.*? This seems very weird having the key in $tableColumn print_r and direct access failing. I can't explain it.

Why are you using php 6-dev anyways? It has been squased and deleted several months ago already.

Comment by Benjamin Eberlei [ 31/Jul/11 ]

No feedback was given on this issue, closing.





Several features to batch eager selects more efficently (DDC-952)

[DDC-963] @OneToOne inverse side executes queries even if object is in IdentityMap Created: 31/Dec/10  Updated: 16/Mar/11  Resolved: 16/Mar/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0, Git Master
Fix Version/s: 2.1
Security Level: All

Type: Sub-task Priority: Critical
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Comments   
Comment by Benjamin Eberlei [ 16/Mar/11 ]

Merged





[DDC-942] Query getSingleResult throws inappropiate exceptions. Created: 17/Dec/10  Updated: 18/Jan/11  Resolved: 17/Dec/10

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0-ALPHA2, 2.0-ALPHA3, 2.0-ALPHA4, 2.0-BETA1, 2.0-BETA2, 2.0-BETA3, 2.0-BETA4, 2.0-RC1, 2.0-RC2
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Critical
Reporter: Henrik Bjornskov Assignee: Roman S. Borschel
Resolution: Invalid Votes: 0
Labels: None

Sub-Tasks:
Key
Summary
Type
Status
Assignee
DDC-991 Add method "getFirstResult()" that re... Sub-task Resolved Benjamin Eberlei  

 Description   

Currently when using the Query object or QueryBuilder there is no easy way to get the first found result with doing a lot of work. The method that seems to be for this purpose is getSingleResult but it throws an exception if no records are found and if there is more than one record found another Exception is thrown. This behavior is different than the ODM\MongoDB where null is returned.



 Comments   
Comment by Roman S. Borschel [ 17/Dec/10 ]
$items = $q->getResult();
$item = $items[0]; // if you're sure there is one...
// php 5.4?
$item = $q->getResult()[0];

The strict behavior of getSingleResult() is correct and desired. See the API documentation. It is for the cases where you know you want a single result and there is exactly a single result, and where everything else is an error. Getting the first object of a list of 0..* results is a different use-case and easily achieved as shown above.

ps. I don't really care how it is in the ODM as this behavior has been specified in the ORM long before that. Returning null in that case is definitely not a good thing to do imho.

Comment by Lukas Kahwe [ 12/Jan/11 ]

well .. there is also a use case for getting a single entity or null without an exception. note the key here is that i do not know that there will be a result and that my code doesnt explode if there is no result. as a result most of my repositories end up having a method for this purpose.

protected function getOneResult(\Doctrine\ORM\Query $query)

{ $result = $query->getResult(); return isset($result[0]) ? $result[0] : null; }




[DDC-933] EntityManager#lock doesn't work with Class Table Inheritance Created: 14/Dec/10  Updated: 14/Dec/10  Resolved: 14/Dec/10

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

Type: Bug Priority: Critical
Reporter: Alex Bogomazov Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

It produces a notice "E_NOTICE Undefined variable: idColumns Doctrine\ORM\Persisters\JoinedSubclassPersister.php : 366" and results in an incorrect SQL



 Comments   
Comment by Benjamin Eberlei [ 14/Dec/10 ]

Fixed





[DDC-921] QueryBuilder: Defining a "WHERE IN (...)" constraint using QueryBuilder::expr()->in() doesn't allow parameter binding for array of values Created: 09/Dec/10  Updated: 10/Dec/10  Resolved: 10/Dec/10

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

Type: Bug Priority: Critical
Reporter: Markus Wößner Assignee: Benjamin Eberlei
Resolution: Won't Fix Votes: 0
Labels: None


 Description   

Following statement issues Doctrine\ORM\Query\QueryException:

$qb = new Doctrine\ORM\QueryBuilder($em);
$qb
->select('u')
->from('Entities\User', 'u')
>where($qb>expr()->in('u.name', array('?1', '?2')))
->setParameters(array(1 => 'Hans', 2 => 'Lieselotte'))
>getQuery()>execute();

Doctrine\ORM\Query\QueryException: "Invalid parameter number: number of bound variables does not match number of tokens."

$qb->getDql() will return "SELECT u FROM Entities\User u WHERE u.name IN('?1', '?2')"
As you can see placeholder variables are quoted due to Doctrine\ORM\Query\Expr::in($x, $y) which expects $y to be an array of Expr\Literal instances. Otherwise it will quote given strings. I can't think that doing something like...

$qb->where($qb->expr()->in('u.name', array(new Expr\Literal('?1'), new Expr\Literal('?2'))))

... is very convenient syntax. Is it?



 Comments   
Comment by Benjamin Eberlei [ 10/Dec/10 ]

You are supposed to put real values in there. There is currently no support for variable parameter lists in combination with IN. You would have to build these kind of queries using a helper function.





[DDC-918] Remove UnitOfWork->flush() in Query->doExecute() Created: 08/Dec/10  Updated: 10/Dec/10  Resolved: 10/Dec/10

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

Type: Improvement Priority: Critical
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

We should remove UnitOfWork->flush() inside the Query class and document clearly the adverse effects that can happen.

Its much better peformance wise this way around and people shouldn't get into trouble.



 Comments   
Comment by Benjamin Eberlei [ 10/Dec/10 ]

Changed and noted in the new ReST branch of the docs that will go live before release.





[DDC-892] Caches can potentially return false positives due to use of MD5 hash codes as keys. A classic. Created: 25/Nov/10  Updated: 23/Jan/11  Resolved: 23/Jan/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0-BETA4
Fix Version/s: 2.0.1, 2.1
Security Level: All

Type: Bug Priority: Critical
Reporter: Daniel Alvarez Arribas Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

I was just checking the execution path for efficiency and bumped into this block of code in /Doctrine/ORM/AbstracQuery.php,
starting on line 560:

protected function _getResultCacheId()
{
if ($this->_resultCacheId)

{ return $this->_resultCacheId; }

else

{ $sql = $this->getSql(); ksort($this->_hints); return md5(implode(";", (array)$sql) . var_export($this->_params, true) . var_export($this->_hints, true)."&hydrationMode=".$this->_hydrationMode); }

}

Of course, MD5 hashes can never be guaranteed to be unique, so this block of the doExecute-Method
starting on line 508 can return false positives and thus break the user's assumptions about the ORM's behavior:

// Check result cache
if ($this->_useResultCache && $cacheDriver = $this->getResultCacheDriver()) {
$id = $this->_getResultCacheId();
$cached = $this->_expireResultCache ? false : $cacheDriver->fetch($id);

if ($cached === false)

{ // Cache miss. $stmt = $this->_doExecute(); $result = $this->_em->getHydrator($this->_hydrationMode)->hydrateAll( $stmt, $this->_resultSetMapping, $this->_hints ); $cacheDriver->save($id, $result, $this->_resultCacheTTL); return $result; }

else

{ // Cache hit. return $cached; }

}

It is not likely to happen, but possible. Rely on it a couple of million times in a production system, and one day, eventually, it will fail
and hell will break loose.

I think it is prohibitive to try to save memory by giving up correctness. If your program does not work, it's simply broken and there is no need to tune it unless you fix it functionally.

The only safe solution would be to use a non-lossy hash (i. e. compression) method, if any. Plain query text would do fine too.

Unless you expect the user to anticipate false positives, i. e.



 Comments   
Comment by Daniel Alvarez Arribas [ 25/Dec/10 ]

Has anyone taken note of this one?

As it seems, this critical bug has been sitting here for a month, untouched, and apparently even made it into the final release.

I would offer to fix it myself, but as the fix would consist in removing just one or two MD5 hash method calls, and it would probably have to be validated anyway by a core developer, there is actually not much technical effort I could save you.

Just a reminder, thanks for your time.

Comment by Benjamin Eberlei [ 27/Dec/10 ]

The problem is rather that cache keys have a limited length depending on the cache driver.I know that Memcache limits at 255, have to look at the others.

Plain Text is not a solution, but we could build a range of several md5 or sha1 hashes to reduce the risk of false/positives even more.

Comment by Daniel Alvarez Arribas [ 29/Dec/10 ]

Hey Ben,

thanks for taking care.

I see the point about the length limitation. Still, I believe is a bad thing to subject correctness to probability considerations. Merely making it more unlikely to happen would only procrastinate a definite solution. Staying with a solution that relies on hash values being unique, is gambling with the probability of software systems malfunctioning randomly for no apparent reason, which is not a desirable outcome.

I figured out an alternate approach that IMO solves the length limit issue, while, to my knowledge, being correct. This is my first shot at it. But right now I do not see why this, or something like it, should not be feasible.

You could keep on indexing by MD5 hash value (just to guarantee an upper bound on the key length and circumvent the limits regarding the maximum key length). I think MD5 does that part quite well. But instead of just storing the value, store a map, mapping all of the original full-length keys that resolve to that common MD5 hash value to their individual values. In almost all but a few very rare cases, this map will have exactly one entry. Therefore in almost all cases, all that is retrieved from the cache is the value, plus the original key, enclosed in a map wrapper object. Needless to say, this map can be optimized for one entry. It could even be a list, with only a few bytes overhead. This solution would be almost as fast for read accesses as the most naïve cache implementation, but still work in cases where keys resolve to the same hash value.

The details are easy:

Fetching: Fetch the cache entry (the map) by the key's MD5 hash value. Then, look the correct value up in the map using the full-length key. Remember this is not any expensive operation. The map contains almost always exactly one value.

Creating: Fetch the cache entry (the map) by the key's MD5 hash value. If there is no cache entry at all, create a new map with a single entry in it and store it into the cache. If there is an entry, get the map, add the new entry to it using the full-length key and the value, and store the map back into the cache using the key's MD5 hash value. Adding a value to the map would also replace any existing entry for the full-length key in case it is already present in the map.

Deleting: Fetch the cache entry (the map) by the key's MD5 hash value. Then, use the full-length key to delete the corresponding value from the map. If the map is empty after removing the entry (and it will be almost always), delete the whole cache entry using the key's MD5 hash value.

This technique is correct always, and gives almost no overhead for reads. For writes and deletes, you have to fetch first, so there is an overhead, but right now I can't come up with anything faster
that isn't broken.

An optimization would be implementing an additional direct full-key mapping, too, for those cache providers supporting arbitrary length keys. This could give slightly better write performance when arbitrary-length keys are supported, as there would not be any map to be read in case of writing and deleting, just a direct cache operation.

Comment by Benjamin Eberlei [ 30/Dec/10 ]

The unhashed key could potentially be very large, which could lead to problems with the value limit of the caches. Plus the unhashed value relies on print_r(), thus on whitespace formatting which i wouldn't call exactly reliable.

We need to find a better solution to fix this

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

As for the size limit on cached values, I think it is an independent problem, because any value size limit applies in any case, whether or not you implement unique keys or not. Currently, it also applies e. g. to query results, for which an upper size limit can not be guaranteed in general. Consequently, a strategy for handling such a limit is required anyway.

The naïve solution for handling the value size limit would be to simply not cache any values with a total size larger than the value size limit of the respective cache. As the value size limit should actually be reasonably large (memcached e.g. has a default limit of 1 MB), and the limitation is inherent to the cache, this should be perfectly plausible, because it is the caches key functionality that imposes the limit, not Doctrine. I believe the naïve solution is on-the-spot here, and would recommend to strictly opt against taking further measures (like splitting cache entries into buckets) to work around the problem. Working around this limit should have been implemented in the respective cache in the first place, not in Doctrine, as it concerns the caches key functionality. IMO the ORM should not duplicate cache functionality, rather use it in a proper way.

But after all, this is an unrelated problem, and it does not affect the point of this bug in any way.

As for the reliance on print_r: If you consider it to be non-deterministic (producing different output formattings for identical objects) it would be broken (possibly by design). That being said, I do not believe print_r() is non-deterministic by design, though the exact workings of it might not be formally specified. The formatting in the return value string should not introduce ambiguity into the representations of otherwise unique values, and neither produce different values for identical objects. As long as these conditions are met, you should be safe using it for generating cache keys. If not, use something that does fit. This is a mere implementation issue, anyway. You could also strip whitespaces (provided this does not affect uniqueness), to eliminate the whitespace factor.

If cache size efficiency of stored values is an issue, you could be well-advised to support compressing cache values (losslessly, of course) as an option.

Comment by Benjamin Eberlei [ 05/Jan/11 ]

Ok, the common recommendation to avoid cache collisions is using a multitude of different hashes and combine them, or use a very large hash.

So the best solution here is probably to switch to a cache key that has "sha1 + md5 + crc32" of the input and if ext/hash is installed use something much more powerful like sha256.

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

That "recommendation" you are referring to might be just the common practice of using a combination of various hash values to increase the accuracy of ensuring data integrity and authenticity (e.g. by providing various different hash values for downloaded files). IMO this practice is feasible only for purposes like those, and can not be relied on if what you want to do is obtain correct results on cache lookups. While a change in hash value means that the file has definitely been modified (compared to the original) it does not imply e. g. that various modified files that have the same hash value have actually the same modified content.

What you are trying to do could be used in situations where a Bloom Filter (http://en.wikipedia.org/wiki/Bloom_filter) could be appropriately used, which is basically such a combination of various hashes. This could perfectly be used to determine whether there is a high chance that a specific value is in the cache. Such information could be useful to optimize disk accesses or costly requests to remote caches. Bloom filters are used e.g. in the Squid Caching HTTP Proxy, but certainly not for keying, rather for cache digests (read: "is it likely that this key is in the cache?"). This is not the case with the Doctrine 2 caches - these should better be 100% reliable.

Increasing the number or size of hash values will just decrease the probability of a crash, but will not ultimately fix the problem (unless you make the hash values include all original information, but that would be pointless in the first place). And that something is unlikely to happen does not mean it will necessarily take a long time to actually happen. It could as well break an application tomorrow.

Seriously, I do not know of any theoretically backed recommendation that tolerates wrong results when correctness is expected. There are a couple of approximation techniques appropriate in situations where false positives are anticipated, but I believe no such technique would be an appropriate solution for your situation, simply because no one expects the programming contract to imply having to anticipate false positives.

But of course, various hashes would still be better than one, though still worth a bug. Personally I would always opt for correctness. Do as you like.

Comment by Benjamin Eberlei [ 23/Jan/11 ]

Implemented separate chaining to avoid hash key collisions.





[DDC-1458] Issue with tracking entity changes Created: 28/Oct/11  Updated: 11/Nov/11  Resolved: 10/Nov/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1, 2.1.2
Fix Version/s: 2.2
Security Level: All

Type: Bug Priority: Critical
Reporter: Maxim Assignee: Alexander
Resolution: Fixed Votes: 0
Labels: None
Environment:

linux/ubuntu, nginx, php-cgi, symfony framework



 Description   

Flushing at point #2 has no effect (outputs int(1)), flushing at point #1 works as expected (outputs int(5)).
this issue comes only when i trying to set boolean value on managed assotiated entity

upd. same issue with datetime properties

/**
 * @ORM\Entity
 */
class TestEntity
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;
    /**
     * @ORM\Column(type="integer")
     */
    protected $value;
    /**
     * @ORM\OneToOne(targetEntity="TestAdditionalEntity", inversedBy="entity", orphanRemoval="true", cascade={"persist", "remove"})
     */
    protected $additional;
}

/**
 * @ORM\Entity
 */
class TestAdditionalEntity
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;
    /**
     * @ORM\OneToOne(targetEntity="TestEntity", mappedBy="additional")
     */
    protected $entity;
    /**
     * @ORM\Column(type="boolean")
     */
    protected $bool;
    
    public function __construct()
    {
        $this->bool = false;
    }
}

$test = new \TestEntity();
$test->setValue(1);
$test->setAdditional(new \TestAdditionalEntity());

$em->persist($test);
$em->flush();
$em->clear();

$test = $em->getRepository('Bundle:TestEntity')->find(1);
$test->setValue(5);

// point #1
$test->getAdditional()->setBool(true);
// point #2

$em->flush();

var_dump($test->getValue());


 Comments   
Comment by Alexander [ 08/Nov/11 ]

Looking into this.

Comment by Benjamin Eberlei [ 09/Nov/11 ]

formatting

Comment by Alexander [ 10/Nov/11 ]

Fixed in master:
https://github.com/doctrine/doctrine2/pull/187

Comment by Benjamin Eberlei [ 11/Nov/11 ]

Merged into 2.1.x





[DDC-1452] ObjectHydrator bug: hydration of entity with self (cyclic) relation through ref entity Created: 24/Oct/11  Updated: 15/Nov/11  Resolved: 14/Nov/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1, 2.1.1, 2.1.2
Fix Version/s: 2.2
Security Level: All

Type: Bug Priority: Critical
Reporter: Piotr Śliwa Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None

Attachments: File DDC1452Test.php     File DDC1452Test.php    

 Description   

ObjectHydrator has bug in hydrate entities with relation to entity of this same class throught reference entity. Example Model:

EntityA

  • id
  • title (string)
  • entitiesB (annotation: @ORM\OneToMany(targetEntity="EntityB", mappedBy="entityAFrom"))

EntityB

  • id
  • entityAFrom (annotation: @ORM\ManyToOne(targetEntity="EntityA", inversedBy="entitiesB"))
  • entityATo (annotation: @ORM\ManyToOne(targetEntity="EntityA"))
  • type (string)

Scenario:

Execution of dql query 'SELECT a, b, ba FROM EntityA AS a LEFT JOIN a.entitiesB AS b LEFT JOIN b.entityATo AS ba' with max results set to "1" and data in database:

EntityATable:
id | title
1 | a
2 | b

EntityBTable:
id | entityAFromId | entityAToId | type
1 | 1 | 2 | type

Resume:

I expected collection of EntityA object (size=1 becouse I set max results to 1) with hydrated entitiesB collection (size=1 becouse in db is only 1 record) and hydrated entityTo object. entitiesB property of entityTo object should be empty PersistCollection (ready to lazy load) but is null...

I can provide TestCase for this issue.



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

Attached a working testcase.

Please put it into tests/Doctrine/Tests/ORM/Functional/Ticket and run:

phpunit --group DDC-1452

Please make that test fail from your perspective, i think it reproduces your test-case exactly.

Comment by Piotr Śliwa [ 29/Oct/11 ]

Ok, I have fixed testcase to situation that I was talking about.

I have hardly debuged this issue, problem is in ObjectHydrator::_getEntity() method. This method delegates to UnitOfWork::createEntity() and passes $hints array. In $hints array, data about fetching associations is stored. In situation when one entity is joined throught two different associations (as in this testcase, first time DDC1452EntityA is used in from clause, second time in join clause) hydrator "minds" that objects from second association have have loaded association that is connecting entities of the same type. In testcase this is "entitiesB" association of "ba" aliased entity. That occurs, becouse $hints['fetched']['Namespace\DDC1452EntityA']['entitiesB'] has already been set on true while hydrating DDC1452EntityA objects from "FROM" clause. If in testcase had not been set limit for results, then this test would have to pass, becouse second object of DDC1452EntityA ($a2) would have to be load propertly as entity from "FROM" clause.

Comment by Benjamin Eberlei [ 29/Oct/11 ]

The explaination makes sense. I will dig into it.

Comment by Benjamin Eberlei [ 14/Nov/11 ]

This is fixed, but only in master. The code change necessary was pretty serious so i dont want to merge it into the stable branch without more people testing it.

Comment by Piotr Śliwa [ 15/Nov/11 ]

Great job, thanks!





[DDC-1440] Doctrine2 is not able to manage correctly a FK based on a unique string which is not a PK on its table Created: 20/Oct/11  Updated: 31/Oct/11  Resolved: 31/Oct/11

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

Type: Bug Priority: Critical
Reporter: Pau Peris Assignee: Benjamin Eberlei
Resolution: Invalid Votes: 0
Labels: None
Environment:

Any GNU/Linux OS (Linux x61090t_05 2.6.32-71.29.1.el6.x86_64 #1 SMP Mon Jun 27 19:49:27 BST 2011 x86_64 x86_64 x86_64 GNU/Linux)


Attachments: File Permission.php     File permission_1308995187.php     File User.php     File user_1308995187.php    

 Description   

Doctrine2 is not able to manage correctly a FK based on a unique string which is not a PK on its table. Tables are created successfully but data is not managed properly. I'm attaching some Entities and Fixture files in order to test it



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

Could you run "doctrine.php orm:validate-schema" ? I think this will give you an error that this is not possible. Doctrine can only work with foreign keys through primary keys. A workaround for this is making doctrine belive that the unique field is the identifier and that the real id field is just a regular field.

Comment by Pau Peris [ 20/Oct/11 ]

Hi, i'm using doctrine2 through symfony2 and it does not provide the command to validate the schema. I think it was removed some time ago. Could you explain a liitle bit how to accomplish your workaround? Right now i've done sme workarounds to avoid that issue but i think it's a feature which is used very often.
Thanks a lot

PD: Entities and fixtures are working fine.

Comment by Benjamin Eberlei [ 27/Oct/11 ]

You can re-add the command by just adding a plain command into your own bundle that extends from doctrines validate schema and extend the "execute" method to inject the EntityManager from the DIC correctly.

Comment by Benjamin Eberlei [ 31/Oct/11 ]

This is an invalid mapping.

You can only map join-columns of associations to primary keys.





[DDC-1436] Problems with identity map on self-referencing Created: 18/Oct/11  Updated: 18/Nov/11  Resolved: 18/Nov/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1.1
Fix Version/s: 2.1.3
Security Level: All

Type: Bug Priority: Critical
Reporter: Konstantin Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

Symfony2



 Description   
/**
 * @Orm\Entity
 * @Orm\Table(name="tt_content")
 */
class Page
{
	/**
	 * @Orm\Id
	 * @Orm\GeneratedValue
	 * @Orm\Column(type="integer", name="id")
	 */
	protected $id;

	/**
	 * @Orm\ManyToOne(targetEntity="Page", inversedBy="children")
	 * @Orm\JoinColumn(name="pid", referencedColumnName="id")
	 */
	protected $parent;

	/** @Orm\OneToMany(targetEntity="Page", mappedBy="parent") */
	protected $children;

	/** @Orm\Column(name="page_title") */
	protected $title;
}

$id = 5;

// step 1 
$page = $this
	->getEntityManager('read')
	->createQuery('
		SELECT p, parent
		FROM OloloContentBundle:Page p
			LEFT JOIN p.parent parent
		WHERE p.id = :id
	')
	->setParameter('id', $id)
	->getOneOrNullResult();

// step 2
$page = $this->getEntityManager('read')->find('OloloContentBundle:Page', $id);
var_dump($page->getParent()->getParent()); // expected instance of Page, but got null

When I added one more fetch join for parent then I got Page.



 Comments   
Comment by Benjamin Eberlei [ 14/Nov/11 ]

Can you test against master again? I made a fix in context of DDC-1452 that i think could solve this issue.

Comment by Konstantin [ 15/Nov/11 ]

I will do it

Comment by Konstantin [ 15/Nov/11 ]

I cann't run master branch on current env (Symfony 2.0.2).

MappingException: The association mapping 'eventArea' misses the 'targetEntity' attribute, but targetEntity present. Can you merge fix into 2.1.x branch?

Comment by Benjamin Eberlei [ 18/Nov/11 ]

I am not sure this fix is mergable in 2.1, also it is a rather complex change that i don't want to merge back to the stable branch for stability reasons.

Let me try to reproduce this in a test and then go further from there.

Comment by Benjamin Eberlei [ 18/Nov/11 ]

DDC-1452 is indeed the same bug as this one and the fix works.

Comment by Benjamin Eberlei [ 18/Nov/11 ]

I cant merge this as with the latest refactorings it gives hundrets of conflicts, but will re-apply manually.

Comment by Benjamin Eberlei [ 18/Nov/11 ]

Backported and fixed in 2.1.x

Comment by Konstantin [ 18/Nov/11 ]

Thank you very much, Benjamin!





[DDC-1414] UnitOfWork#getCommitOrder() does not add dependencies for all related classes Created: 11/Oct/11  Updated: 15/Oct/11  Resolved: 15/Oct/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1.2, Git Master
Fix Version/s: 2.1.3
Security Level: All

Type: Bug Priority: Critical
Reporter: Petri Mahanen Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

All



 Description   

getCommitOrder() does not add dependencies for all related classes. This causes database-level exceptions in certain cases, as insertion order can be calculated incorrectly, and foreign key constraints fail.

An example case in pseudocode:

A: ManyToOne to B, nullable=true
B: ManyToOne to C, nullable=false
C: no owning relations

a = new A()
em->persist(a)
em->flush()     // does CommitOrderCalculator->addClass(B), but does not add B's dependency to C

c = new C()
b = new B(c)

em->persist(c)
em->persist(b)
em->flush()     // CommitOrderCalculator->hasClass(B) == true, dependencies not added, foreign key constraint fails

Suggested fix against master:

diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php
index ea516f3..991acac 100644
--- a/lib/Doctrine/ORM/UnitOfWork.php
+++ b/lib/Doctrine/ORM/UnitOfWork.php
@@ -853,6 +853,7 @@ class UnitOfWork implements PropertyChangedListener
                     $targetClass = $this->em->getClassMetadata($assoc['targetEntity']);
                     if ( ! $calc->hasClass($targetClass->name)) {
                         $calc->addClass($targetClass);
+                        $newNodes[] = $targetClass;
                     }
                     $calc->addDependency($targetClass, $class);
                     // If the target class has mapped subclasses,

This $newNodes[] push is done for all new classes in $entityChangeSet (above) and $targetClass->subClasses (below), but not for $targetClass itself. I'm assuming this is a bug, not by design.



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

Fixed.





[DDC-1402] Huge performance leak in SingleTablePersister Created: 04/Oct/11  Updated: 10/Oct/11  Resolved: 10/Oct/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1, 2.1.1, 2.1.2
Fix Version/s: 2.1.3
Security Level: All

Type: Bug Priority: Critical
Reporter: Sylvain Bernier Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None

Attachments: Text File doctrine-orm-2.1.0-SingleTablePersister.patch    

 Description   

This code :

/**
 * @Entity
 * @InheritanceType("SINGLE_TABLE")
 * @DiscriminatorColumn(name="discr", type="string")
 * @DiscriminatorMap({"person" = "Person", "employee" = "Employee"})
 */
class Person
{
    /** @Id @Column(type="integer") */ private $id;
}

/**
 * @Entity
 */
class Employee extends Person
{
    /** @Column(type="integer") */ private $a;
    /** @Column(type="integer") */ private $b;
    /** @Column(type="integer") */ private $c;
    /** @Column(type="integer") */ private $d;
    /** @Column(type="integer") */ private $e;
    /** @Column(type="integer") */ private $f;
    /** @Column(type="integer") */ private $g;
    /** @Column(type="integer") */ private $h;
}

foreach (range(0, 20) as $i) {
    $time = microtime(true);
    foreach (range(1, 100) as $j) {
        $id = ($i * 100) + $j;
        $entityManager->find('Person', $id);
    }
    printf("%4d ==> %f\n", $id, microtime(true) - $time);
}

Will output:

 100 ==> 0.461275
 200 ==> 1.128404
 300 ==> 1.823122
 400 ==> 2.521054
 500 ==> 3.232034
 600 ==> 3.950081
 700 ==> 4.648849
 800 ==> 5.380236
 900 ==> 6.080108
1000 ==> 6.807214
1100 ==> 7.519942
1200 ==> 8.238971
1300 ==> 8.951686
1400 ==> 9.648996
1500 ==> 10.370053
1600 ==> 11.069523
1700 ==> 11.791530
1800 ==> 12.481427
1900 ==> 13.190570
2000 ==> 13.902810
2100 ==> 14.671100

With the first and last SELECT queries as:

SELECT t0.id AS id1, discr, t0.a AS a2, t0.b AS b3, t0.c AS c4, t0.d AS d5, t0.e AS e6, t0.f AS f7, t0.g AS g8, t0.h AS h9 FROM Person t0 WHERE t0.id = 1 AND t0.discr IN ('person', 'employee')

...

SELECT t0.id AS id1, discr, t0.a AS a16794, t0.b AS b16795, t0.c AS c16796, t0.d AS d16797, t0.e AS e16798, t0.f AS f16799, t0.g AS g16800, t0.h AS h16801 FROM Person t0 WHERE t0.id = 2100 AND t0.discr IN ('person', 'employee')

Notes:

  • Last 100 SELECT queries take more than 14 seconds to execute! (table is empty)
  • Filed as a bug because a real life scenario caused major performance leak and memory usage when attempting to do 6000 calls to find().

Analysis:

  1. Calls to SingleTablePersister::_getSelectColumnListSQL() do not use BasicEntityPersister::$_selectColumnListSql
  2. This generates a lot of calls to _getSelectColumnSQL() (See last SELECT query with alias counter up to 16800)
  3. This generates a lot of calls to addFieldResult()
  4. And this fills up pretty quickly ResultSetMapping::$declaringClasses
  5. To finally put a huge burden on SimpleObjectHydrator::_prepare() where it iterates on $this->_rsm->declaringClasses and calls getClassMetadata() for each one!
  6. And all that, including _prepare(), is executed for each SELECT, even though none of them find any result (the table is empty).

I fixed my project using the following patch:

diff --git a/doctrine-orm/Doctrine/ORM/Persisters/SingleTablePersister.php b/doctrine-orm/Doctrine/ORM/Persisters/SingleTablePersister.php
index f910a8e..78b27cb 100644
--- a/doctrine-orm/Doctrine/ORM/Persisters/SingleTablePersister.php
+++ b/doctrine-orm/Doctrine/ORM/Persisters/SingleTablePersister.php
@@ -41,6 +41,15 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
     /** {@inheritdoc} */
     protected function _getSelectColumnListSQL()
     {
+        /** @see BasicEntityPersister::_getSelectColumnListSQL() */
+        if ($this->_selectColumnListSql !== null) {
+            return $this->_selectColumnListSql;
+        }
+
+        #####
+        #####
+        #####
+
         $columnList = parent::_getSelectColumnListSQL();
 
         // Append discriminator column
@@ -74,7 +83,13 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
             }
         }
 
-        return $columnList;
+        #####
+        #####
+        #####
+
+        /** @see BasicEntityPersister::_getSelectColumnListSQL() */
+        $this->_selectColumnListSql = $columnList;
+        return $this->_selectColumnListSql;
     }
 
     /** {@inheritdoc} */

I do not know if this patch is safe for everybody.

But, well, you can easily reproduce the problem and analyze the phenomenon using a profiler on the sample code provided.

Thanks for this great piece of software. I hope this will help you find and fix the bug.



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

good catch, thank you very much!

fixed and merged back into 2.1.x





[DDC-1396] [APC Cache] "clear-cache" commands do not work with cli Created: 27/Sep/11  Updated: 03/Oct/11  Resolved: 03/Oct/11

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

Type: Bug Priority: Critical
Reporter: Jérôme Forêt Assignee: Guilherme Blanco
Resolution: Fixed Votes: 0
Labels: None
Environment:

in php.ini
apc.enable_cli = 1



 Description   

Commands for clear-cache:result, clear-cache:query, clear-cache:metadata do not work with cli and APC Cache

Revert some correction not tested by guilhermeblanco by adding

if ($cacheDriver instanceof \Doctrine\Common\Cache\ApcCache)
{
    throw new \LogicException("Cannot clear APC Cache from Console, its shared in the Webserver memory and not accessible from the CLI.");
}


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

Fixed in https://github.com/doctrine/doctrine2/commit/8efae0b232210b27200f2709e7fcb24c7f02c5de

Thanks for the report. =)





[DDC-1367] Include path not passed to ClassLoader when autoloading Doctrine library from directory Created: 08/Sep/11  Updated: 25/Sep/11  Resolved: 25/Sep/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Tools
Affects Version/s: 2.1, 2.1.1, Git Master
Fix Version/s: 2.1.2
Security Level: All

Type: Bug Priority: Critical
Reporter: Lucas Brown Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

Found while trying to write a Doctrine 2.1 module for Kohana.



 Description   

The bug is in ORM\Tools\Setup.php in the function registerAutoloadDirectory($directory), specificially the following line:

$loader = new ClassLoader("Doctrine");

Which should actually be:

$loader = new ClassLoader("Doctrine", $directory);

As it stands the actual directory location is not being passed to the ClassLoader while attempting to autoload the Doctrine from that specified directory. Under certain circumstances this causes loading to completely fail (although in cases where this function is being called from a parent directory to Doctrine this seems to go unnoticed - perhaps why this was not picked up sooner?)



 Comments   
Comment by Benjamin Eberlei [ 25/Sep/11 ]

Fixed and merged into 2.1.x





[DDC-1346] Error when referencing aliased sub-select in where clause Created: 24/Aug/11  Updated: 31/Oct/11  Resolved: 05/Sep/11

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

Type: Bug Priority: Critical
Reporter: Glen Ainscow Assignee: Guilherme Blanco
Resolution: Fixed Votes: 0
Labels: None


 Description   

Example:

$qb->addSelect('(SELECT COUNT(tp2) FROM TeamPlayer tp2 WHERE tp2.team = t) AS test');

$qb->andWhere('test > 3');

[Semantical Error] line 0, col 186 near 'test > 3 ORDER': Error: 'test' does not point to a Class.



 Comments   
Comment by Benjamin Eberlei [ 27/Aug/11 ]

Assigned to Guilherme

Comment by Guilherme Blanco [ 05/Sep/11 ]

Fixed since commit https://github.com/doctrine/doctrine2/commit/6bbf2d9da35aa8ce500f26d671a135a00870e33a

Comment by Benjamin Eberlei [ 25/Sep/11 ]

Merged into 2.1

Comment by Benjamin Eberlei [ 31/Oct/11 ]

Merged into 2.1.x





[DDC-1300] Can't fetch entities from IdentityMap when using a foreign keys as identifiers Created: 27/Jul/11  Updated: 06/Aug/11  Resolved: 06/Aug/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1
Fix Version/s: 2.1.1

Type: Bug Priority: Critical
Reporter: Van Hauwaert Bert Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

Given the follow SQL structure:

CREATE TABLE `foo` (
  `fooID` int(11) NOT NULL AUTO_INCREMENT,
  `fooReference` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`fooID`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='module=bug';

CREATE TABLE `fooLocale` (
  `fooID` int(11) NOT NULL,
  `locale` varchar(5) NOT NULL DEFAULT '',
  `title` varchar(150) DEFAULT NULL,
  PRIMARY KEY (`fooID`,`locale`),
  KEY `fk_foo2` (`fooID`),
  CONSTRAINT `fk_table1_foo2` FOREIGN KEY (`fooID`) REFERENCES `foo` (`fooID`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='module=bug';

INSERT INTO `foo` (`fooID`, `fooReference`)
VALUES
	(1, 'foo1');

INSERT INTO `fooLocale` (`fooID`, `locale`, `title`)
VALUES
	(1, 'en_GB', 'Foo title test');

and the following models:

use Doctrine\ORM\Mapping as ORM;

/**
 * Model for foo
 *
 * @category Application
 * @package Bug
 * @subpackage Model
 * @ORM\Table(name="foo")
 * @ORM\Entity
 */
class Bug_Model_Foo
{
	/**
	 * @var integer fooID
	 * @ORM\Column(name="fooID", type="integer", nullable=false)
	 * @ORM\GeneratedValue(strategy="IDENTITY")
	 * @ORM\Id
	 */
	protected $_fooID = null;

	/**
	 * @var string fooReference
	 * @ORM\Column(name="fooReference", type="string", nullable=true, length=45)
	 */
	protected $_fooReference = null;

	/**
	 * @ORM\OneToMany(targetEntity="Bug_Model_FooLocale", mappedBy="_foo",
	 * cascade={"persist"})
	 */
	protected $_fooLocaleRefFoo = null;

	/**
	 * Constructor
	 *
	 * @param array|Zend_Config|null $options
	 * @return Bug_Model_Foo
	 */
	public function __construct($options = null)
	{
		$this->_fooLocaleRefFoo = new \Doctrine\Common\Collections\ArrayCollection();
	}

}
use Doctrine\ORM\Mapping as ORM;

/**
 * Model for fooLocale
 *
 * @category Application
 * @package Bug
 * @subpackage Model
 * @ORM\Table(name="fooLocale")
 * @ORM\Entity
 */
class Bug_Model_FooLocale
{
	/**
	 * @ORM\ManyToOne(targetEntity="Bug_Model_Foo")
	 * @ORM\JoinColumn(name="fooID", referencedColumnName="fooID")
	 * @ORM\Id
	 */
	protected $_foo = null;

	/**
	 * @var string locale
	 * @ORM\Column(name="locale", type="string", nullable=false, length=5)
	 * @ORM\Id
	 */
	protected $_locale = null;

	/**
	 * @var string title
	 * @ORM\Column(name="title", type="string", nullable=true, length=150)
	 */
	protected $_title = null;

}

Execute the following DQL 2 times:

$query = $entityManager->createQuery('
			SELECT 
				f, fl 
			FROM 
				Bug_Model_Foo f 
			JOIN 
				f._fooLocaleRefFoo fl');
		return $query->getResult();

The first time, you won't have any issues.
The second time, when the data will be fetched from the identityMap, you won't find it because there is something wrong with the identities and you will get the following warning

( ! ) Notice: Undefined index: _foo in /var/www/vhost/core/htdocs/externals/Doctrine/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php on line 217
Call Stack
#	Time	Memory	Function	Location
1	0.0002	337752	{main}( )	../index.php:0
2	0.0848	7268724	Zend_Application->run( )	../index.php:26
3	0.0848	7268724	Zend_Application_Bootstrap_Bootstrap->run( )	../Application.php:366
4	0.0850	7268796	Zend_Controller_Front->dispatch( )	../Bootstrap.php:97
5	0.0908	7900416	Zend_Controller_Dispatcher_Standard->dispatch( )	../Front.php:954
6	0.0967	8209564	Zend_Controller_Action->dispatch( )	../Standard.php:295
7	0.0967	8213912	Bug_IndexController->indexAction( )	../Action.php:513
8	0.1936	11391900	Bug_Service_Bug->getFooLocaleList( )	../IndexController.php:35
9	0.1936	11394088	Doctrine\ORM\AbstractQuery->getResult( )	../Bug.php:41
10	0.1936	11394296	Doctrine\ORM\AbstractQuery->execute( )	../AbstractQuery.php:392
11	0.1945	11397960	Doctrine\ORM\Internal\Hydration\AbstractHydrator->hydrateAll( )	../AbstractQuery.php:594
12	0.1946	11398656	Doctrine\ORM\Internal\Hydration\ObjectHydrator->_hydrateAll( )	../AbstractHydrator.php:99
13	0.1946	11399876	Doctrine\ORM\Internal\Hydration\ObjectHydrator->_hydrateRow( )	../ObjectHydrator.php:140
14	0.1949	11405584	Doctrine\ORM\Internal\Hydration\ObjectHydrator->_getEntityFromIdentityMap( )	../ObjectHydrator.php:326

With the invalid key, it is not possible to get the entity from the identityMap.



 Comments   
Comment by Benjamin Eberlei [ 06/Aug/11 ]

I could reproduce this, working on a fix.

Comment by Benjamin Eberlei [ 06/Aug/11 ]

Fixed





[DDC-1298] SqlWalker->walkSelectClause imploding empty strings results in invalid query Created: 27/Jul/11  Updated: 28/Jul/11  Resolved: 28/Jul/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: DQL
Affects Version/s: 2.1
Fix Version/s: 2.1.1
Security Level: All

Type: Bug Priority: Critical
Reporter: Van Hauwaert Bert Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

Given the following MySQL structure

CREATE TABLE `bar` (
  `barID` int(11) NOT NULL AUTO_INCREMENT,
  `barReference` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`barID`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='module=bug';

CREATE TABLE `foo` (
  `fooID` int(11) NOT NULL AUTO_INCREMENT,
  `fooReference` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`fooID`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='module=bug';

CREATE TABLE `fooBar` (
  `fooID` int(11) NOT NULL,
  `barID` int(11) NOT NULL,
  PRIMARY KEY (`fooID`,`barID`),
  KEY `fk_foo1` (`fooID`),
  KEY `fk_bar1` (`barID`),
  CONSTRAINT `fk_table1_foo1` FOREIGN KEY (`fooID`) REFERENCES `foo` (`fooID`) ON DELETE CASCADE ON UPDATE NO ACTION,
  CONSTRAINT `fk_table1_bar1` FOREIGN KEY (`barID`) REFERENCES `bar` (`barID`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='module=bug';

INSERT INTO `bar` (`barID`, `barReference`)
VALUES
	(1, 'bar1'),
	(2, 'bar2');

INSERT INTO `foo` (`fooID`, `fooReference`)
VALUES
	(1, 'foo1');

INSERT INTO `fooBar` (`fooID`, `barID`)
VALUES
	(1, 1);

the following models:

use Doctrine\ORM\Mapping as ORM;

/**
 * Model for foo
 *
 * @category Application
 * @package Bug
 * @subpackage Model
 * @ORM\Table(name="foo")
 * @ORM\Entity
 */
class Bug_Model_Foo
{
	/**
	 * @var integer fooID
	 * @ORM\Column(name="fooID", type="integer", nullable=false)
	 * @ORM\GeneratedValue(strategy="IDENTITY")
	 * @ORM\Id
	 */
	protected $_fooID = null;

	/**
	 * @var string fooReference
	 * @ORM\Column(name="fooReference", type="string", nullable=true, length=45)
	 */
	protected $_fooReference = null;

	/**
	 * @ORM\OneToMany(targetEntity="Bug_Model_FooBar", mappedBy="_foo",
	 * cascade={"persist"})
	 */
	protected $_fooBarRefFoo = null;

	/**
	 * Constructor
	 *
	 * @param array|Zend_Config|null $options
	 * @return Bug_Model_Foo
	 */
	public function __construct($options = null)
	{
		$this->_fooBarRefFoo = new \Doctrine\Common\Collections\ArrayCollection();
		parent::__construct($options);
	}

}
use Doctrine\ORM\Mapping as ORM;

/**
 * Model for bar
 *
 * @category Application
 * @package Bug
 * @subpackage Model
 * @ORM\Table(name="bar")
 * @ORM\Entity
 */
class Bug_Model_Bar
{
	/**
	 * @var integer barID
	 * @ORM\Column(name="barID", type="integer", nullable=false)
	 * @ORM\GeneratedValue(strategy="IDENTITY")
	 * @ORM\Id
	 */
	protected $_barID = null;

	/**
	 * @var string barReference
	 * @ORM\Column(name="barReference", type="string", nullable=true, length=45)
	 */
	protected $_barReference = null;

	/**
	 * @ORM\OneToMany(targetEntity="Bug_Model_FooBar", mappedBy="_bar",
	 * cascade={"persist"})
	 */
	protected $_fooBarRefBar = null;

	/**
	 * Constructor
	 *
	 * @param array|Zend_Config|null $options
	 * @return Bug_Model_Bar
	 */
	public function __construct($options = null)
	{
		$this->_fooBarRefBar = new \Doctrine\Common\Collections\ArrayCollection();
		parent::__construct($options);
	}
}

use Doctrine\ORM\Mapping as ORM;

/**
 * Model for fooBar
 *
 * @category Application
 * @package Bug
 * @subpackage Model
 * @ORM\Table(name="fooBar")
 * @ORM\Entity
 */
class Bug_Model_FooBar
{
	/**
	 * @ORM\ManyToOne(targetEntity="Bug_Model_Foo")
	 * @ORM\JoinColumn(name="fooID", referencedColumnName="fooID")
	 * @ORM\Id
	 */
	protected $_foo = null;

	/**
	 * @ORM\ManyToOne(targetEntity="Bug_Model_Bar")
	 * @ORM\JoinColumn(name="barID", referencedColumnName="barID")
	 * @ORM\Id
	 */
	protected $_bar = null;

}

and using the following DQL:

SELECT 
	f, b, fb 
FROM 
	Bug_Model_Foo f 
JOIN 
	f._fooBarRefFoo fb
JOIN
	fb._bar b

will result in the following sql query:

SELECT f0_.fooID AS fooID0, f0_.fooReference AS fooReference1, , b1_.barID AS barID2, b1_.barReference AS barReference3, f2_.fooID AS fooID4, f2_.barID AS barID5 FROM foo f0_ INNER JOIN fooBar f2_ ON f0_.fooID = f2_.fooID INNER JOIN bar b1_ ON f2_.barID = b1_.barID

there are 2 comma's between "f0_.fooReference AS fooReference1" and "b1_.barID AS barID2" resulting in an invalid query.

The first line of the walkSelectClause function in Doctrine/ORM/Query/SqlWalker.php will implode the result of the array_map.
But you receive an empty result from processing the data for the selectExpression "fb" explaining why you got the extra comma.

This worked in a previous version when 2.1 was still in development.



 Comments   
Comment by Van Hauwaert Bert [ 27/Jul/11 ]

I have fixed it and made a pull request: https://github.com/doctrine/doctrine2/pull/96

Comment by Benjamin Eberlei [ 28/Jul/11 ]

Fixed





[DDC-2079] Error in build entities using yml with several inversedJoinColumns Created: 15/Oct/12  Updated: 09/Nov/12  Resolved: 21/Oct/12

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Tools
Affects Version/s: 2.3
Fix Version/s: 2.3.1
Security Level: All

Type: Bug Priority: Critical
Reporter: André Antônio Lemos de Moraes Assignee: Fabio B. Silva
Resolution: Fixed Votes: 0
Labels: None
Environment:

windows 7/php 5.3/apache 2.2



 Description   

Hello guys, sorry for the bad English found the error during a necessity and would like to post the solution.

Below is an example of my yml relationamento a many to many.

manyToMany:
centroCustos:
targetEntity: Album\Entity\CentroCusto
cascade: ["persist", "merge"]
inversedBy: unidades
joinTable:
name: unidade_centro_custo
joinColumns:
idunidade:
referencedColumnName: idunidade
onDelete: cascade
inverseJoinColumns:
idcentrocusto:
referencedColumnName: idcentrocusto
idpais:
referencedColumnName: idpais
idmundo:
referencedColumnName: idmundo
onDelete: cascade

Well this example is generating this code.

/**

  • @var \Doctrine\Common\Collections\ArrayCollection
    *
  • @ORM\ManyToMany(targetEntity="Album\Entity\CentroCusto", inversedBy="unidades", cascade= {"persist","merge"}

    )

  • @ORM\JoinTable(name="unidade_centro_custo",
  • joinColumns= { * @ORM\JoinColumn(name="idunidade", referencedColumnName="idunidade", onDelete="cascade") * }

    ,

  • inverseJoinColumns= { * @ORM\JoinColumn(name="idcentrocusto", referencedColumnName="idcentrocusto") * @ORM\JoinColumn(name="idpais", referencedColumnName="idpais") * @ORM\JoinColumn(name="idmundo", referencedColumnName="idmundo", onDelete="cascade") * }
  • )
    */

Notice that Doctrine 2 is not putting commas to separate JoinColumns.

So looking at the source code I found the following code and put it solved my problem.

The changes was performed in EntityGenerator.php line 1090.

$arrJoins = array();
foreach ($associationMapping['joinTable']['joinColumns'] as $joinColumn)

{ $arrJoins[] = $this->spaces . ' * ' . $this->generateJoinColumnAnnotation($joinColumn); }

$lines[] = implode(",". PHP_EOL, $arrJoins);
$lines[] = $this->spaces . ' * },';
$lines[] = $this->spaces . ' * inverseJoinColumns={';

$arrJoinsInverse = array();
foreach ($associationMapping['joinTable']['inverseJoinColumns'] as $joinColumn)

{ $arrJoinsInverse[] = $this->spaces . ' * ' . $this->generateJoinColumnAnnotation($joinColumn); }

$lines[] = implode(",". PHP_EOL, $arrJoinsInverse);
$lines[] = $this->spaces . ' * }';
$lines[] = $this->spaces . ' * )'; }

I hope you understand what I'm trying to say, for you do not know if this error occurred, but if there ocorrei is one possible solution.

Thank you.



 Comments   
Comment by Fabio B. Silva [ 21/Oct/12 ]

Fixed by : https://github.com/doctrine/doctrine2/commit/2c0feb2a46a7cf97dc2878e6214924c3ffdbce67





[DDC-2032] DQL fails for Joined Inheritance with Associations on child classes Created: 15/Sep/12  Updated: 21/Sep/12  Resolved: 21/Sep/12

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

Type: Bug Priority: Critical
Reporter: Philipp Dobrigkeit Assignee: Benjamin Eberlei
Resolution: Invalid Votes: 0
Labels: dql
Environment:

Windows XAMPP



 Description   

I have the following object hierarchy:

Clazz A with Joined Table Inheritance
Clazz B extends A
Clazz C extends A with an association (n:1) to D
Clazz D

I am doing a DQL query 'SELECT u FROM A u'

If I just have As and Bs in the DB everything is fine. But I there is a C in there I get the following error:

Notice: Trying to get property of non-object in X:\Zend_Workspace\goalio_application\vendor\doctrine\orm\lib\Doctrine\ORM\Internal\Hydration\ObjectHydrator.php on line 479

Fatal error: Call to a member function fetch() on a non-object in X:\Zend_Workspace\goalio_application\vendor\doctrine\orm\lib\Doctrine\ORM\Internal\Hydration\ObjectHydrator.php on line 148

When I debug the _rsm of the Hydrator is null when trying to hydrate the row for C.

Any ideas?



 Comments   
Comment by Philipp Dobrigkeit [ 19/Sep/12 ]

Ok, it doesn't seem related to inheritance. Have the same problem now as well with a Join DQL query.

Foo (1:n) Bar
Bar (1:n) Baz

SELECT c FROM Foo c INNER JOIN c.bar cj WITH cj.id IN(1)

Gives me the same error as above when it tries to hydrate Bar

Comment by Philipp Dobrigkeit [ 21/Sep/12 ]

Ok, further investigations on my part have found the problem to be somewhere else entirely... Not sure yet if it is a bug, but the problem arises because during the hydration my application does another query, which uses the same hydrator object and thus does cleanup before the initial query is complete. That results in the _rsm being null when the original hydration continues. Will see if that can be fixed in my application.

Comment by Marco Pivetta [ 21/Sep/12 ]

Philipp Dobrigkeit this is known. You have to pass a custom hydrator to the new query if you use DQL during PostLoad events.





[DDC-2012] Inserting a new entity with a custom mapping type does not call convertToDatabaseValueSQL() when using InheritanceType("JOINED") Created: 04/Sep/12  Updated: 03/Oct/12  Resolved: 03/Oct/12

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers
Affects Version/s: 2.2.3
Fix Version/s: 2.2.4, 2.3.1
Security Level: All

Type: Bug Priority: Critical
Reporter: Kaspars Sproģis Assignee: Fabio B. Silva
Resolution: Fixed Votes: 0
Labels: None
Environment:

PHP


Attachments: Text File DDC2012Test.php     File DDC2012Test.php    

 Description   

When using class type inheritance - @InheritanceType("JOINED") and inserting new entity with a custom mapping type, custom type method convertToDatabaseValueSQL() is never called.

Here is sample class mapping:

Unable to find source-code formatter for language: php. Available languages are: actionscript, html, java, javascript, none, sql, xhtml, xml
 
/**
 * @Table(name="item")
 * @Entity
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="type_id", type="smallint")
 * @DiscriminatorMap({1 = "ItemPerson"})
 */
class Item {

	/**
	 * @Column(name="tsv", type="tsvector", nullable=true)
	 */
	protected $tsv;
}

/**
 * @Table(name="item_person")
 * @Entity
 */
class ItemPerson extends Item
{
}

I am using the same custom TsvectorType with simple entities and even Mapped Superclasses and it works perfectly, however on InheritanceType("JOINED") method convertToDatabaseValueSQL() is never called :/
Hope someone knows how to fix this.
Thank you.



 Comments   
Comment by Fabio B. Silva [ 24/Sep/12 ]

Hi Kaspars,

I can't reproduce,
Could you change the added testcase and try to make it fails ?

Thanks

Comment by Kaspars Sproģis [ 26/Sep/12 ]

@Fabio thanks for looking into my problem
I attached test where you can detect the problem.

It was quite strange, all i did was changed column that uses custom type to array and some minimal convertToDatabaseValue and convertToDatabaseValueSQL logic and convertToDatabaseValueSQL was never called.

One more thing i noticed, this bug only appears on persist and not on merge.

Thanks

Comment by Fabio B. Silva [ 29/Sep/12 ]

Thanks Kaspars

But sorry, I dont get your use case.

Notice that convertToDatabaseValueSQL is called just when using queries to find a object by a especific columns which is your mapping type.

http://docs.doctrine-project.org/en/2.1/cookbook/advanced-field-value-conversion-using-custom-mapping-types.html#the-mapping-type

Comment by Kaspars Sproģis [ 29/Sep/12 ]

I am using PostgreSQL tsvector data type for full text search.

Here is my tsvector custom data type class:
https://gist.github.com/3129096

The only way to update this field in postgresql is to use postgresql function to_tsvector('some text').
And everything works fine, if i persist simple entity, this method transforms insert query as needed:

public function convertToDatabaseValueSQL($sqlExpr, AbstractPlatform $platform)
{
	return sprintf('to_tsvector(%s)', $sqlExpr);
}

But when i use inheritance, then by some reason convertToDatabaseValueSQL method is not called and tsv field is updated with simple text as returned by convertToDatabaseValue() method.
I modified the Ticket Test so that you can see exact moment of when it is not called, which is exactly my problem.

Here is the result after persisting (for persist it failed)

$person = new ItemPerson();
$person->setName('some words for test');
$em->persist($person);
$em->flush();

DB Result:
Name                | Tsv
--------------------|------------------------------------
some words for test | 'for' 'some' 'test' 'words'

Here is the result after second time update (now by tsv format you can see it worked):

$person->setName('some more words for test');
$em->flush();

DB Result:
Name                | Tsv
--------------------|------------------------------------
some words for test | 'test':5 'word':3
Comment by Fabio B. Silva [ 30/Sep/12 ]

Thanks Kaspars

Now i saw the problem

Writing a patch ...

Comment by Kaspars Sproģis [ 03/Oct/12 ]

Just tested fixed version and everything works perfectly now.
Thank you!

Comment by Fabio B. Silva [ 03/Oct/12 ]

Fixed by : https://github.com/doctrine/doctrine2/commit/91caff1d8965c20b72d5fdd04ffadf3ab063c1ba





[DDC-2001] Problem nextval sequence persist many object Created: 29/Aug/12  Updated: 06/Oct/12  Resolved: 06/Oct/12

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

Type: Bug Priority: Critical
Reporter: Sandro Cândido de Oliveira Assignee: Benjamin Eberlei
Resolution: Invalid Votes: 0
Labels: None

Attachments: GZip Archive bugcodeigniterdoctrine.tar.gz    

 Description   

Seems to be a bug doctrine.

Scenario: You cart table and Product table when trying to persist the products do not set the last sequence postgres. In the example cart will id = 1
products id = 1 ... 5 but the sequence of the final product value is 2 and not 5.
If I run the script again I get the following error.

PDOException: SQLSTATE[23505]: Unique violation: 7 ERROR: duplicate key value violates unique constraint "product_pkey" DETAIL: Key (id)=(2) already exists. in /var/www/codeigniter/scclocal/application/third_party/doctrine-orm/Doctrine/DBAL/Statement.php on line 131

Sample code:

        $cart = new cart\models\Cart;

        $cart->em->getConnection()->beginTransaction();

        $cart->setDescription('My Cart');

        try {
            //Persist Cart
            $cart->em->persist($cart);
            $cart->em->flush();
        } catch(Exception $e) {
            $cart->em->getConnection()->rollback();
            $cart->em->close();
            throw $e;
        }
        //Product
        for($i=0; $i < 5; $i++){
            $product = new cart\models\Product;
            $product->setName('Name product '.$i);
            $product->setDescription('Description product '.$i);
            $product->setCart($cart);
            $cart->getProducts()->add($product); //Add products in cart
            $product->em->persist($product); //Persist Products
        }

        try {
            $cart->em->persist($cart);
            $cart->em->flush();
            $cart->em->getConnection()->commit();
        } catch(Exception $e) {
            $cart->em->getConnection()->rollback();
            $cart->em->close();
            throw $e;
        }
        die ('success save);

EchoSQLLogger Cart:

SELECT NEXTVAL('cart_id_seq') INSERT INTO cart (id, description) VALUES (?, ?)

array
  1 => int 1
  2 => string 'My Cart' (length=7)

EchoSQLLogger Products( Note that the second interaction forward select nextval was not generated. ) :

SELECT NEXTVAL('product_id_seq') INSERT INTO product (id, name, description, cart_id) VALUES (?, ?, ?, ?)

array
  1 => int 1
  2 => string 'Name product 0' (length=14)
  3 => string 'Description product 0' (length=21)
  4 => int 1

INSERT INTO product (id, name, description, cart_id) VALUES (?, ?, ?, ?)

array
  1 => int 2
  2 => string 'Name product 1' (length=14)
  3 => string 'Description product 1' (length=21)
  4 => int 1

INSERT INTO product (id, name, description, cart_id) VALUES (?, ?, ?, ?)

array
  1 => int 3
  2 => string 'Name product 2' (length=14)
  3 => string 'Description product 2' (length=21)
  4 => int 1

INSERT INTO product (id, name, description, cart_id) VALUES (?, ?, ?, ?)

array
  1 => int 4
  2 => string 'Name product 3' (length=14)
  3 => string 'Description product 3' (length=21)
  4 => int 1

INSERT INTO product (id, name, description, cart_id) VALUES (?, ?, ?, ?)

array
  1 => int 5
  2 => string 'Name product 4' (length=14)
  3 => string 'Description product 4' (length=21)
  4 => int 1

Entity Cart:

<?php
namespace cart\models;

/**
 * @Entity
 * @Table(name="cart")
 */
use models\MY_Model,
    Doctrine\Common\Collections\ArrayCollection;


class Cart extends MY_Model {

    /**
     * @Id
     * @Column(type="integer", nullable=false)
     * @GeneratedValue(strategy="SEQUENCE")
     * @SequenceGenerator(sequenceName="cart_id_seq", initialValue=1, allocationSize=100)
     */
    private $id;

    /**
     * @Column(type="string", length=200, nullable=true)
     */
    private $description;


    /**
     * @OneToMany(targetEntity="Product", mappedBy="cart", cascade={"all"})
     */
    private $products;

    public function __construct() {
        parent::__construct();
        $this->products = new ArrayCollection();
    }

    /**
     *
     * @return
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     *
     * @param $id
     */
    public function setId($id)
    {
        $this->id = $id;
    }

    /**
     *
     * @return
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     *
     * @param $descricao
     */
    public function setDescription($description)
    {
        $this->description = $description;
    }

    /**
     *
     * @return
     */
    public function getProducts()
    {
        return $this->products;
    }

    /**
     *
     * @param $categoria
     */
    public function setProducts(Products $products)
    {
        $this->products = $products;
    }
}
?>

Entity Product:

<?php
namespace cart\models;

/**
 * @Entity
 * @Table(name="product")
 */
use models\MY_Model,
    Doctrine\Common\Collections\ArrayCollection;

class Product extends MY_Model {

    /**
     * @Id
     * @Column(type="integer", nullable=false)
     * @GeneratedValue(strategy="SEQUENCE")
     * @SequenceGenerator(sequenceName="product_id_seq", initialValue=1, allocationSize=100)
     */
    private $id;

    /**
     * @Column(type="string", length=100)
     */
    private $name;

    /**
     * @Column(type="string", length=200)
     */
    private $description;

   
    /**
     * @link http://www.doctrine-project.org/docs/orm/2.0/en/reference/association-mapping.html#one-to-many-bidirectional
     *
     * @ManyToOne(targetEntity="Cart", inversedBy="product")
     * @JoinColumn(name="cart_id", referencedColumnName="id")
     */
    protected $cart;


    public function __construct(){
        parent::__construct();
    }

    /**
     *
     * @return
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     *
     * @param $id
     */
    public function setId($id)
    {
        $this->id = $id;
    }

    /**
     *
     * @return
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     *
     * @param $name
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     *
     * @return
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     *
     * @param $description
     */
    public function setDescription($description)
    {
        $this->description = $description;
    }

    /**
     *
     * @return
     */
    public function getCart()
    {
        return $this->cart;
    }

    /**
     *
     * @param $cart
     */
    public function setCart(Cart $cart)
    {
        $this->cart = $cart;
    }
}
?>

Attachment application sample



 Comments   
Comment by Benjamin Eberlei [ 29/Aug/12 ]

But the SQL Log correctly shows 1,..,5 in case of the INSERT statements for products. Where is the unique id clash happening?

Comment by Sandro Cândido de Oliveira [ 29/Aug/12 ]

It happens that for each insert must have a nextval to generate the unique id. Log in to run the script the first time the insert works but if you run the script again next products are not generated 6 ... 10 of the error occurring.

PDOException: SQLSTATE[23505]: Unique violation: 7 ERROR: duplicate key value violates unique constraint "product_pkey" DETAIL: Key (id)=(2) already exists. in /var/www/codeigniter/bugcodeigniterdoctrine/application/third_party/doctrine-orm/Doctrine/DBAL/Statement.php on line 131

Comment by Sandro Cândido de Oliveira [ 30/Aug/12 ]

Benjamin you could understand the problem now?

Comment by Benjamin Eberlei [ 06/Oct/12 ]

Its not a bug with Doctrine but your code, your sequence is defined wrong:

CREATE SEQUENCE product_id_seq
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;

If you increment by 100, then the sequence has to increment by 100. This is a low level db vendor feature.





[DDC-1657] The Doctrine cli tool does not handle schema correctly. Created: 19/Feb/12  Updated: 08/Jul/12  Resolved: 08/Jul/12

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Tools
Affects Version/s: 2.2
Fix Version/s: 2.3
Security Level: All

Type: Bug Priority: Critical
Reporter: Presteus Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

Linux Mint Debian Edition, PHP 5.3.10, PostgreSQL 9.1



 Description   

At first time, sorry for my english and I will be short and brief, the problem is clearly explained in the title and the test is very simple.

The entity

/**
 * Short description.
 *
 * @Entity(repositoryClass="Stonewood\Model\Entity\Repository\Screen")
 * @Table(name="stonewood.screen")
 */
class Screen extends Entity
{

    /**
     * Identifier
     * @var integer
     *
     * @Id
     * @GeneratedValue(strategy="IDENTITY")
     * @Column(name="pk", type="integer", nullable=false)
     */
    private $pk;

    /**
     * Title
     * @var string
     *
     * @Column(name="title", type="string", length=255, nullable=false)
     */
    private $title;

    /**
     * Path
     * @var string
     *
     * @Column(name="path", type="string", length=255, nullable=false)
     */
    private $path;

    /**
     * Register date
     * @var Date
     *
     * @Column(name="ddate", type="date", nullable=false)
     */
    private $ddate;

    /**
     * Avatar
     * @var Stonewood\Model\Entity\Avatar
     *
     * @ManyToOne(targetEntity="Stonewood\Model\Entity\Avatar")
     * @JoinColumn(name="pk_avatar", referencedColumnName="pk", nullable=true, onDelete="CASCADE")
     */
    private $avatar;

    /**
     *
     */
    public function __construct($pk = null, $title = null, $path = null, $ddate = null, $avatar = null) {
        $this->setPk($pk);
        $this->setTitle($title);
        $this->setPath($path);
        $this->setDdate($ddate);
        $this->setAvatar($avatar);
    }

    [...]

}

Before the first deployment

./doctrine orm:schema-tool:update --dump-sql
CREATE TABLE stonewood.screen (pk SERIAL NOT NULL, pk_avatar INT DEFAULT NULL, title VARCHAR(255) NOT NULL, path VARCHAR(255) NOT NULL, ddate DATE NOT NULL, PRIMARY KEY(pk));
CREATE INDEX IDX_D91A7FB3E9032144 ON stonewood.screen (pk_avatar);

During the first deployement

 
./doctrine orm:schema-tool:update --force
Updating database schema...
Database schema updated successfully! "100" queries were executed

I test the application and all work correctly

After this test

 
./doctrine orm:schema-tool:update --dump-sql
ALTER TABLE screen ADD pk SERIAL NOT NULL;
ALTER TABLE screen ADD pk_avatar INT DEFAULT NULL;
ALTER TABLE screen ADD title VARCHAR(255) NOT NULL;
ALTER TABLE screen ADD path VARCHAR(255) NOT NULL;
ALTER TABLE screen ADD ddate DATE NOT NULL;
ALTER TABLE screen ADD CONSTRAINT FK_D91A7FB3E9032144 FOREIGN KEY (pk_avatar) REFERENCES stonewood.avatar (pk) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE;
CREATE INDEX IDX_D91A7FB3E9032144 ON screen (pk_avatar);
ALTER TABLE screen ADD PRIMARY KEY (pk);

The result is false. I should see Nothing to update - your database is already in sync with the current entity metadata.
In addition, the schema name does not appear, except for foreign key, what must be causing the problem.



 Comments   
Comment by Benjamin Eberlei [ 27/May/12 ]

This issue was partially fixed in DBAL already, however it seems there is still a problem with sequence detection.

Comment by Benjamin Eberlei [ 08/Jul/12 ]

Fixed the sequence problem in 2.3, the other schema problems where indeed fixed in 2.2.1 already.





[DDC-1651] APC query caching fails when an entity is bound to a query parameter. Created: 14/Feb/12  Updated: 18/Feb/12  Resolved: 18/Feb/12

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: DQL, ORM
Affects Version/s: 2.1.6
Fix Version/s: 2.2.1

Type: Bug Priority: Critical
Reporter: Jonathan Robinson Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

Debian, Php 5.3, APC 3.1.9



 Description   

When an entity is bound as a query parameter, query caching with APC fails with error message:

Catchable fatal error: Object of class XXX could not be converted to string in /libs/doctrine-orm/Doctrine/DBAL/Connection.php on line 1081

If I bind with entity's primary key field, everything works fine.



 Comments   
Comment by Benjamin Eberlei [ 18/Feb/12 ]

Fixed and merged into 2.2 branch.

A rebase onto the 2.1.x branch would take a rewrite, since the code is completly new and since there is a simple workaround ($entity->getId()) when binding i will not backported it into the 2.1.x branch.

https://github.com/doctrine/doctrine2/commit/6cd82d77f5e581b3d21c60c5cb5e6c5042a3ff9b





[DDC-1644] Using full annotation namespace breaks annotations Created: 10/Feb/12  Updated: 17/Feb/12  Resolved: 17/Feb/12

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

Type: Bug Priority: Critical
Reporter: James Reed Assignee: Benjamin Eberlei
Resolution: Invalid Votes: 1
Labels: None
Environment:

Red Hat Linux - PHP 5.3.8



 Description   

I have created my own custom annotations. They work fine when I use them in a normal class file, but if I try to use them inside of a Doctrine Model class then the base Doctrine annotations don't work. My understanding is I have to specify the full namespace for the default Annotations in order for them to work with custom annotations. However, when I do this I get the dreaded error:

Uncaught exception 'Doctrine\ORM\Mapping\MappingException' with message 'Class xxx is not a valid entity or mapped super class.' in /Magnet/winlibrary/doctrine-orm/Doctrine/ORM/Mapping/MappingException.php:142

In order to test this further I used the quick start documentation and modified it to use full annotation namespaces. Here is the code:

<?php
require_once '/library/doctrine-orm/Doctrine/Common/ClassLoader.php';

$loader = new \Doctrine\Common\ClassLoader("Doctrine", '/library/doctrine-orm');
$loader->register();

use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping as ORM;

/** @ORM\Entity **/
class Post
{
    /** @ORM\Id @GeneratedValue @ORM\Column(type="integer") **/
    protected $id;
    /** @ORM\Column(type="string") **/
    protected $title;
    /** @ORM\Column(type="text") **/
    protected $body;
}

$dbParams = array(
    'driver' => 'pdo_mysql',
    'user' => 'root',
    'password' => '',
    'dbname' => 'mydb'
);

$config = Setup::createAnnotationMetadataConfiguration(array());
$entityManager = EntityManager::create($dbParams, $config);
$post = $entityManager->find("Post", 555);

print_r($post);

When I run this I get the error:

Uncaught exception 'Doctrine\ORM\Mapping\MappingException' with message 'Class Post is not a valid entity or mapped super class.' in /Magnet/winlibrary/doctrine-orm/Doctrine/ORM/Mapping/MappingException.php:142

If I remove the "ORM\" from the annotations and remove "use Doctrine\ORM\Mapping as ORM;" then it works properly. I can't seem to find why the full annotation namespaces don't work properly as I've seen a number of examples that do this.

Also, I noticed that if I specify the full namespace without the "use Doctrine\ORM\Mapping as ORM;" alias (i.e. @Doctrine\ORM\Mapping\Entity) then it works on 2.1.x but does not work on 2.2.0. Using the ORM alias does not work on either version. Given I've followed the documentation and have found inconsistencies between the versions it seems this is a bug in either the code or the documentation.



 Comments   
Comment by Benjamin Eberlei [ 17/Feb/12 ]

Setup::createAnnotationMetadataDriver().. uses the Simple Annotation Reader.

You have to setup the "normal" annotation reader with the AnnotationDriver to get "ORM\" working. This could be documented better.





[DDC-1640] Actual classMetadata is not used when entity with DiscriminatorMap is hydrated, instead AbstractClass metaData is used. Created: 08/Feb/12  Updated: 17/Feb/12  Resolved: 17/Feb/12

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.2
Fix Version/s: 2.2.1
Security Level: All

Type: Bug Priority: Critical
Reporter: Jelte Steijaert Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

Because the className changes in ObjectHydrator:226 it might be that the ClassMetadata has not been loaded yet.
When the classMetadata has not been loaded the PostLoad events are not executed.

adding the following after the className has changed solves the issue.

$this->_getClassMetadata($className);

example:

Class Session {
    /**
     * @access private
     * @var ArrayCollection
     * @ORM\OneToMany(targetEntity="AbstractService", mappedBy="session")
     */
    public $services;
}
/**
 * @ORM\Entity
 * @ORM\HasLifecycleCallbacks
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="type", type="string")
 * @ORM\DiscriminatorMap({
 * 		"A" = "ServiceA",
 * 		"B" = "ServiceB"
 * })
 */
abstract class AbstractService 
{
    /**
     * @access private
     * @var string
     * @ORM\Column()
     */
    private $_status;

    public $status;

    /**
     * @access public
     * @internal Do not use; this is for Doctrine only
     * @ORM\PostLoad
     * @return void
     */
    public function _reconstituteValueObjects()
    {
        $this->status = new Status($this->_status);
    }
}

When I would do now:

foreach ( $session->services as $service ) {
    $service->status->stop();
}

$service would be a concrete class ServceA or ServiceB, but these ClassMetadata's might not be loaded yet. If this is the cause then $service->status will be null as the @PostLoad has not been executed.



 Comments   
Comment by Jelte Steijaert [ 09/Feb/12 ]

I've have found the same issue with the SimpleObjectHydrator.

Although here it might have worse consequences.
When a row is hydrated it the class has a discriminatorMap, the classMetadata of the defined class (usually the abstract class) is used and not the actual classMetadata of the class it will be converted to.
Same issue here that the @PostLoad isn't triggered but also

$this->registerManaged($this->class,...) 

uses the wrong classMetadata is used.

should be: Doctrine\ORM\Internal\Hydration\SimpleObjectHydrator:86

    protected function hydrateRowData(array $sqlResult, array &$cache, array &$result)
    {
        $classMetadata = $this->class;
        $entityName = $this->class->name;
        $data       = array();

        // We need to find the correct entity class name if we have inheritance in resultset
        if ($classMetadata->inheritanceType !== ClassMetadata::INHERITANCE_TYPE_NONE) {
            $discrColumnName = $this->_platform->getSQLResultCasing($classMetadata->discriminatorColumn['name']);

            if ($sqlResult[$discrColumnName] === '') {
                throw HydrationException::emptyDiscriminatorValue(key($this->_rsm->aliasMap));
            }

            $entityName = $classMetadata->discriminatorMap[$sqlResult[$discrColumnName]];
            $classMetadata = $this->_getClassMetadata($entityName);

            unset($sqlResult[$discrColumnName]);
        }
        foreach ($sqlResult as $column => $value) {
            // Hydrate column information if not yet present
            if ( ! isset($cache[$column])) {
                if (($info = $this->hydrateColumnInfo($entityName, $column)) === null) {
                    continue;
                }

                $cache[$column] = $info;
            }

            // Convert field to a valid PHP value
            if (isset($cache[$column]['field'])) {
                $type  = Type::getType($cache[$column]['class']->fieldMappings[$cache[$column]['name']]['type']);
                $value = $type->convertToPHPValue($value, $this->_platform);
            }

            // Prevent overwrite in case of inherit classes using same property name (See AbstractHydrator)
            if (isset($cache[$column]) && ( ! isset($data[$cache[$column]['name']]) || $value !== null)) {
                $data[$cache[$column]['name']] = $value;
            }
        }

        if (isset($this->_hints[Query::HINT_REFRESH_ENTITY])) {
            $this->registerManaged($classMetadata, $this->_hints[Query::HINT_REFRESH_ENTITY], $data);
        }

        $uow    = $this->_em->getUnitOfWork();
        $entity = $uow->createEntity($entityName, $data, $this->_hints);

        //TODO: These should be invoked later, after hydration, because associations may not yet be loaded here.
        if (isset($classMetadata->lifecycleCallbacks[Events::postLoad])) {
            $classMetadata->invokeLifecycleCallbacks(Events::postLoad, $entity);
        }

        $evm = $this->_em->getEventManager();

        if ($evm->hasListeners(Events::postLoad)) {
            $evm->dispatchEvent(Events::postLoad, new LifecycleEventArgs($entity, $this->_em));
        }

        $result[] = $entity;
    }
Comment by Jelte Steijaert [ 09/Feb/12 ]

Changed summery to better reflect the bug.

Comment by Benjamin Eberlei [ 17/Feb/12 ]

Fixed.





[DDC-1638] Inexistant method newInstance in UnitOfWork Created: 07/Feb/12  Updated: 10/Feb/12  Resolved: 10/Feb/12

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

Type: Bug Priority: Critical
Reporter: Christophe Coevoet Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

the UnitOfWork uses ``newInstance`` to get the managed copy but this method does not exist in 2.1.6, thus breaking the code: https://github.com/doctrine/doctrine2/blob/e1647229cd2544bd77f10620e1b95a5781c4a733/lib/Doctrine/ORM/UnitOfWork.php#L1418

This is probably an error when backporting a patch as the method exists in master



 Comments   
Comment by Marco Pivetta [ 07/Feb/12 ]

Patch at https://github.com/doctrine/doctrine2/pull/276

Comment by Benjamin Eberlei [ 10/Feb/12 ]

Fixed





[DDC-1636] JoinColumn with name the same as id generates wrong SQL. Created: 06/Feb/12  Updated: 07/Apr/12  Resolved: 07/Apr/12

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

Type: Bug Priority: Critical
Reporter: Guilherme Blanco Assignee: Benjamin Eberlei
Resolution: Can't Fix Votes: 0
Labels: None

Attachments: File DDC1636Test.php    

 Description   

Issue came from Hussani de Oliveira on MSN.
He has this Entities configuration:

Usuario.php

<?php
 
namespace App\UsuariosBundle\Entity;
 
use Doctrine\ORM\Mapping as ORM;
 
/**
 * @ORM\Entity
 * @ORM\Table(name="usuarios")
 */
class Usuario
{
    /**
     * @var int
     *
     * @ORM\Id
     * @ORM\Column(name="usuarios_id", type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;
   
    /**
     * @var string
     *
     * @ORM\Column(name="nome", type="string", length=45)
     */
    protected $nome;
   
    /**
     * @var string
     *
     * @ORM\ManyToOne(targetEntity="PerfilUsuario", fetch="EAGER")
     * @ORM\JoinColumn(name="perfil_usuarios_id", referencedColumnName="perfil_usuarios_id")
     */
    protected $perfil;
   
    // getters and setters
}

PerfilUsuario.php

<?php
 
namespace App\UsuariosBundle\Entity;
 
use Doctrine\ORM\Mapping as ORM;
 
/**
 * @ORM\Entity
 * @ORM\Table(name="perfil_usuarios")
 */
class PerfilUsuario
{
    /**
     * @var integer
     * @ORM\Id
     * @ORM\Column(name="perfil_usuarios_id", type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;
     
    /**
     * @ORM\ManyToOne(targetEntity="Secoes", fetch="EAGER")
     */
    protected $secoes;
   
    // getters and setters
}

Whenever he tries to load User (Usuario) and automatically join the UserProfle (PerfilUsuario), it generates the wrong SQL:

SELECT 
    t0.usuarios_id AS usuarios_id1, 
    t0.nome AS nome2, 
    t0.email AS email3,
    t0.login AS login4,
    t0.senha AS senha5,
    t0.cargo AS cargo6,
    t0.perfil_usuarios_id AS perfil_usuarios_id7,
    t8.perfil_usuarios_id AS perfil_usuarios_id9,
    t8.secoes_id AS secoes_id10 
FROM usuarios t0 
LEFT JOIN perfil_usuarios t8 
  ON t0.perfil_usuarios_id = t11.perfil_usuarios_id

His schema dump:

SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL';
 
CREATE SCHEMA IF NOT EXISTS `aquario` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
USE `aquario` ;
 
-- -----------------------------------------------------
-- Table `aquario`.`perfil_usuarios`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `aquario`.`perfil_usuarios` (
  `perfil_usuarios_id` INT(11) NOT NULL ,
  `nome` VARCHAR(45) CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci' NULL DEFAULT NULL ,
  PRIMARY KEY (`perfil_usuarios_id`) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_unicode_ci;
 
 
-- -----------------------------------------------------
-- Table `aquario`.`usuarios`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `aquario`.`usuarios` (
  `usuarios_id` INT(11) NOT NULL ,
  `perfil_usuarios_id` INT(11) NULL DEFAULT NULL ,
  `nome` VARCHAR(45) CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci' NULL DEFAULT NULL ,
  `email` VARCHAR(100) CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci' NULL DEFAULT NULL ,
  `login` VARCHAR(45) CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci' NULL DEFAULT NULL ,
  `senha` VARCHAR(45) CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci' NULL DEFAULT NULL ,
  `cargo` VARCHAR(45) CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci' NULL DEFAULT NULL ,
  PRIMARY KEY (`usuarios_id`) ,
  INDEX `FK_PERIFIL_USUARIOS_PERFIL_USUARIOSID_PERFIL_USUARIOS` (`perfil_usuarios_id` ASC) ,
  CONSTRAINT `FK_PERIFIL_USUARIOS_PERFIL_USUARIOSID_PERFIL_USUARIOS`
    FOREIGN KEY (`perfil_usuarios_id` )
    REFERENCES `aquario`.`perfil_usuarios` (`perfil_usuarios_id` ))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_unicode_ci;


 Comments   
Comment by Fabio B. Silva [ 11/Feb/12 ]

Hi,
I'm trying to test this, But I can't reproduce.
I'm attaching a test case.

Hussani Oliveira ,
Can you try to change the test to make it fail ?

Comment by Benjamin Eberlei [ 07/Apr/12 ]

No feedback was given on this critical issue with proof of working through TestCase. Closing until further feedback.





[DDC-1635] Single Table Inheritance and a composite key gives the wrong entity when using the IdentityMap Created: 06/Feb/12  Updated: 20/Feb/12  Resolved: 18/Feb/12

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

Type: Bug Priority: Critical
Reporter: Andreas Hörnicke Assignee: Benjamin Eberlei
Resolution: Invalid Votes: 0
Labels: None


 Description   

Given the following data, a single table inheritance with 'type' being the discriminator column and a composite key of (type, key, foreign):

type key foreign
type-1 key-1 xyz
type-2 key-1 xyz

As Doctrine only takes the columns 'key' and 'foreign' into the composite key, it gives me an instance of the class being mapped to 'type-1' when wanting to select an instance of 'type-2' with key=key-1 && foreign=xyz. BUT this only occurs when i already fetched the instance mapped to type-1 with the same values.



 Comments   
Comment by Benjamin Eberlei [ 10/Feb/12 ]

The type can never be part of the primary key, how did you even map that? can you post details?

Comment by Andreas Hörnicke [ 14/Feb/12 ]

I did not specified type as being part of the primary key ... for obvious reasons. I didnt even thought of it being necessary as this is the only time we are using single table inheritance.

This is an abstracted version of our domain model:

sql definition
CREATE TABLE `users` (
	`id` MEDIUMINT(8) UNSIGNED NOT NULL AUTO_INCREMENT,
	`mail` VARCHAR(255) NULL DEFAULT NULL,
	`passwd` VARCHAR(255) NULL DEFAULT NULL,
	PRIMARY KEY (`id`)
) ENGINE=InnoDB;

CREATE TABLE `tasks` (
	`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
	`f_user` MEDIUMINT(8) UNSIGNED NULL DEFAULT NULL,
	`priority` SMALLINT(5) UNSIGNED NOT NULL,
	`some_other_column` VARCHAR(255) NULL DEFAULT NULL,
	PRIMARY KEY (`id`),
	CONSTRAINT `fk_tasks_user` FOREIGN KEY (`f_user`) REFERENCES `users` (`id`) ON UPDATE CASCADE ON DELETE SET NULL
) ENGINE=InnoDB;

CREATE TABLE `attributes` (
	`key` VARCHAR(50) NOT NULL,
	`name` VARCHAR(255) NOT NULL,
	PRIMARY KEY (`key`)
) ENGINE=InnoDB;

CREATE TABLE `attributes_rel` (
	`type` ENUM('task','user') NOT NULL,
	`foreign_id` BIGINT(20) UNSIGNED NOT NULL,
	`f_attribute` VARCHAR(50) NOT NULL,
	`value_int` BIGINT(20) UNSIGNED NULL DEFAULT NULL,
	`value_date` DATETIME NULL DEFAULT NULL,
	`value_text` TEXT NULL,
	PRIMARY KEY (`type`, `foreign_id`, `f_attribute`),
	CONSTRAINT `fk_attributes_rel_attribute` FOREIGN KEY (`f_attribute`) REFERENCES `attributes` (`key`) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB;

INSERT INTO `attributes` (`key`, `name`) VALUES
  ('description', 'description');

INSERT INTO `users` (`id`, `mail`, `passwd`) VALUES
  (1, 'abc@def.xyz', 'e10adc3949ba59abbe56e057f20f883e');

INSERT INTO `tasks` (`id`, `f_user`, `priority`, `some_other_column`) VALUES
  (1, 1, 1, 'nothing in here');

INSERT INTO `attributes_rel` (`type`, `foreign_id`, `f_attribute`, `value_int`, `value_date`, `value_text`) VALUES
  ('task', 1, 'description', NULL, NULL, 'catchy description for a task'),
  ('user', 1, 'description', NULL, NULL, 'catchy description for a user');
// definition wihin task model
/**
 * @var \Doctrine\Common\Collections\ArrayCollection
 *
 * @OneToMany(targetEntity="TaskAttribute", mappedBy="foreign")
 * @JoinColumn(name="foreign", referencedColumnName="id")
 */
protected $attributes;

// definition wihin user model
/**
 * @var \Doctrine\Common\Collections\ArrayCollection
 *
 * @OneToMany(targetEntity="UserAttribute", mappedBy="foreign")
 * @JoinColumn(name="foreign", referencedColumnName="id")
 */
protected $attributes;

When calling $em->find('Task', 1)>getAttributes() and then doing $em>find('User', 1)->getAttributes() it gives me an instance of TaskAttribute for the user instead of a fresh UserAttribute.

Comment by Benjamin Eberlei [ 18/Feb/12 ]

To have type part of the primary key you have to map it as field. Discrimnator columns can never be part of the PK for doctrine, even if they are in the database.

You can change your domain model to something like

class Attribute
{
   /** @Id @Column(type="integer") */
   public $type;
   /** @Id @ManyToOne(target="Foreign") */
   public $foreign;
   /** @id @Column(type="string") */
   public $key;
}
Comment by Andreas Hörnicke [ 20/Feb/12 ]

But then i cant use table inheritance.

Comment by Benjamin Eberlei [ 20/Feb/12 ]

Yes, you can't in your scenario, its just not supported with the discriminator column in it.





[DDC-1632] one-to-many associations with fetch mode eager using too many SQL queries Created: 02/Feb/12  Updated: 10/Feb/12  Resolved: 09/Feb/12

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

Type: Bug Priority: Critical
Reporter: Martin Assignee: Benjamin Eberlei
Resolution: Invalid Votes: 0
Labels: None


 Description   

I am loading a list of many entities.
These entities have a one-to-many association to other entities.
These other entities should be loaded in one single SQL query (instead of one query for every entity in the first list).

As discribed in the doctrine2 documentation: http://www.doctrine-project.org/docs/orm/2.1/en/reference/dql-doctrine-query-language.html#temporarily-change-fetch-mode-in-dql this should be possible with "EAGER" loading.

but it does not work as described.

my code:

class User{
    /**
     * @ORM\OneToMany(targetEntity="Address", mappedBy="user", indexBy="id", fetch="EAGER")
     */
    protected $addresses;
    public function __construct(){
        $this->addresses = new ArrayCollection();
    }
}

class Address{
    /**
     * @ORM\ManyToOne(targetEntity="User", inversedBy="addresses")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="UserId", referencedColumnName="id")
     * })
     */
    private $user;
}

class UserRepository{
    public function findUsersWithAddresses(){
        return $this->getEntityManager()
            ->createQuery('SELECT u FROM MyBundle:User u ORDER BY u.name ASC')
            ->setFetchMode('MyBundle\Entity\User', 'addresses', \Doctrine\ORM\Mapping\ClassMetadata::FETCH_EAGER)
            ->setMaxResults(10)
            ->getResult();
    }
}

The method UserRepository::findUsersWithAddresses() executes 11 SQL Queries instead of 2 SQL Queries.

I am using:

  • symfony v2.0.9
  • doctrine-common 2.1.4
  • doctrine-dbal 2.1.5
  • doctrine 2.1.5


 Comments   
Comment by Benjamin Eberlei [ 06/Feb/12 ]

Increased priority

Comment by Martin [ 09/Feb/12 ]

there is also a question on stackoverflow about this issue: http://stackoverflow.com/questions/9020433/doctrine2-loads-one-to-many-associations-with-fetch-mode-eager-using-too-many-sq

Comment by Benjamin Eberlei [ 09/Feb/12 ]

Its not a bug, its just a feature we haven't implemented yet.

There is a ticket for it

Comment by Martin [ 10/Feb/12 ]

Sorry, I didn't found the ticket before I reported this issue.
now i found it http://www.doctrine-project.org/jira/browse/DDC-1149

Would be very great to have this feature in a future version of doctrine.





[DDC-1598] ProxyFactory makes assumptions on identifier getter code Created: 13/Jan/12  Updated: 16/Jan/12  Resolved: 16/Jan/12

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0, 2.0.1, 2.0.2, 2.0.3, 2.0.4, 2.0.5, 2.0.6, 2.0.7, 2.1, 2.1.1, 2.1.2, 2.1.3, 2.1.4, 2.1.5, 2.2-BETA1, 2.2-BETA2, Git Master
Fix Version/s: 2.2, 2.3, 2.x
Security Level: All

Type: Bug Priority: Critical
Reporter: Marco Pivetta Assignee: Benjamin Eberlei
Resolution: Invalid Votes: 0
Labels: None


 Description   

As of
https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/Proxy/ProxyFactory.php#L214
and
https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/Proxy/ProxyFactory.php#L237
the current ProxyFactory isn't actually checking if the identifier getter has logic in it.
Current checks aren't enough/valid.

In my opinion the check should be matching following:

(public|protected)\s+function\s+getFieldname\s*(\s*)\s+

{\s*\$this\s*->Fieldname\s*;\s*}

Not really experienced with regex, but currently cannot come up with a more secure check.



 Comments   
Comment by Benjamin Eberlei [ 15/Jan/12 ]

Can you explain why you think this is necessary?

You are right an id method with logic could exist in 4 lines of code, but for what purpose?

Comment by Marco Pivetta [ 15/Jan/12 ]

First of all it is a question of concept. Doctrine shouldn't assume anything about entities outside of their fields. It already introduces a level of complication when we explain how to clone/serialize objects, which was very confusing.

Asking for the purpose of an identifier field getter method is in my opinion again an attempt of making assumptions over user's code...

What if the user wrote something like:

public function getIdentifierField1()
{
return $this->identifierField1? $this->_myInitializationStuff() : null;
}

private function _myInitializationStuff()
{
//open files, check stuff, make things difficult for the D2 team
}

For instance, opening file handlers, sockets, whatever... This is a case that would break the entity because of optimization introduced by the ProxyFactory. (not to mention when getIdentifierField1 does some conversion, like return $this->identifierField1 + self::OFFSET_REQUIRED_BY_WEBSERVICE;

I'm not arguing about the validity of this optimization, but that the checks are too lazy.

I've read something about moving the ProxyFactory to common and using code scanner tools, and the check should be about applying the optimization only when the form is

return $this->identifierField1;

That's why I put the example of the regex. That would probably not be as safe as using some reflection-based tool, but surely more than just checking if the code is <= 4 lines...

Comment by Marco Pivetta [ 15/Jan/12 ]

Also don't know what stuff like EAccelerator (known in this Jira as of it's fantastic idea about stripping comments) would make the check of the 4 lines like.

Comment by Benjamin Eberlei [ 16/Jan/12 ]

This argument is void i just seen

A method:

public function getIdentifierField1()
{
   return $this->identifierField1? $this->_myInitializationStuff() : null;
} 

Will only used when the id is not set anyways.

In any other case Ids are Immutable and changing them in your code would break a lot more than just this smart proxy method generation.

Comment by Marco Pivetta [ 16/Jan/12 ]

Nope, this code actually works only if the ID is set
I'm not talking about changing IDs, it's just that getters and setters don't always reflect the class attributes...

Comment by Marco Pivetta [ 16/Jan/12 ]

As of IRC there's 3 ways (for now) to get this solved:

  • Some code scanner/stronger checks (difficult/problems with private methods/slow)
  • Regex (as of description)
  • Adding configuration (per-entity or per-method. Probably too messy)
  • Documenting it as "magic" of proxies and let the users be aware of it




[DDC-1568] A better quality control?? Created: 27/Dec/11  Updated: 27/Dec/11  Resolved: 27/Dec/11

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

Type: Improvement Priority: Critical
Reporter: Nurlan Turdaliev Assignee: Benjamin Eberlei
Resolution: Invalid Votes: 0
Labels: None


 Description   

The problem

I love doctrine, but I think you should control quality of your releases better.
Issues like this one - DDC-1504 makes doctrine smell bad.



 Comments   
Comment by Nurlan Turdaliev [ 27/Dec/11 ]

Hey guys, sorry for this ticket
I've checkouted doctrine tests, looked through 'em.
They are thorough and good.
The issue I linked in ticket happens because of misuse





[DDC-1548] One to one entity badly populated Created: 19/Dec/11  Updated: 19/Dec/11  Resolved: 19/Dec/11

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

Type: Bug Priority: Critical
Reporter: Asmir Mustafic Assignee: Guilherme Blanco
Resolution: Fixed Votes: 0
Labels: None
Environment:

ubuntu php 5.3.8


Attachments: File 1548.php    

 Description   

One to one entity over populated



 Comments   
Comment by Asmir Mustafic [ 19/Dec/11 ]

I have created a test.

the bug may be in \Doctrine\ORM\Internal\Hydration\AbstractHydrator at line 246.

i think...

remove
if ( ! isset($rowData[$dqlAlias][$cache[$key]['fieldName']]) || $value !== null) {

and replace with :

if ( ! isset($rowData[$dqlAlias][$cache[$key]['fieldName']]) && $value !== null) {

this will fix the bug

Comment by Guilherme Blanco [ 19/Dec/11 ]

Fixed since this commit: https://github.com/doctrine/doctrine2/commit/68663fac4b5619643b8a140d6bbe7031e4fa2ad5

Thanks a lot for the report and patch! =D

Comment by Benjamin Eberlei [ 19/Dec/11 ]

Update fix version, this was merged into 2.1.5





[DDC-1545] Update on loaded association not detected upon flush() Created: 18/Dec/11  Updated: 19/Dec/11  Resolved: 19/Dec/11

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

Type: Bug Priority: Critical
Reporter: Bernhard Schussek Assignee: Guilherme Blanco
Resolution: Fixed Votes: 0
Labels: None


 Description   

If an association is joined during fetching and then updated in-memory, the update is not detected during flushing. I made the following test cases:

Association is joined:

  • change NULL → entity: does not work
  • change entity → NULL: works
  • change entity1 → entity2: does not work

Assocation is not joined:

  • change NULL → entity: works
  • change entity → NULL: works
  • change entity1 → entity2: works


 Comments   
Comment by Bernhard Schussek [ 18/Dec/11 ]

See here for the test case: https://github.com/bschussek/doctrine-orm/tree/DDC-1545

Comment by Guilherme Blanco [ 19/Dec/11 ]

Increasing priority

Comment by Guilherme Blanco [ 19/Dec/11 ]

Issue fixed since this commit:

https://github.com/doctrine/doctrine2/commit/a8478d5766e2cc4185612af680b7f6bcd83af61e

Thanks a lot for the bug reporting. It was the second time someone reported me this issue and I could not reproduce! =)

Comment by Benjamin Eberlei [ 19/Dec/11 ]

This issue is referenced in Github Pull-Request GH-229
https://github.com/doctrine/doctrine2/pull/229

Comment by Benjamin Eberlei [ 19/Dec/11 ]

Related Pull Request was closed: https://github.com/doctrine/doctrine2/pull/229