[DDC-2795] the queryBuider Expr\Join class has a ON type but unsupported by the parser Created: 14/Nov/13  Updated: 14/Nov/13

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

Type: Bug Priority: Major
Reporter: Christophe Coevoet Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: documentation, dql, querybuilder,


 Description   

The Doctrine\ORM\Query\Expr\Join class has 2 cosntants for the condition types: WITH and ON.

None of them are documented. The only place where WITH appear is the EBNF, which is outdated in the doc as it does not show arbitrary joins (added in 2.3) but only association joins.

and when looking at the EBNF in the code, I find 2 different ones (none of them matching the one given in the doc):

  • in Doctrine\ORM\query\Parser::Join:
Join ::= ["LEFT" ["OUTER"] | "INNER"] "JOIN"
         (JoinAssociationDeclaration | RangeVariableDeclaration)
         ["WITH" ConditionalExpression]

This is matching the implementation and ON is not supported.

  • in Doctrine\ORM\Query\AST\Join:
Join ::= ["LEFT" ["OUTER"] | "INNER"] "JOIN" JoinAssociationPathExpression
         ["AS"] AliasIdentificationVariable [("ON" | "WITH") ConditionalExpression]

This one is missing 2 features also missing in the doc (INDEX BY for associations, and arbitrary joins) and adds the support of ON which is not implemented.

What is the reason to have this ON constant in the query builder ? It is confusing to get a DQL parse exception when using it if it is there.

On a side note, what is the canonical source for the EBNF ? There is 2 different locations in the code (the phpdoc of parser methods and the phpdoc of AST nodes created by the parser), plus the doc. Shouldn't we try to limit the duplication and have a way to check the consistency of the doc ?






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

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

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

Attachments: Zip Archive Testcase.zip    

 Description   

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

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

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

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

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



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

Hi Quintenvk

Could you please try to write a failing test case ?

Thanks

Comment by Quintenvk [ 18/Apr/13 ]

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

Apart from that all should run well immediately.

Comment by Quintenvk [ 18/Apr/13 ]

Fabio,

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

Thanks,
Quinten

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

Thanks Quintenvk,

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

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

Also the INDEX BY documentations seems wrong to me.

The given DQL :

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

Show the following result :

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

Which IMHO represents another DQL, something like :

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

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

Thanks,
Quinten

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

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

Something like :

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

or something like :

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

And than :

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

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

Thanks for your help though!





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

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

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

OSX



 Description   

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

This is what I am doing:

$parts = $qb->getDQLParts();

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

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


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

I wrote a test showing the issue.

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

Comment by Benjamin Eberlei [ 04/May/13 ]

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





[DDC-2185] Better explain DQL "WITH" and implications for the collection filtering API Created: 04/Dec/12  Updated: 17/Dec/12

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

Type: Documentation Priority: Major
Reporter: Matthias Pigulla Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: collection, documentation, dql, filtering


 Description   

Available documentation is a bit thin regarding the "WITH" clause on JOIN expressions. Only a single example is provided in

http://docs.doctrine-project.org/en/2.1/reference/dql-doctrine-query-language.html#dql-select-examples

WITH seems to allow to only "partially" load a collection, so the collection in memory does not fully represent the associations available in the database.

The resulting collection is marked as "initialized" and it seems there is no way to tell later on whether/how (with which expression) the collection has been initialized.

When using the collection filtering API, the "initialized" flag on the collection will lead to in-memory processing. If a collection has been loaded WITH a restricting clause and another filter is applied later, results may not be what one might expect.

I assume this is by design (no idea how the collection could be "partially" loaded and behave correctly under all conditions), so filing it as a documentation issue.



 Comments   
Comment by Matthias Pigulla [ 17/Dec/12 ]

An additional observation:

If you eager-load a collection using WITH, for the resulting entities that collection is marked as initialized as described above.

Should you happen to come across the same entity during hydration in another (later) context where you explicitly eager load the same association without the WITH restriction (or with another one), the collection on that (existing) entity won't be re-initialized and still contains the associated objects found during the first query.





[DDC-1947] Update EBNF with arbitrary joins Created: 26/Jul/12  Updated: 26/Jul/12

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

Type: Documentation Priority: Major
Reporter: Marco Pivetta Assignee: Marco Pivetta
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Arbitrary joins need to be documented in EBNF






[DDC-1894] Cannot view Doctrine 2.2 QueryBuilder documentation Created: 27/Jun/12  Updated: 27/Jun/12

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

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

Chrome, Firefox, Safari on OS X



 Description   

Visiting the following page:

http://www.doctrine-project.org/api/orm/2.2/class-Doctrine.ORM.QueryBuilder.html

always redirects back to http://www.doctrine-project.org/api/orm/2.2/






[DDC-1702] EBNF for IN expressions should be updated for 2.2 Created: 13/Mar/12  Updated: 13/Mar/12

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

Type: Documentation Priority: Major
Reporter: Patrick Schwisow Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 2
Labels: None


 Description   

Following the changes made for DDC-1472 and DDC-1416, the EBNF for InExpression should have been updated. It now takes an ArithmeticExpression instead of a SingleValuePathExpression.



 Comments   
Comment by Patrick Schwisow [ 13/Mar/12 ]

I marked this as "Major" because this change represents a BC break. Because EBNF was not updated, I initially believed this to be a bug in ORM and wasted a lot of time debugging Doctrine code before I discovered this change was intentional.





[DDC-1645] Paths to Annotations classes are not considered Created: 10/Feb/12  Updated: 10/Feb/12

Status: Open
Project: Doctrine 2 - ORM
Component/s: Documentation, Mapping Drivers
Affects Version/s: 2.2
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: feathers and down Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

openSUSE 12.1 x86, Apache/2.2.21, mysql 5.5.16, PHP 5.3.8 (modules: Core, ctype, curl, date, dom, ereg, filter, gd, hash, http, iconv, json, libxml, mbstring, mcrypt, mhash, mysql, mysqli, mysqlnd, pcre, PDO, pdo_mysql, pdo_sqlite, Reflection, session, SimpleXML, SPL, SQLite, sqlite3, standard, tokenizer, xml, xmlreader, xmlwriter, zip, zlib )


Attachments: Zip Archive bugtracker.zip    

 Description   

Hi, my battle is described here: http://groups.google.com/group/doctrine-user/browse_thread/thread/db9c77b6bc000f13

When I follow bugtracker tutorial I think that there is an error when working with Annotations, see these examples:

Start a new bugtracker project as described in tutorial from scratch, create folders and files as tutorial expose, then do following changes:

1) put Product, Bug, User class files at root level, same level as bootstraps files and create_xxxxx files
2) Create 'entities' folder, but leave it empty.
3) Create 'yaml' and 'xml' at root level too and add related files.
4) Open bootstrap and edit paths to Product, Bug and User class files to read from root files as in 1) so they can be read from scripts.

1) YAML
a) When using YAML as mapping driver you need a path to Setup::createYAMLMetadataConfiguration( ) method, I use this
Setup::createYAMLMetadataConfiguration(array(_DIR_."/yaml"), $isDevMode);
where "yaml" directory is same level as bootstraps and create_xxxxx files are. When executing script to create a product
Doctrine work as expected, creating a row inside table correctly.
b) If you comment line where class Product is included, the object can't be found at runtime and will throw an exception as expected.
c) With uncommented require Product line, change yaml name folder to anything, and Doctrine throw an exception (MappingException) as expected

so Setup method path argument is considered correctly, Doctrine engine must know where yaml files for classes are.

2) XML
a) When using XML as mapping driver you need a path to Setup::createXMLMetadataConfiguration( ) method, I use this
Setup::createXMLMetadataConfiguration(array(_DIR_."/xml"), $isDevMode);
where "xml" directory is same level as bootstraps and create_xxxxx files are. When executing script to create a product
Doctrine work as expected, creating a row inside table correctly.
b) If you comment line where class Product is included, the object can't be found at runtime and will throw an exception as expected.
c) With uncommented require Product line, change xml name folder to anything, and Doctrine throw an exception (MappingException) as expected

so Setup method path argument is considered correctly again, Doctrine engine must know where xml files for classes are.

3) Annotations
a) When using Annotations as mapping driver you need a path to Setup::createAnnotationsMetadataConfiguration( ) method, I use this
Setup::createAnnotationsMetadataConfiguration(array(_DIR_."/entities"), $isDevMode);
where "entities" directory is same level as bootstraps and create_xxxxx files are (but remember THEY ARE EMPTY). When executing script to create a product
Doctrine WORK AS EXPECTED, creating a row inside table correctly and still I don't know how if THERE IS NO Annotations files.
b) If you comment line where class Product is included, the object can't be found at runtime and will throw an exception as expected.
c) With uncommented require Product line, change name folder to anything, and Doctrine WILL NOT throw an exception, continue with execution.
d) Copy /Product.php to /entities/Product.php, then comment docblocks from /Product class (using // or delete them). When running script Doctrine throw a MappingException with message: "Class Product is not a valid entity or mapped super class", when as follow concepts from 1) (yaml) and 2) (xml) it should search docblocks from /entities/Product.php file (path argument from Setup), right?

so Setup method path argument IS NOT CONSIDERED, Doctrine engine use already defined classes to get Annotations docblocks using php reflexion classes, methods and functions.

How to deal with this? I mean...

a) Erase path argument from Setup::createAnnotationMetadataConfiguration methos (and similar functions for Annotations) because is not needed, classes and annotations must be defined before.
b) Add support to find docblocks from path argument when no valid dockblock is found from class definition, so entities classes can live without docblocks because they are found inside Setup path function argument, as YAML and XML do.

I know that is easy to follow tutorial guidelines to develop applications in Annotations point of view, load them before Doctrine script start (with require/include or autoloaders, etc) and will work, but I think that is wrong how tutorial and functional logic are given, so a) and b) are my proposed solutions. I think b) should be right, get dockblocks from a class already defined and if are not defined it follow XML and YAML logic: read metadata from other files.

Attachment: My bugtracker Netbeans project.

Sorry by my english






[DDC-1605] No documentation about the usage of indexes with YAML and XML Created: 16/Jan/12  Updated: 08/Apr/13

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

Type: Documentation Priority: Major
Reporter: Christian Stoller Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: documentation


 Description   

I am missing documentation about how to handle indexes in YAML and XML definition files. I had to search in the code to learn how to do that.
Please add some documentation about it.

This issue is related to #DDC-160 where the reporter asked for documentation about indexes in annotation mapping.

EDIT:
Maybe an example how I have done it with YAML would be helpful for others:

User:
  type: entity
  fields:
    id:
      id: true
      type: integer
      generator:
        strategy: IDENTITY
    email:
      type: string
      length: 150
      unique: true
    active:
      type: boolean
  indexes:
    indexActiveField: { name: idx_user_active, columns: [ active ] }

indexActiveField is the name of the index used by doctrine and idx_user_active is the name of the index in the database. The rest should be clear.



 Comments   
Comment by Christian Stoller [ 27/Sep/12 ]

Hi. I got an email notification that arbuscula has changed the status to "Awaiting Feedback". Do you need any feedback from me?





[DDC-1513] Missing documentation for using references in Docs Created: 28/Nov/11  Updated: 29/Nov/11

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

Type: Documentation Priority: Major
Reporter: Thomas Gray Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

I am in the process of switching over from Doctrine 2.0.7 to Doctrine 2.1 and one of the major missing components in my entities was the new use of using the mapping entity.

Example:

 
<?php
namespace My\Project\Entities;
use Doctrine\ORM\Mapping\Entity as ORM;
/**
 * @ORM\Entity(...)
 */
class Something
{
// Doctrine annotations here
}

The nessecity for this to be included in the entities is (as far as I can tell) nowhere to be found in the docs, so I am a little curious as to how people are supposed to know. I have also had a look here: http://www.doctrine-project.org/blog/doctrine-2-1-beta-release and can see no references too it.

Am I missing something; or is it really just missing from the docs?



 Comments   
Comment by Erik Bernhardson [ 28/Nov/11 ]

I also glanced through the docs and didn't find it. I would suggest it be added to the Annotations Reference page: http://www.doctrine-project.org/docs/orm/2.1/en/reference/annotations-reference.html

Comment by Thomas Gray [ 29/Nov/11 ]

Ahh, so there are some docs about it; http://www.doctrine-project.org/docs/common/2.1/en/reference/annotations.html however they do not seem to be that clear; nor well linked too.





[DDC-1475] Documentation for One-To-Many, Bidirectional Association does not have YAML example Created: 07/Nov/11  Updated: 07/Nov/11

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

Type: Documentation Priority: Major
Reporter: Christian Stoller Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

When you are looking for a config example for the bidirectional mapping of an one-to-many association you will just find an example with XML, but not with YAML or PHP. It would be nice if somebody could add an example or a link to the bidirectional one-to-one association, because it should be the same, right?

Here the link to the example: http://www.doctrine-project.org/docs/orm/2.0/en/reference/association-mapping.html#one-to-many-bidirectional






[DDC-1201] DQL Example about count(*) related entity is wrong Created: 10/Jun/11  Updated: 10/Oct/11

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

Type: Documentation Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: None


 Description   

DQL Example about count related entity is wrong



 Comments   
Comment by Aigars Gedroics [ 10/Oct/11 ]

Also similar DQL in documentation URL http://www.doctrine-project.org/docs/orm/2.1/en/reference/dql-doctrine-query-language.html#pure-and-mixed-results fails parsing stage:

$dql = "SELECT u, 'some scalar string', count(u.groups) AS num FROM User u JOIN u.groups g GROUP BY u.id";

with error

  [Doctrine\ORM\Query\QueryException]                                                                                                                         
  [Semantical Error] line 0, col 40 near 'localizations)': Error: Invalid PathExpression. StateFieldPathExpression or SingleValuedAssociationField expected. 

Should be "count(g.id)" instead of "count(u.groups)".





[DDC-1099] Tutorial :: Getting started code sample entity manager Created: 04/Apr/11  Updated: 11/Jul/11

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

Type: Documentation Priority: Major
Reporter: Gordon Franke Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

see pull request 24 on github.com



 Comments   
Comment by Michael Ridgway [ 11/Jul/11 ]

This issue should be closed: https://github.com/doctrine/orm-documentation/pull/24





[DDC-1089] Annotations reference examples are inaccurate and confusing Created: 30/Mar/11  Updated: 30/Mar/11

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

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

N.A.



 Description   

In chapter 19 of the reference guide some coding examples seem to be inaccurate or incorrect. Especially when it comes to the bidirectional many-to-many associations, this might be confusing.

Example:
The code fragment on http://www.doctrine-project.org/docs/orm/2.0/en/reference/annotations-reference.html#annref-manytomany has the following issues:

  • it does not include class declarations although the collections associated are both mentioned. It should be clear to which target entity they belong and therefore their classes should be declared.
  • from the context it seems that the associated classes should probably be User and Group, and the owning side is User. So the association should probably be inversed by 'users', although the example mentions 'features'.
  • the mapping for the inverse side maps a collection called $features, although this should probably be $users. Also the class declaration for the Group class is missing.

Some other code fragments in chapter 19 have similar issues. I think they could easily be replaced by the examples from the earlier chapters, like for the bidirectional man-to-many association the example from chapter 5:

http://www.doctrine-project.org/docs/orm/2.0/en/reference/association-mapping.html#many-to-many-bidirectional






[DDC-1088] Description for SequenceGenerator annotation options is wrong Created: 30/Mar/11  Updated: 26/Nov/13

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

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

N/A



 Description   

On paragraph 4.8.1.1 SequenceGenerator, the correct example should be:

<?php
class User {
/**

  • @Id
  • @GeneratedValue(strategy="SEQUENCE")
  • @SequenceGenerator(sequenceName="tablename_seq", initialValue=1, allocationSize=100)
    */
    protected $id = null;
    }


 Comments   
Comment by Steve Müller [ 26/Nov/13 ]

Is that still an issue? Seems it is fixed...





[DDC-1072] Private property mapping can cause issues, suggest changing to protected Created: 17/Mar/11  Updated: 17/Mar/11

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

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

not applicable



 Description   

The documentation recommends using private variables in entities. This can be problematic on entities with relations when using caching drivers as the proxy objects cannot access private variables and so the caching driver can throw notices like

...apc_store(): "_id" returned as member variable from __sleep() but
does not exist in ...

Making member variables protected resolves this issue when caching is enabled.

This information would be helpful on the documentation so others can be made aware of this issue. We spent a few days trying to debug the issue before understanding exactly what was going on.






[DDC-1011] Finding out if a model is persist Created: 02/Feb/11  Updated: 02/Feb/11

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

Type: Documentation Priority: Major
Reporter: Ronny Deter Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

To find out if a model is persist, is missing in the documentation of doctrine 2.

To become the state of an model you must call the entitymanager->getUnitOfWork()->getEntityState(model)






[DDC-993] Cookbook: Overriding the ID Generator during a database migration Created: 19/Jan/11  Updated: 28/Oct/12

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

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


 Description   

If you need to override the ID Generator, e.g. during a migration, you can do that in your migration script as follows:

Overriding the ID generator

$em->getClassMetadata('foo\bar\Entity')->setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator());
$em->getClassMetadata('foo\bar\Entity')->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_NONE'));

Make sure that both calls equal to the same generator type. You can now modify the @Id fields in your entities. Additionally, make sure that you set the IdGenerator after you created the database using e.g. SchemaTool->create().



 Comments   
Comment by Endre Kósa [ 27/Oct/12 ]

Hi, this doesn't seem to work for me. I have written a small database export / import utility. As long as I use the automatic ID generation, everything works flawlessly, but I'm trying to preserve the existing IDs. I do exactly what you've suggested in your post. It works for @OneToOne relations, but I get the following error messages when persisting entities that are parts of @ManyToOne relations:
Notice: Undefined index: [....] in [...]Doctrine/ORM/UnitOfWork.php on line 2655
I'm using version 2.2.2
Am I doing something wrong?

Comment by Endre Kósa [ 28/Oct/12 ]

Never mind. I've upgraded to Doctrine 2.3.0 and it works as expected.





[DDC-923] Add note about DateTime Query Parameter Type Hint Created: 10/Dec/10  Updated: 10/Dec/10

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

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





[DDC-919] subselect Created: 08/Dec/10  Updated: 20/Mar/11

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

Type: Documentation Priority: Major
Reporter: Mungiu Dragos Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 0
Labels: None


 Description   

i'd like to see more example in documentation with this subselects
[23:08] <beberlei> can you open a tciket on jira? then i dont forget to do that when i have time



 Comments   
Comment by Alberto [ 20/Mar/11 ]

Subselect as columns or FROM clause should have mor examples.





[DDC-2286] Update documentation for collation Created: 08/Feb/13  Updated: 08/Feb/13

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

Type: Documentation Priority: Minor
Reporter: Rickard Andersson Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: collation, documentation


 Description   

The documentation at http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/faq.html#how-do-i-set-the-charset-and-collation-for-mysql-tables clearly states that the collation should be set at database level and then inherited for all tables created.

Digging through the code and reading this issue http://www.doctrine-project.org/jira/browse/DDC-2139 it's clear that this is no longer the case.






[DDC-2227] Add details about developer being responsible of inverse side of an association Created: 09/Jan/13  Updated: 09/Jan/13

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

Type: Documentation Priority: Minor
Reporter: Marco Pivetta Assignee: Marco Pivetta
Resolution: Unresolved Votes: 0
Labels: None


 Description   

As far as I know, docs don't explain that it is up to the developer to keep the object graph consistent instead of relying on Doctrine ORM for everything.

For example, for many to many, examples like following may be used:
https://gist.github.com/3121916






[DDC-1983] Incorrect use statement in 25.1.3. Configuration example (Doctrine Console) Created: 15/Aug/12  Updated: 15/Aug/12

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

Type: Documentation Priority: Minor
Reporter: Atli Thor Jonsson Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: Cli, documentation


 Description   

The code example here:
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/tools.html#configuration-non-pear

In the second "use" statement it references a "EntityManagerHelper" from the "Doctrine\DBAL\Tools\Console\Helper\" package. However, it does not exist there. It does exist in the "Doctrine\ORM\Tools\Console\Helper\" package though, and replacing it seems to work.






[DDC-1921] Clarify Identifier definition for CTI entities Created: 11/Jul/12  Updated: 11/Jul/12

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

Type: Documentation Priority: Minor
Reporter: Ludek Stepan Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Hello,

Reference Guide topic 4.8 Identifers/Primary Keys(http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/basic-mapping.html#identifiers-primary-keys) states that: "Every entity class needs an identifier/primary key."

However, example in topic 7.3. Class Table Inheritance (http://docs.doctrine-project.org/projects/doctrine-orm/en/2.1/reference/inheritance-mapping.html#class-table-inheritance) doesn't contain any definitions for Ids.

Consider following code:

/**
 * @Entity
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="discr", type="string")
 * @DiscriminatorMap({"person" = "Person", "employee" = "Employee"})
 */
class Person
{
    /** @Id @Column(type="integer") */
    private $id;

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

/** @Entity */
class Employee extends Person
{
    /** @Id @Column(type="integer") */
    private $id;

    // Overrides parent to retrieve private
    public function getId() {
        return $this->id;
    }
}

// create instances and $em->persist(...)

// $person instanceof Person
$person->getId(); // Returns id.

// $employee instanceof Employee
$employee->getId(); // Returns null. Private $id in subclass isn't assigned.

Please clarify correct use of identifiers in CTI subclass entities. Should subclasses contain any definitions of identifiers?

Thank you!

Ludek






[DDC-1555] Reference. 8 Work. with obj. Making "see "Transitive Persistence"" as link Created: 22/Dec/11  Updated: 22/Dec/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: Documentation
Affects Version/s: 2.1, 2.1.1, 2.1.2, 2.1.3, 2.1.4, 2.1.5
Fix Version/s: None
Security Level: All

Type: Documentation Priority: Minor
Reporter: Yaroslav Kiliba Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

8. Working with Objects:
"... if the relationships from X to these other entities are mapped with cascade=PERSIST or cascade=ALL (see "Transitive Persistence")."
"... with cascade=REMOVE or cascade=ALL (see "Transitive Persistence")."
and so on.
Maybe it's reasonable to make "Transitive Persistence" as links to http://www.doctrine-project.org/docs/orm/2.1/en/reference/working-with-associations.html#transitive-persistence-cascade-operations






[DDC-1511] Suggestion on the docs for batch processing Created: 25/Nov/11  Updated: 25/Nov/11

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

Type: Documentation Priority: Minor
Reporter: Jamie Wong Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

br0wser



 Description   

I am refering to the examples on

http://www.doctrine-project.org/docs/orm/2.0/en/reference/batch-processing.html

Let's say you want to process a bulk of 25 objects and have a batchsize of 20.
With the code provided the last 5 would not be saved as far as I understand unless you do another flush after the for-loop.

This is probably very clear to any experienced Doctrine developer but maybe it is also confusing for beginners like me (some internet sources say, that flush is executed automatically at the end of the request, but obviously it is not). Maybe this could be mentioned somewhere?






[DDC-1405] Define semantics of comparison operators, particularly with regard to null values Created: 06/Oct/11  Updated: 12/Oct/11

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

Type: Improvement Priority: Minor
Reporter: Daniel Alvarez Arribas Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

The Doctrine 2 reference documentation defines the comparison operators syntactically, as:

ComparisonOperator  ::= "=" | "<" | "<=" | "<>" | ">" | ">=" | "!="

Now, without experimentation, it is pure guesswork to tell whether e. g. null = null, or e. g. null <> null, or null = 0, or null <> 0 are considered true statements in DQL.

In SQL semantics, all four statements would be false (or more precisely, null). In PHP semantics, both null == null and null == 0 would be true, while null != null and null != 0 would be false.

It would be helpful to have the semantics of the comparison operators defined. While comparisons with non-null values behave in a common-sense way, it is hard to guess how queries involving comparison operators on fields allowing null values or null query arguments will filter the results, without knowing the exact semantics of the comparison operators with regard to null values.

It would be great if this could be clarified in the docs.

Thanks.






[DDC-1329] Documentation for @JoinColumn may be incorrect Created: 13/Aug/11  Updated: 13/Aug/11

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

Type: Documentation Priority: Minor
Reporter: Damon Jones Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

The Documentation for @JoinColumn annotation states:
"This annotation is not required. If its not specified the attributes name and referencedColumnName are inferred from the table and primary key names."

However, this seems not to be correct. If you have non-standard name for the @Id columns for a @OneToMany/@ManyToMany the name and referencedColumnName are not correctly inferred.

https://gist.github.com/e61bf8f4462870ffd4f3






[DDC-1248] Documentation regarding prePersist and postPersist events a bit lacking Created: 04/Jul/11  Updated: 04/Jul/11

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

Type: Documentation Priority: Minor
Reporter: Helmer Aaviksoo Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Browser



 Description   

Please make it more clear that prePersist and postPersist events are called only when creating new entity (that is, prior and after a database insert).

IRC log:
helmer
Hi. I have a question regarding (pre|post)persist events. Why are the events ignored for second persist (should fire prePersist) + flush (should fire postPersist) in the following pastie: http://pastebin.com/V8CrPWkM Is it a bug or am I missing sth?
Stof
helmer: there is no second persist. persist() means saying Doctrine to manage the entity. Once it is managed, you are not persisting it anymore but updating it
helmer
Stof: so basically one could define these two events for themselves as (pre|post)Insert?
beberlei
yes
helmer
thanks beberlei&stof! though a suggestion to docteam .. perhaps make it more clear to people like me, current doc can be kind of misleading ie: "There are two ways for the prePersist event to be triggered. One is obviously when you call EntityManager#persist()" http://www.doctrine-project.org/docs/orm/2.0/en/reference/events.html#prepersist

Pastie code (probably expired by now):
$entity = new Entity();

$entity->setSomething('xxx');
$this->em->persist($entity);
$this->em->flush();

$entity->setSomething('yyy');
$this->em->persist($entity);
$this->em->flush();






[DDC-1058] Documentation on orphan removal in XML Mapping is incorrect Created: 04/Mar/11  Updated: 04/Mar/11

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

Type: Documentation Priority: Minor
Reporter: Josh Freed Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

The XML Mapping documentation indicates that "orphan-removal" is an attribute on One-to-One or Many-to-One elements, but in DoctrineORM version 2.0 that does not work. It seems I have to make "orphan-removal" a child attribute of those elements to turn it on.

Just to be clear:

Documentation says to do this, but it does not work:
<one-to-many field="..." orphan-removal="true"> ... </one-to-many>

This does work:
<one-to-many field="..."> <orphan-removal>true</orphan-removal> </one-to-many>






[DDC-1015] @DiscriminatorColumn is not required anymore Created: 03/Feb/11  Updated: 03/Feb/11

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

Type: Documentation Priority: Minor
Reporter: Karsten Dambekalns Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Since DDC-514 there is a default in place for this, thus the description is wrong in stating this is required.






[DDC-987] How to register lifecycle callbacks from YAML is not done correctly in the Events section of the documentation. Created: 14/Jan/11  Updated: 27/Nov/13

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

Type: Documentation Priority: Minor
Reporter: Amir Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

http://www.doctrine-project.org/docs/orm/2.0/en/reference/events.html

The above URL has an example of how to register lifecycle callbacks from YAML, but actually it does not work. The correct way of doing it is mentioned on the page: http://www.doctrine-project.org/docs/orm/2.0/en/reference/yaml-mapping.html



 Comments   
Comment by Jeremy Postlethwaite [ 27/Nov/13 ]

Please close this issue

Both pages now have the same documentation.

Doctrine example
  lifecycleCallbacks:
    prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersistToo ]
    postPersist: [ doStuffOnPostPersist ]
Partial stack trace exhibiting call:
/redacted-path/vendor/doctrine/orm/lib/Doctrine/ORM/Event/ListenersInvoker.php(73) : eval()'d code :: Tue, 26 Nov 2013 22:05:03 -0800 $eventName

prePersist

/redacted-path/src/Application/Modules/System/Entity/Sites.php(161) : eval()'d code :: Tue, 26 Nov 2013 22:05:03 -0800 $args

object(Doctrine\ORM\Event\LifecycleEventArgs)[839]
  private 'objectManager' (Doctrine\Common\Persistence\Event\LifecycleEventArgs) => 
    object(Doctrine\ORM\EntityManager)[330]
      private 'config' => 
        object(Doctrine\ORM\Configuration)[156]

/redacted-path/src/Application/Base.php(371) : eval()'d code :: Tue, 26 Nov 2013 22:05:03 -0800

#0 /redacted-path/src/Application/Modules/System/Entity/Sites.php(161): Application\Base::puke(Object(Doctrine\ORM\Event\LifecycleEventArgs), '/www/sites/loca...', true)
#1 /redacted-path/vendor/doctrine/orm/lib/Doctrine/ORM/Event/ListenersInvoker.php(104): Application\Modules\System\Entity\Sites->prePersist(Object(Doctrine\ORM\Event\LifecycleEventArgs))
#2 /redacted-path/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php(845): Doctrine\ORM\Event\ListenersInvoker->invoke(Object(Doctrine\ORM\Mapping\ClassMetadata), 'prePersist', Object(Application\Modules\System\Entity\Sites), Object(Doctrine\ORM\Event\LifecycleEventArgs), 2)
#3 /redacted-path/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php(1621): Doctrine\ORM\UnitOfWork->persistNew(Object(Doctrine\ORM\Mapping\ClassMetadata), Object(Application\Modules\System\Entity\Sites))
#4 /redacted-path/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php(1577): Doctrine\ORM\UnitOfWork->doPersist(Object(Application\Modules\System\Entity\Sites), Array)
#5 /redacted-path/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php(624): Doctrine\ORM\UnitOfWork->persist(Object(Application\Modules\System\Entity\Sites))
#6 /redacted-path/src/Application/Modules/Application/Controller/AbstractEntityFormActionController.php(128): Doctrine\ORM\EntityManager->persist(Object(Application\Modules\System\Entity\Sites))

My configuration was slightly different from the example.

  • Changed some of the details to protect the innocent.
My configuration inherited from a mappedSuperclass
  lifecycleCallbacks:
    prePersist: [ prePersist ]
    preFlush: [ preFlush ]




[DDC-986] bad cli commands in ORM introduction Created: 14/Jan/11  Updated: 15/Jan/11

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

Type: Documentation Priority: Minor
Reporter: Stepan Tanasiychuk Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

I read mini tutorial http://www.doctrine-project.org/docs/orm/2.0/en/reference/introduction.html#mini-tutorial and try run command "doctrine orm:schema-tool --drop"

TIP When you create new model classes or alter existing ones you can recreate the database schema with the command doctrine orm:schema-tool --drop followed by doctrine orm:schema-tool --create.

It's not worked for me:

[InvalidArgumentException]
Command "orm:schema-tool" is not defined.

But command "doctrine orm:schema-tool:drop --force" and "doctrine orm:schema-tool:create" is worked.
It's bug in documentation?






[DDC-740] Mantain a list of DQL reserved keywords Created: 09/Aug/10  Updated: 07/Aug/13

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

Type: Improvement Priority: Minor
Reporter: Guilherme Blanco Assignee: Guilherme Blanco
Resolution: Unresolved Votes: 0
Labels: None


 Description   

We should keep a list of DQ reserved keywords, so users can check out what they can use or not.



 Comments   
Comment by Manasi [ 07/Aug/13 ]

Here is the list of reserved keywords for MySQL: http://dev.mysql.com/doc/refman/5.0/en/reserved-words.html
The documentation does not clearly mention that the backticks for a column with a reserved keyword in the ORM mapping file. This file could be in xml, yaml or php.
So,the right way to apply backticks is: <field name="group" type="string" column="`group`" length="32" nullable="false"/>





[DDC-473] Inadequate description for @MappedSuperclass in Annotations Reference Created: 25/Mar/10  Updated: 26/Aug/10

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

Type: Improvement Priority: Minor
Reporter: David Abdemoulaie Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None


 Description   

See: http://www.doctrine-project.org/documentation/manual/2_0/en/annotations-reference#ann_mappedsuperclass

@MappedSuperclass

An mapped superclass is an abstract or concrete class that provides persistent entity state and mapping information for its subclasses, but which is not itself an entity. This annotation is specified on the Class docblock and has no additional attributes.

This doesn't adequately communicate how to use it. It took me several minutes of failing before I downloaded the PDF and did a search for @MappedSuperclass to find an example of how it's used.

Specifically the following were unclear:

  • Is this defined on the superclass or on the children classes?
  • If it's defined on the child classes, does it take parameters? The name of the super class?
  • It was not at all apparent to me that it was mutually exclusive with the @Entity tag


 Comments   
Comment by David Abdemoulaie [ 25/Mar/10 ]

Apparently it's also incompatible with several other tag as well.

I thought it made sense to try the following and see if the @InheritanceType and @Discriminator___ tags would apply to the children classes:

/**
 * @MappedSuperclass
 * @InheritanceType("SINGLE_TABLE")
 * @DiscriminatorColumn(name="type", type="string")
 * @DiscriminatorMap({"User" = "User", "Group" = "Group"})
 */
abstract class Principal

But apparently this flags D2 to treat it as an Entity anyway, resulting in the following error:

PDOException: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'sentact5.principal'
Comment by Benjamin Eberlei [ 28/Mar/10 ]

I updated the documentation, the question is if we should check for the mapped superclass attribute and throw exceptions if other entity level annotations are specified.

Comment by Roman S. Borschel [ 15/Apr/10 ]

A mapped superclass has not many restrictions and these are mentioned in the docs (i.e. only unidirectional associations), what David mentions above should work, if it doesnt its a bug, I think DDC-511 looks like that same issue.

Comment by Roman S. Borschel [ 15/Apr/10 ]

David,

@"Is this defined on the superclass or on the children classes?"

It doesnt matter. A @MappedSuperclass can be anywhere in an inheritance hierarchy and it always does the same thing, inherit its mapping information to subclasses (but its not itself an entity). The docs say:

Mapped superclasses, just as regular, non-mapped classes, can appear in the middle of an otherwise mapped inheritance hierarchy (through Single Table Inheritance or Class Table Inheritance).

as well as

Entities support inheritance, polymorphic associations, and polymorphic queries. Both abstract and concrete classes can be entities. Entities may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes.

So entities, mapped superclasses and plain non-mapped classes can appear mixed in an inheritance hierarchy. Nevertheless all the classes in a hierarchy that are entities must use 1 inheritance strategy, you can not mix inheritance mapping strategies in a single class hierarchy.

@"If it's defined on the child classes, does it take parameters? The name of the super class?"

No, it doesnt. The docs dont mention any parameters either which is correct.

@"It was not at all apparent to me that it was mutually exclusive with the @Entity tag"

OK, that needs to be made clearer in the docs then.





[DDC-1611] Tools Reference example is apparently wrong Created: 19/Jan/12  Updated: 20/Jan/12

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

Type: Documentation Priority: Trivial
Reporter: Tarcísio Fischer Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

I was reading http://www.doctrine-project.org/docs/orm/2.1/en/reference/tools.html
In 24.2.2. Configuration (Non-PEAR)

The example seems to be wrong.

use Doctrine\DBAL\Tools\Console\Helper\EntityManagerHelper;
should be
use Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper;

That's all.



 Comments   
Comment by craz [ 20/Jan/12 ]

Yes, this is a real problem.

fixation and helped me





[DDC-1003] Documentation refers to EAGER loading as FETCH Created: 26/Jan/11  Updated: 26/Jan/11

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

Type: Documentation Priority: Trivial
Reporter: jared fraser Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Throughout the documentation found in the following link (http://www.doctrine-project.org/docs/orm/2.0/en/reference/xml-mapping.html) when mentioning eager or lazy loading the documentation says FETCH instead of EAGER.

E.G. content says "fetch - Either LAZY or FETCH" which should read "fetch - Either LAZY or EAGER"

This occurs in a few different areas on this page.






[DDC-940] Entities can / can not have private properties Created: 15/Dec/10  Updated: 15/Dec/10

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

Type: Documentation Priority: Trivial
Reporter: Ray Rehbein Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 0
Labels: None
Environment:

PHP 5.3.3 (cli) (built: Nov 14 2010 16:54:26)



 Description   

In the note in
http://www.doctrine-project.org/docs/orm/2.0/en/reference/working-with-objects.html#merging-entities
It appears to state that private variables are not serialized for child objects

If this is the only reason entities can't have private properties, then this restriction is no longer valid, or possibly be reconsidered.

<?php

class A {
    private $a = null;

    public function setValue($value) {
        $this->a = $value;
    }
}

class B extends A {}

$b = new B();
$b->setValue("B");
var_dump($b);

$c = unserialize(serialize($b));
var_dump($c);

The output suggests private variables are serialized, and are restored fine






[DDC-2911] IndexBy doesn' work with arbitrary join Created: 13/Jan/14  Updated: 13/Jan/14

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

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


 Description   
        $statsQb = $em->createQueryBuilder()
            ->select('d AS date')
            ->from('MetalStatisticBundle:Day', 'd', 'd.date')
            ->leftJoin('MetalStatisticBundle:StatsDaily', 'sd', 'WITH', 'd.date = sd.date', 'sd.date')
            ->addSelect('sd AS stats')
            ->andWhere('sd.company = :company_id')
            ->setParameter('company_id', $company->getId())
            ->orderBy('sd.date', 'DESC')
            ->setMaxResults(10)

expected: array like

2012-10-10 => array(date => object, stats => object)
2012-10-09 => array(date => object)
2012-10-08 => array(date => object, stats => object)

got: exception Expected Literal, got 'BY'






[DDC-2870] Doctrine error when using SUM(a.id=1) as `ìdentifier`: Expected Doctrine\ORM\Query\Lexer::T_CLOSE_PARENTHESIS, got '=' Created: 22/Dec/13  Updated: 06/Jan/14

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

Type: Bug Priority: Major
Reporter: Maxim Geerinck Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: dql
Environment:

Symfony2 bundle



 Description   

Doctrine error when using SUM(a.id=1) as `ìdentifier`: Expected Doctrine\ORM\Query\Lexer::T_CLOSE_PARENTHESIS, got '='

I am trying to execute a query in doctrine that contains something like this

SUM(a.id = 1) as `1`
for some reasons it always gives me the following error:

[Syntax Error] line 0, col 15: Error: Expected Doctrine\ORM\Query\Lexer::T_CLOSE_PARENTHESIS, got '='
This is the code i am using

$result = $em->getRepository('MyBundle:PlayerAction')
->createQueryBuilder('pa')
->select(array(
'SUM(a.id=1) as `1`,
SUM(a.id=2) as `2`,
SUM(a.id=3) as `3`,
p.playerName,
pa.timestamp'
))
->innerJoin('pa.action', 'a')
->innerJoin('pa.player', 'p')
->where('pa.timestamp > ?1')
->groupBy('p')
->setParameter(1, time() - $time)
->orderBy('p.playerName', 'ASC');






[DDC-2787] COALESCE() doesn't work with NOT IN() Created: 09/Nov/13  Updated: 09/Nov/13

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

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


 Description   

When I try running the following query:

SELECT count(c.id) FROM my\model c WHERE COALESCE(c.up, 0) NOT IN( :parent_ids)

I get

Doctrine\ORM\Query\QueryException: [Semantical Error] line 0, col 118 near 'up, 0) NOT IN(': Error: Invalid PathExpression. Must be a StateFieldPathExpression.

When I run the query as straight SQL against the database, it works as expected. Is this something that can be fixed in Doctrine or is this syntax unsupported?






[DDC-2746] When generating DQL query entities with "Class Table Inheritance" is a SQL generated inconsistent Created: 16/Oct/13  Updated: 18/Oct/13

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

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

Attachments: File DDC2746Test.php     File DDC2746Test_original.php    

 Description   

When I run the query DQL involving entities "Class Table Inheritance" is a SQL generated inconsistent see this gist: https://gist.github.com/hugohenrique/b322e8d998c870265177



 Comments   
Comment by Hugo Henrique [ 17/Oct/13 ]

An example of incoherent generation of SQL:
https://gist.github.com/hugohenrique/b322e8d998c870265177





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

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

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

PostgreSQL



 Description   

The summary pretty much sums it up.

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






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

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

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

irrelevant



 Description   

Given a simple Joined Table Inheritance like following:

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

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

Following DQL

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

Will produce broken SQL:

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

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

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

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

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






[DDC-2223] unable to use scalar function when a scalar expression is expected Created: 04/Jan/13  Updated: 04/Jan/13

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

Type: Bug Priority: Major
Reporter: Alexis Lameire Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: dql
Environment:

(not affected by this bug)



 Description   

the DQL Parser don't parse properly functions when a ScalarExpression is needed like of all case functions.

In fact first function token is interpreted as a T_IDENTIFIER and enter on line 1663 of Doctrine\ORM\Query\Parser class. in search of math operator, when not found this case considere that the token is a row element with no considération of the functions procession treated after.

fix of this bug consist to enclose the line 1672 by a if (!$this->_isFunction()).






[DDC-2119] Problem with inheritance type: INHERITANCE_TYPE_NONE and INHERITANCE_TYPE_TABLE_PER_CLASS Created: 03/Nov/12  Updated: 08/Apr/13

Status: Open
Project: Doctrine 2 - ORM
Component/s: DQL, Tools
Affects Version/s: 2.1
Fix Version/s: None

Type: Bug Priority: Major
Reporter: SergSW Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: dql, schematool

Attachments: File dump.sql     File SSWTestBundle.rar    

 Description   

I tried to create inheritance entities with save policy table per class.
Simple fileds was created normally, but a field with ManyToOne type was lost.

I had found a solution.

In Doctrine\ORM\Tools\SchemaTool
...

private function _gatherRelationsSql($class, $table, $schema)
    {
        foreach ($class->associationMappings as $fieldName => $mapping) {

           // if (isset($mapping['inherited'])) { // - old version

	/**
             * SSW
             * It's the solution
             */
	if (isset($mapping['inherited']) && !$class->isInheritanceTypeNone() && !$class->isInheritanceTypeTablePerClass() ) {
                continue;
            }            

            $foreignClass = $this->_em->getClassMetadata($mapping['targetEntity']);
...

But it was enough. In DQL query a simple query was made wrong.

I had found a solution again.
In Doctrine\ORM\Query\SqlWalker
...

public function walkSelectExpression($selectExpression)
...

                // original => if (isset($mapping['inherited'])){
                // It's the solution
                if (isset($mapping['inherited']) && !$class->isInheritanceTypeNone() && !$class->isInheritanceTypeTablePerClass()) {
                    $tableName = $this->_em->getClassMetadata($mapping['inherited'])->table['name'];
                } else {
                    $tableName = $class->table['name'];
                }
...

This problems are topical for inheritance type: INHERITANCE_TYPE_NONE and INHERITANCE_TYPE_TABLE_PER_CLASS.

I don't know, may be my solutions are wrong. But some programmers want to correctly work with INHERITANCE_TYPE_TABLE_PER_CLASS.

Sorry for my english.



 Comments   
Comment by Fabio B. Silva [ 05/Nov/12 ]

Hi SergSW

Could you try to write a failing test case ?

Thanks

Comment by SergSW [ 06/Nov/12 ]

SSW/TestBundle with the problem

Comment by SergSW [ 07/Nov/12 ]

I install the Symfony v2.0.18. and made small TestBundle.
I made schema database, by CLI "console doctrine:schema:update --force"
Result: Database schema updated successfully!
But I saw that I lost a field 'user_id' in a table 'AttachTree' (see Attach)

Comment by SergSW [ 07/Nov/12 ]

MySQL dump

Comment by Benjamin Eberlei [ 12/Nov/12 ]

Adjusted example formatting, don't apologize for your English, thanks for the report!

Comment by Benjamin Eberlei [ 24/Dec/12 ]

What version of 2.1 are you using? We don't actually support 2.1 anymore. Inheritance has always worked as used in hundrets of unit-tests, this changes look quite major a bug to have been missed before. I can't really explain whats happening here.

Comment by Marco Pivetta [ 23/Jan/13 ]

SergSW news?





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

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

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

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

 Description   

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

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

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

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

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

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

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

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



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

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





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

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

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

Ubuntu 11.10



 Description   

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






[DDC-1602] Executors for Class Table Inheritance (JOINED) are extremely slow on MySQL Created: 15/Jan/12  Updated: 27/Jun/12

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

Type: Improvement Priority: Major
Reporter: Michael Moravec Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 3
Labels: None
Environment:

Debian, MySQL 5.5.17



 Description   

Update and delete executors for Class Table Inheritance (JOINED) are extremely slow on MySQL platform. It is most probably due to use of subselect on the temporary table.
The slowdown is really significant as the table size increases. As an example, lets have a root entity with one subclass:

/**
 * @Entity
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="discr", type="string")
 * @DiscriminatorMap({"root" = "Root", "a" = "SubA"})
 */
class Root
{
	/**
	 * @Column(type="integer")
	 * @Id
	 * @GeneratedValue
	 */
	private $id;

	/**
	 * @Column(type="integer")
	 */
	private $xyz;
}
/**
 * @Entity
 */
class SubA extends Root
{
	/**
	 * @Column(type="integer")
	 */
	private $foo;
}

Now lets perform a simple DQL UPDATE:

UPDATE Entities\Root r SET r.xyz = 123 WHERE r.id > ?

(note: always the upper half of entries)
Which creates following SQLs:

CREATE TEMPORARY TABLE Root_id_tmp (id INT NOT NULL)
INSERT INTO Root_id_tmp (id) SELECT t0.id FROM Root t0 LEFT JOIN SubA s0_ ON t0.id = s0_.id WHERE t0.id > 25000
UPDATE Root SET xyz = 123 WHERE (id) IN (SELECT id FROM Root_id_tmp)
DROP TEMPORARY TABLE Root_id_tmp

The time spent on this on MySQL 5.5.17 and PostgreSQL 9.1 is:

no. of entries 500 1000 2500 5000 10000 20000 50000
MySQL 0.26s 0.35s 1.1s 3.68s 14.13s 54.44s 338s
PostgreSQL 0.10s 0.10s 0.13s 0.15s 0.22s 0.35s 1.01s

As you can see, MySQL is drastically slower on even relatively small tables. This currently makes Doctrine unusable for this type of inheritance on MySQL. The solution probably would be to avoid subselect in WHERE clause in Doctrine\ORM\Query\Exec\MultiTableUpdateExecutor and Doctrine\ORM\Query\Exec\MultiTableDeleteExecutor.

Feel free to try/modify the test script yourself, it's here.



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

Its not a bug as it works. The performance drawback of JTI is discussed in the manual http://www.doctrine-project.org/docs/orm/2.1/en/reference/inheritance-mapping.html.

Changing this would be an improvement where we would hint if databases prefer subselects or joins for different operations. This would increase complexity of the SQL generation since now we are getting along with just one SQL generation strategy.

Comment by Michael Moravec [ 11/May/12 ]

Any chance to get this implemented before 2.3?

Comment by Michael Moravec [ 11/May/12 ]

I've made a change in DBAL and ORM code to implement a solution issue. It's currently more likely a proof of concept.

With the change, my results are (approximately):

no. of entries 500 1000 2500 5000 10000 20000 50000
MySQL 0.17s 0.19s 0.21s 0.26s 0.27s 0.37s 0.92s

Currently only update executor was changed.
DBAL branch with changes: https://github.com/Majkl578/doctrine-dbal/tree/DDC-1602
ORM branch with changes: https://github.com/Majkl578/doctrine2/tree/DDC-1602

Looking forward for your opinions.

Comment by Michael Moravec [ 27/Jun/12 ]

bump





[DDC-1465] Fetching partial objects doesn't work if HINT_FORCE_PARTIAL_LOAD is not explicitly used Created: 02/Nov/11  Updated: 11/Nov/11

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

Type: Bug Priority: Major
Reporter: Julien Pauli Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: None

Issue Links:
Duplicate
duplicates DDC-624 Partial object query that leaves out ... Open

 Description   

Using the DQL "partial" keyword is not enough to get a partial entity as a result.
The DQL hint HINT_FORCE_PARTIAL_LOAD must be used as well.

$q = $em->createQuery('SELECT partial r.{id,comment} FROM Entities\Rating r WHERE r.id=3');
$r = $q->getResult() /* HYDRATE_OBJECT is the default hydration mode */

Here, $r contains the full Entity, a SELECT * has been sent

$q = $em->createQuery('SELECT partial r.{id,comment} FROM Entities\Rating r WHERE r.id=3');
$q->setHint(Doctrine\ORM\Query::HINT_FORCE_PARTIAL_LOAD, 1);

$r = $q->getResult() /* HYDRATE_OBJECT is the default hydration mode */

Here, $r contains only the selected fields, hence a true partial Entity






[DDC-726] DQL should deal correctly with composite primary keys Created: 30/Jul/10  Updated: 04/Oct/11

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

Type: Improvement Priority: Major
Reporter: Guilherme Blanco Assignee: Guilherme Blanco
Resolution: Unresolved Votes: 1
Labels: None

Issue Links:
Duplicate
is duplicated by DDC-1162 Add support for multi-column IN state... Resolved

 Description   

DQL should deal correctly with composite primary keys:

SELECT u FROM User u WHERE u.CompositeAssocEntity = ?1

Should be converted to:

SELECT ... FROM users u WHERE (u.cae_id1, u.cae_id2) = (?, ?) // or something similar

It also supports IN expressions:

SELECT u FROM User u WHERE u.CompositeAssocEntity IN (?1, ?2)

Should be converted to:

SELECT ... FROM users u WHERE (u.cae_id1, u.cae_id2) IN ((?, ?), (?, ?)) // or something similar

MySQL, SQLite and PgSQL works smoothly.
Need to check out MSSQL, Oracle and DB2.






[DDC-349] Add support for specifying precedence in joins in DQL Created: 18/Feb/10  Updated: 01/May/13

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

Type: Improvement Priority: Major
Reporter: Dennis Verspuij Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 1
Labels: None

Attachments: Text File DDC349Test.patch    
Issue Links:
Duplicate
is duplicated by DDC-1256 Generated SQL error with DQL WITH and... Resolved

 Description   

This request is in followup to my doctrine-user message "Doctrine 2.0: Nested joins'.
I am a bit surprised by the responses in that defining precedences in joins by placing parenthesis around join expressions is not well-known. Although not in the original SQL92 specification it is a major and important feature offered by all the RDBMS's that Doctrine 2 supports, and oftenly performs better than using subselects or alike. Doctrine 1 did not support it, but imho Doctrine 2 should support it to be a mature allround ORM.

As a short example the following is a SQL statement with a nested join, where the nesting is absolutely necessary to return only a's together with either both b's and c's or no b's and c's at all:

SELECT *
FROM a A
LEFT JOIN (
b B
INNER JOIN c C ON C.b_id = B.id
) ON B.a_id = A.id

In order for Doctrine 2 to support this the BNF should be something like:
Join ::= ["LEFT" ["OUTER"] | "INNER"] "JOIN" ( "(" JoinAssociationPathExpression ["AS"] AliasIdentificationVariable Join ")" | JoinAssociationPathExpression ["AS"] AliasIdentificationVariable ) [("ON" | "WITH") ConditionalExpression]
instead of the current:
Join ::= ["LEFT" ["OUTER"] | "INNER"] "JOIN" JoinAssociationPathExpression ["AS"] AliasIdentificationVariable [("ON" | "WITH") ConditionalExpression]

This would allow DQL like:

SELECT A, B, C
FROM a A
LEFT JOIN (
A.b B
INNER JOIN B.c C
) WITH B.something = 'value' AND C.something = 'othervalue'

What further needs to be done is that the DQL parser loosly couples the ConditionalExpression to any of the previously parsed JoinAssociationPathExpression's instead of tieing it explicitely to the JoinAssociationPathExpression that preceedes it according to the old BNF notation. The new BNF should however not require any changes to the hydrator. Therefore I have the feeling that improving the DQL parser for nested joins does not require extensive work, while the benefit of running these kind of queries is considerable.

As an extra substantiation here are links to (BNF) FROM clause documentations of the RDBMS's that Doctrine 2 supports, they all show support for nested joins:
MySQL: http://dev.mysql.com/doc/refman/5.0/en/join.html
PostgreSQL: http://www.postgresql.org/docs/8.4/interactive/sql-select.html#SQL-FROM and http://www.postgresql.org/docs/8.1/interactive/explicit-joins.html
MSSQL: http://msdn.microsoft.com/en-us/library/ms177634.aspx
Oracle: http://download.oracle.com/docs/cd/E11882_01/server.112/e10592/statements_10002.htm#CHDDCHGF
SQLite: http://www.sqlite.org/syntaxdiagrams.html#single-source

I surely hope you will consider implementing this improvement because it would save me and others from the hassle of writing raw SQL queries or executing multiple (thus slow) queries in DQL for doing the same. Thanks anyway for the great product so far!



 Comments   
Comment by Guilherme Blanco [ 13/Apr/10 ]

This seems to be a valid issue to me.

This implementation is the actual solution to associations retrieval that are inherited (type joined).

Example:

/** Joined */
class Base {}

class Foo extends Base {}

class Bar {
    public $foo;
}

// This causes the CTI to link as INNER JOIN, which makes the result become 0
// il if you have no Foo's defined (although it should ignore this)
$q = $this->_em->createQuery('SELECT b, f FROM Bar b LEFT JOIN b.foo f'); 
Comment by Roman S. Borschel [ 13/Apr/10 ]

Yes, this is a possible solution for DDC-512 but on the SQL level. I still don't see this as appropriate for DQL, it just doesnt make sense to me, DQL joins object associations, there is no precedence.

Comment by Roman S. Borschel [ 13/Apr/10 ]

So, no, this has nothing to do with DDC-512. DDC-512 can even be fixed differently as outlined in my comments there.

Comment by Roman S. Borschel [ 13/Apr/10 ]

On a side note I would still like to know/see the following for this issue:

  • Some realisitic DQL examples where this feature would be essential, i.e. there is no other way to do it.
    This also means explaining what the impact on the resulting object graph is and why it makes sense.
  • Which other ORMs support this on the OQL/Criteria level?

So far, my stance on this issue is:

1) It doesnt make sense (semantically) in DQL
2) Its rarely needed
3) When you really need it you can use a NativeQuery anyway and use this nesting in SQL, where it probably belongs and makes more sense
4) It would (unnecessarily) complicate DQL

Thus I am currently leaning towards "Wont fix" for this issue.

Comment by Dennis Verspuij [ 13/Apr/10 ]

Hi Roman. I understand your doubts, and I have been breaking my head over
creating a realistic example the last few hours that would hopefully convince
you for implementing this feature. But actually I cannot find one that you wouldn't
consider to be trivial. I do have a number of very complex optimized queries written
for sportskickoff dot com (using Doctrine 1.2) but they are probably hard to understand
because they may not be selfdescribing. Below is one example literally ripped from
the application. Still they often can be broken down to my example query in this
ticket's description, but applied grouping, additional other joins on the root component
and/or other criteria made them impossible to rewrite using subselects or choosing
another root component. Most often they just performed way best using the nested
syntax and saved me a number of additional queries.

SELECT A.id, A.username, A.balance, COALESCE(SUM(B.stake), 0) AS sumstake, COUNT(B.id) AS nrbets
FROM account A
LEFT JOIN (
bet B
INNER JOIN game G ON G.id = :GAMEID AND B.timestampcompletion BETWEEN G.timestampstart AND G.timestampend
) ON B.accountid = A.id AND B.timestampcompletion IS NOT NULL
WHERE A.Status & :ACTIVEORDISQUALIFIED = :ACTIVE
GROUP BY A.id, A.username, A.balance
ORDER BY A.balance DESC, sumstake ASC, nrbets ASC, A.username ASC

But let's put it another way. I would also like this feature to be supported in DQL
because I just do not want to use native queries. Why would I want to use native
queries if it can be done using DQL? In DQL I work with class names and field
names, and they may differ from the underlying table and column names. Doctrine
takes care of that mapping based on my schema/annotations and I do not
have to "know" these mappings. In native queries I suddenly do have to "know"
these mappings. I use Doctrine because it makes my application portable and
enables me to work with my database in an OOP way like I do in my model,
abstracting things. The need for native queries partly reverts the benefits Doctrine
offers in the first place.

Btw, I recall to have successfully used the nested join syntax in HQL (.NET Hibernate)
but I cannot find examples on the web or a BNF notation.

Furthermore, in reply to your stances:
1) It indeed doesnt make sense (semantically) in DQL, it only makes the result
set different, but not the way data is hydrated into objects;
2) Its indeed rarely needed for inserting, updating and populating basic lists but
it allows you to better select what combinations of associated rows are joined
and which not in more optimized queries without having to use native queries,
or because they perform better than using subseletcs and alike.
3) Not having to use native queries is just an extra reason for using Doctrine and
maintains the abstraction the ORM provides througout on'es whole application
4) Why would it complicate DQL, if people do not know about or understand
the feature it wouldn't matter because not using parenthesises is the default
way to specify joins?

Well, this is it, can't find any more words to promote and make you enthusiastic.... lol.

Comment by Dennis Verspuij [ 13/Apr/10 ]

Ok, I have not given up yet... , here's a "stupid" example.

Imagine a book store that sells books of various authors and keeps track of those sales.
Let's say you would have an admin page that lists all authors, and for each author
its also shows the books and their sales dates since january 1st, but only for those
books that were actually sold and contain an A in its name. An optimized SQL query
to fetch all the information at once would be something like:

SELECT A., B., S.*
FROM author A
LEFT JOIN (
book B
INNER JOIN sale S ON S.book_id = B.id AND S.dt >= '2010-01-01'
) ON B.author_id = A.id AND A.name LIKE '%A%'

In DQL it would then be something like:

SELECT A., B., S.*
FROM author A
LEFT JOIN (
book B
INNER JOIN sale S WITH S.dt >= '2010-01-01'
) WITH A.name LIKE '%A%'

If the database would contain thousands of books, but sales for just a
few books, this will definitely perform better than using subselects.
Off course one would like to fetch array graphs instead of objects for
further optimization, but this hopefully shows my point.

I have attached a test casefor a similar query, though without the additional
join constraints for clarity. I surely hope you can consider it.

One last note, you shouldn't be afraid that nesting joins is not in the
ansi SQL spec. Select queries are about record sets and products
between these sets, tables are just the basic means of providing record
sets to the query. This is an important terminological difference to think about.
Specifying precedence with parenthesis around joins is a logical and
natural evolution of the ansi sql standard. For example views are a good
proof of this concept, I could define book B INNER JOIN sale S as a view
and LEFT JOIN that to authors to get effectively the same result
set as the above example. The database server would internally perform the
same query (though may additionally take indexes on the view into account).
That said, rdbm's that support this syntax would certainly never drop the
feature, as its not a feature but just plain logical and smart querying!

P.S. I had a hard time finding out how to run the test cases, I could not find
it in the Doctrine 2 documentation, development wiki, cookbook or any other
place, while finally it was as easy as running phpunit Doctrine_Tests_AllTests
from within the tests/ directory, or just phpunit Doctrine_Tests_ORM_Functional_Ticket_DDC349Test
for my test. Could you please add some info about this somewhere, it might
save others some googling.

Comment by Dennis Verspuij [ 13/Apr/10 ]

Test case as SVN patch using a parenthesized join.
Just remove the parenthesises from the query to have it fail...

Comment by Roman S. Borschel [ 29/May/10 ]

@"The need for native queries partly reverts the benefits Doctrine offers in the first place."

That is something I hugely disagree with. Neither SQL abstraction, nor database vendor independence is the main purpose of an ORM like Doctrine 2.
It is the state management of your objects, the transparent change tracking, lazy-loading and synchronization of the object state with the database state and nothing of this gets lost when using native queries.

We could rip out DQL and any other querying mechanism except a basic find() (and lazy-loading, of course), only providing the native query facility and even only supporting MySQL and would still retain all the core ORM functionality.

NativeQuery is one of the best and core "features" of the project. It is even the foundation for DQL. A DQL query is nothing more than an additional (beautiful) abstraction but what comes out is a native query + a ResultSetMapping, the same thing you can build yourself in the first place, even using the mapping metadata to construct the query. Nothing forces you to hardcode table and column names in native queries if you don't want that. Just use the mapping metadata, DQL does the same.

SQL abstraction and database vendor independence is icing on the cake, not the heart of the ORM.





[DDC-138] Allow for mixed inheritance mapping Created: 12/Nov/09  Updated: 24/Dec/10

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

Type: New Feature Priority: Major
Reporter: Reinier Kip Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 3
Labels: None

Issue Links:
Duplicate
is duplicated by DDC-265 Possibility for Nested Inheritance Open

 Description   

Requesting implementation of mixed inheritance mapping (class table inheritance and single table inheritance).

This would be especially handy when the difference between certain classes is only "implementational" (i.e. a subclass only functions differently/implements abstract methods and does not specify any additional fields). Using class table inheritance would result in tables only containing an id column.






[DDC-3108] Criteria cannot reference a joined tables' fields when used with an ORM QueryBuilder Created: 30/Apr/14  Updated: 30/Apr/14

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

Type: Bug Priority: Major
Reporter: Chris Rog Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: criteria, dql, orm, querybuilder


 Description   

This regression was introduced in 2.4.2 with the addition of the "rootAlias" stuff. Basically, the hard-coded addition of the rootAlias + "." prevents any Criteria object from referencing any field that isn't on the first table selected.

Example:
// Assume $repo is a valid EntityRepository and $value is some scalar value.
$qb = $repo->createQueryBuilder('T1')->join('T1.field', 'T2');

$criteria = new Comparison('T2.field2', Comparison::EQ, $value);

$qb->addCriteria($criteria);
$dql = $qb->getDQL();

$dql is now (roughly) equal to:
SELECT T1 FROM <entityclass> T1 JOIN T1.field T2 WHERE T1.T2.field2 = <value>

Evaluating this causes QueryExceptions to be thrown; usually something along the lines of "Expected Doctrine\ORM\Query\Lexer::<token>, got '.'"

There's a similar issue involving ordering by a related field for the same reason.






[DDC-3063] Unexpected behavior with 'WHERE NOT IN' and empty array Created: 01/Apr/14  Updated: 06/May/14

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

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

CentOS, PHP 5.4, mysql



 Description   

I tried to set version to 2.4.0 but was prevented.

Assume the set 'n' contains 10 records, all with id > 0.

->andWhere('n.id NOT IN (:ids)')->setParameter('ids', [])
returns 0 records.

->andWhere('n.id NOT IN (:ids)')->setParameter('ids', [0])
returns 10 records.


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

This is a simple misunderstanding of how SQL IN() works

Comment by Tim Stamp [ 01/Apr/14 ]

You're right that its invalid SQL, but this is DQL. In SQL this would raise an error, in DQL it says nothing and returns nothing.

Isnt there a way to check if a statement has caused this error?

Comment by Marco Pivetta [ 01/Apr/14 ]

Tim Stamp yeah, when using IN() and NOT IN() you should actually check if the parameters are empty or not before adding the clause.

Comment by Steve Müller [ 01/Apr/14 ]

It's still weird that no error is raised by that. Tim Stamp can you check what SQL is generated by your query?

Comment by Steve Müller [ 01/Apr/14 ]

Hehe I think I got the problem. It might be DBAL related. See:

https://github.com/doctrine/dbal/blob/master/lib/Doctrine/DBAL/SQLParserUtils.php#L140
https://github.com/doctrine/dbal/blob/master/lib/Doctrine/DBAL/SQLParserUtils.php#L169

Looks like the implementing person did that by intention but don't ask me why.

Comment by Marco Pivetta [ 01/Apr/14 ]

Thats to avoid having an SQL statement like

SELECT * FROM foo WHERE bar IN()

, which is invalid.

Indeed, the NOT IN() case is not contemplated by that.

Comment by Steve Müller [ 01/Apr/14 ]

Just wondering if that kind of implementation isn't changing expectations because it looks like IN(NULL) will select all NULL rows then, even though this is not explicitly requested by the user. I don't care really TBH but this behaviour is not very transparent to the user. Personally I would like to see an error instead... Then at least I know what's going on and can fix that by additional checks instead.

Comment by Marco Pivetta [ 01/Apr/14 ]

Makes sense. Re-opening.

Comment by Steve Müller [ 01/Apr/14 ]

The question is if we can change this behaviour without breaking applications that rely on the current one. Because changing the code to throw an error breaks applications that insist on returning 0 rows for an empty array. I don't know what rules apply here concerning BC. What do you think Marco Pivetta?

Comment by Marco Pivetta [ 01/Apr/14 ]

Steve Müller existing apps should do following anyway:

if ($productIds) {
    $qb->andWhere('p.id IN (:productIds)')->setParameter('productIds', $productIds);
}

If they are not, that's most likely a bug in their codebase.

Comment by Steve Müller [ 01/Apr/14 ]

Agree. Was just wondering about what we can expect and what we can't expect.

Comment by Guilherme Blanco [ 21/Apr/14 ]

Steve Müller feel free to patch DBAL.
It's a bug, not a supported feature. If we have 2 tickets:
1- If I pass an empty array, I get nullable rows and I can't fix this
2- If I pass an empty array, it used to return nullable rows, now it returns nothing
Which one would you fix?

Comment by Tim Stamp [ 06/May/14 ]

Guilherme Blanco shouldn't both these use cases throw an exception, as both cases in MySQL would return an error?





[DDC-3136] DQL JOIN association return null Created: 24/May/14  Updated: 24/May/14

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

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

Symfony2



 Description   

Hello,
I observe a strange behavior of a query result done by DQL (only tested DQL in fact). In the last entry of my result, the joined entity are returned to null

My tables are:

Entity1
/**
 * @ORM\Table(name="entity1")
 * @ORM\Entity()
**/
class Entity1
{	
	 /**
     * @ORM\Column(name="entity1_id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
	protected $entity1_Id; 
	
	/**
	* @ORM\Column(name="entity1_text", type="string")
	*/
    protected $entity1_Text;
}
Entity2
/**
 * @ORM\Table(name="entity2")
 * @ORM\Entity()
**/
class Entity2
{	
        /**
	* @ORM\OneToOne(targetEntity="Entity1")
	* @ORM\JoinColumn(name="entity1_id", referencedColumnName="entity1_id")
	* @ORM\Id
	*/
	protected $entity1_id; 
    
	/**
	* @ORM\ManyToOne(targetEntity="Entity3")
	* @ORM\JoinColumn(name="entity3_id", referencedColumnName="entity3_id")
	*/
	protected $entity3; 
}
Entity3
/**
 * @ORM\Table(name="entity3")
 * @ORM\Entity()
**/
class Entity3
{	
	 /**
     * @ORM\Column(name="entity3_id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
	protected $entity3_Id; 
	
	/**
	* @ORM\Column(name="entity3_text", type="string")
	*/
    protected $entity3_Text;
}

So when I do a simple request like this:

DQL Request
SELECT ent2, ent3 FROM f4cIndexBundle:Entity2 ent2 JOIN ent2.entity3 ent3

The result is looks like this

Result NOK
array (size=2)
  0 => 
    object(f4c\IndexBundle\Entity\Entity2)[550]
      protected 'entity1_id' => 
        object(Proxies\__CG__\f4c\IndexBundle\Entity\Entity1)[502]
          ...
      protected 'entity3' => 
        object(f4c\IndexBundle\Entity\Entity3)[497]
          protected 'entity3_Id' => int 2
          protected 'entity3_Text' => string 'TEXT OF ENTITY 3 - SPECIFIC 2' (length=29)
  1 => 
    object(f4c\IndexBundle\Entity\Entity2)[498]
      protected 'entity1_id' => 
        object(Proxies\__CG__\f4c\IndexBundle\Entity\Entity1)[499]
          ...
     protected 'entity3' => null

The entity3 of the last result is never joined and set to null (it's not possible because of the JOIN no ?)
I spent to days on this and I observed that when I add a property in my entity 2 like this

Entity2
/**
 * @ORM\Table(name="entity2")
 * @ORM\Entity()
**/
class Entity2
{	
    ...
    /**
	* @ORM\Column(name="entity2_text", type="string")
	*/
    protected $entity2_Text;
}

The result is ok

Result OK
array (size=2)
  0 => 
    object(f4c\IndexBundle\Entity\Entity2)[550]
      protected 'entity1_id' => 
        object(Proxies\__CG__\f4c\IndexBundle\Entity\Entity1)[498]
         ...
      protected 'entity2_Text' => string 'TEXT2' (length=5)
      protected 'entity3' => 
        object(f4c\IndexBundle\Entity\Entity3)[499]
          protected 'entity3_Id' => int 1
          protected 'entity3_Text' => string 'TEXT OF ENTITY 3 - SPECIFIC 1' (length=29)
  1 => 
    object(f4c\IndexBundle\Entity\Entity2)[494]
      protected 'entity1_id' => 
        object(Proxies\__CG__\f4c\IndexBundle\Entity\Entity1)[495]
          ...
      protected 'entity2_Text' => string 'TEXT1' (length=5)
      protected 'entity3' => 
        object(f4c\IndexBundle\Entity\Entity3)[496]
          protected 'entity3_Id' => int 2
          protected 'entity3_Text' => string 'TEXT OF ENTITY 3 - SPECIFIC 2' (length=29)

Is it normal ? Is this a kwon issue ?

Thanks for your help

Raphael P.






[DDC-3215] wrong quotation Created: 16/Jul/14  Updated: 17/Jul/14

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

Type: Bug Priority: Major
Reporter: revrev Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: dql, orm


 Description   

when doctrine build query´s, for example when you doing

$entitity->getTest()->clear();

following queries are generated (test_id is integer in mysql):

DELETE FROM test WHERE test_id = '6'

Is this right?
For me the right query would be:

DELETE FROM test WHERE test_id = 6

as in http://dev.mysql.com/doc/refman/5.5/en/type-conversion.html
6 will be converted to float, this can be an issue, or?

Comparisons that use floating-point numbers (or values that are converted to floating-point numbers) are approximate because such numbers are inexact. This might lead to results that appear inconsistent:

mysql> SELECT '18015376320243458' = 18015376320243458;
        -> 1
mysql> SELECT '18015376320243459' = 18015376320243459;
        -> 0

this also happens in dql sometimes, why doctrine does this not automatic right due to description in the entities?

     /**
     * @ORM\Id @ORM\Column(type="integer")
     * @ORM\GeneratedValue
     */


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

Could you please convert this to a failing test case? Doctrine doesn't quote integers as strings by default.

Comment by revrev [ 16/Jul/14 ]

i try to describe what i have done

i have an Entity with:

    /**
     * @ORM\ManyToMany(targetEntity="Messen", inversedBy="vertrag_messen")
     * @ORM\JoinTable(name="vertrag_messen")
     **/
    private $vertrag_messen;

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

    public function getMessen()
    {
        return $this->vertrag_messen;
    }

when i now clear the Data

$entitity->getMessen()->clear();

following query is created
DELETE FROM vertrag_messen where messe_id = '6'

Should here not set the value 6 as integer (param_int) (DELETE FROM test vertrag_messen where messe_id = 6) that mysql doesn´t have to cast the value? (http://dev.mysql.com/doc/refman/5.5/en/type-conversion.html) or is this not an problem?

Comment by Marco Pivetta [ 16/Jul/14 ]

is messe_id in your entity an integer or a string at the moment in time when that query is being executed?

Comment by revrev [ 16/Jul/14 ]

the value comes automatic
$entitity = $em->getRepository('Base\Entities\Vertrag')>find(intval($data["id"]));

i don´t set messe_id here

Comment by Marco Pivetta [ 16/Jul/14 ]

Can you var_dump the Base\Entities\Messe instance?

Comment by revrev [ 16/Jul/14 ]

object(stdClass)#1014 (64) {
["__CLASS__"]=>
string(24) "Base\Entities\Vertrag"
["id"]=>
int(6)
[„vertrag_messen"]=>
array(1)

Unknown macro: { [0]=> string(20) "BaseEntitiesMessen" }


["erstellungsdatum"]=>
object(stdClass)#1210 (3)

Unknown macro: { ["__CLASS__"]=> string(8) "DateTime" ["date"]=> string(25) "2013-09-28T00}

["zeitraumvon"]=>
NULL
["zeitraumbis"]=>
NULL
["jahr"]=>
int(2014)
["created"]=>
object(stdClass)#1178 (3)

Unknown macro: { ["__CLASS__"]=> string(8) "DateTime" ["date"]=> string(25) "2013-09-28T19}

["updated"]=>
object(stdClass)#1177 (3)

Unknown macro: { ["__CLASS__"]=> string(8) "DateTime" ["date"]=> string(25) "2014-07-16T17}

["uuid"]=>
string(36) "52470c58-4288-45eb-b75f-0c41c0a81437"
}

Comment by Marco Pivetta [ 17/Jul/14 ]

yeah, integer identifier there.
Could you verify if the problem also comes up with current master? I think this issue is related with another one that was fixed some months ago in 2.5.x-dev





[DDC-2938] Support all time intervals on DATE_ADD Created: 27/Jan/14  Updated: 27/Jan/14

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

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


 Description   

The DATE_ADD built-in function of Doctrine supports only the "hour", "month" and "day" intervals. I don't see the point of not having all the intervals available. These should be "minute", "second" and "year". I didn't check compatibility with other database vendors rather than MySQL but I don't think it should be a problem






[DDC-2842] Leave out discriminator part of Doctrine' generated SQL Created: 06/Dec/13  Updated: 06/Dec/13

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

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


 Description   

Assume the following AbstractPage model:

/*

  • @ORM\Entity
  • @ORM\Table(name="page")
  • @ORM\InheritanceType("SINGLE_TABLE")
  • @ORM\DiscriminatorColumn(name="type", type="string")
  • @ORM\DiscriminatorMap
  • ( { * "page" = "Page", * "link" = "Link" * }

    )
    */

And the following DQL query:

SELECT p FROM \Page\Model\AbstractPage

The generated SQL will be:

SELECT ... FROM page p0_ WHERE p0_.type IN ('page', 'link')

Now to the question: how can I remove the WHERE clause from this query. On more complex queries this part of the WHERE clause makes it not possible to use some indexes that are defined. This can be resolved by adding type to the indexes, but this makes my indexes larger and I feel this is not necessary.

The AbstractPage is the root in the inheritance tree. Thus we are interested in ALL records in the table. Omiting the WHERE part does precisely that.

So the question is: how can I make Doctrine remove this WHERE part where it is not necessary.






[DDC-2479] Add possibility to only query for root entities in a class table inheritance Created: 30/May/13  Updated: 30/May/13

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

Type: Improvement Priority: Minor
Reporter: Steve Müller Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: dql,, inheritance


 Description   

It is not possible to query for root/topmost class entities (only) in a class table inheritance situation without extra JOINs to the child entities/classes.

E.g.
Person -> root entity/class
Employee -> child entity/class extending Person

The DQL:

SELECT p
FROM Person p;

also joins Employee even though I am not interested in Employee properties.

Person is the base class in this use case and it should be possible to only retrieve those information. Thinking of OOP, if I instanciate Person I do not have any reference to its child either.
This is especially useful for large base tables where you want to only retrieve base information without inferring the childs.

IMO the DQL should be modified to allow selecting root/base information only, similar to the INSTANCE OF operator, that allows selecting specific childs only.






[DDC-2260] Partial DQL query doesn't respect given order of columns Created: 26/Jan/13  Updated: 27/Jan/13

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

Type: Improvement Priority: Minor
Reporter: Alexander Grimalovsky Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

When executing partial DQL queries it may be important to keep given order of columns e.g. for "pairs" hydrator when first column of a pair is used as a key and second - as value. For example query like this:

select partial u.{id,name} from my:User u

will expect "id" to be first in resulted set and "name" to be second and not vice versa.

However Doctrine parses this part of statement via iterating over fields mapping from entity's class metadata (as can be seen in Doctrine\ORM\Query\SqlWalker::walkSelectExpression()):

foreach ($class->fieldMappings as $fieldName => $mapping) {
  if ($partialFieldSet && ! in_array($fieldName, $partialFieldSet)) {
    continue;
  }
  ...

and hence given columns order preserving is not guaranteed.



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

What is the advantage in respecting the order given in the DQL query?

Comment by Alexander Grimalovsky [ 27/Jan/13 ]

Currently the only practical reason for it that I found is "pairs" hydrator. However it is, of course, possible to implement it without such change too.

Generally speaking this behavior (getting result set with same order of columns that was given in a query) is something that is feeling "natural" for operations with database since it is how you normally get results from SQL queries.

Maybe it will be enough to mention in documentation for Doctrine that given columns order is not guaranteed to be kept.

Comment by Marco Pivetta [ 27/Jan/13 ]

@Alexander Grimalovsky I don't think it's worth mentioning it. Also, including a fix for this is quite complex. If you prefer to document it, go for it!





[DDC-2076] Optimization for MEMBER OF Created: 14/Oct/12  Updated: 14/Oct/12

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

Type: Improvement Priority: Minor
Reporter: Christophe Coevoet Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: dql


 Description   

Currently, using MEMBER OF for a ManyToMany collection does a join on the table of the related entity, whereas all it needs is in the join table.

Using the following DQL:

SELECT p FROM Player p
WHERE NOT :team MEMBER OF p.targetedBy

Here is the current generated SQL:

WHERE NOT EXISTS (SELECT 1 FROM player_team p1_ INNER JOIN Team t2_ ON p1_.team_id = t2_.id WHERE p1_.player_id = p0_.id AND t2_.id = ?)

whereas it could drop the join:

WHERE NOT EXISTS (SELECT 1 FROM player_team p1_ WHERE p1_.player_id = p0_.id AND p1_.team_id = ?)





[DDC-1916] Centralize the Cache mechanism simplifying the query creation Created: 09/Jul/12  Updated: 09/Jul/12

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

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


 Description   

Hi all,

in a big project if you have queries spread out in different
repositories,
when you have to modify a cache lifetime, you have to search the query and
modify the code, than test it.
Is not so easy also to answer to 'how much is the cache for the query XYZ?'

the idea:
Each group of repository (bundle) should have in a single point maybe into its config file a place where you could set the lifetime of the various queries.

see the code for a better explanation
https://gist.github.com/3075742

the pro: a better handling of the cache mechanism
cons: ?

Do you think is a good approach?
Have you ever had a similar problem?

Thanks

liuggio






[DDC-1754] Allow use of Foregin Keys in DQL LIKE condition Created: 03/Apr/12  Updated: 09/Apr/12

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

Type: Improvement Priority: Minor
Reporter: Tim Roediger Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Php 5.3



 Description   

When using a LIKE condition in a WHERE clause, I would like to be able to use the foreign key of a single value association. For example:

Imagine Product and Department are both entities. Department has the field Name with a unique index. Product is has a ManyToOne association called Department with the Department entity, referencing the field Name.

I would like to write:
SELECT FROM Product p WHERE p.Department LIKE '% Tools'

However, at present I need to write:
SELECT FROM Product p
JOIN p.Department d
WHERE d.name LIKE '% Tools'

The issue is one of performance. On large record sets the first query runs several magnatudes more quickly than the second, particularly when four or five joins are involved.

Looking at the DQL grammar from the online docs, the relveant lines are:

LikeExpression ::= StringExpression ["NOT"] "LIKE" string ["ESCAPE" char]
StringExpression ::= StringPrimary | "(" Subselect ")"
StringPrimary ::= StateFieldPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression

The problem is the StateFieldPathExpression in StringPrimary. When used with a LikeExpression a SingleValuedAssociationField should be allowed also.



 Comments   
Comment by Benjamin Eberlei [ 07/Apr/12 ]

This would only work if Department#Name is the primary key. Is it?

DQL is not about optimized performance in very single edge case. We need to keep some parts open to keep the code simple. This is at best a feature request, not a bug.

Comment by Tim Roediger [ 09/Apr/12 ]

Thanks for your reply Benjamin,

I agree with your assesment that this is more accurately an improvement request than a bug. My appologies it was placed in the wrong category.

No, Department#Name is not the primary key, but it does have a unique index.

I've worked a little more to understand the DQL grammar. It appears that only one small, simple change is required:

FROM:
StringPrimary ::= StateFieldPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression

TO:
StringPrimary ::= SingleValuedPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression

This would improve consistancy with other aspects of DQL. For example, AggregateExpression COUNT, NullComparisonExpression , GroupByItem, and ArithmeticPrimary all allow a SingleValuedPathExpression rather than the more strict StateFieldPathExpression.

Bascially my frustration is that as DQL currently stands, foregin keys which are already existant in a db table cannot be used in a LIKE expression without doing an unnessessary JOIN. Foreign keys can already be used in DQL for BETWEEN, IS NULL and comparison expressions, so why not LIKE expressions also? It appears the only thing holding this back is an unrequired restriction in the DQL grammar.

Cheers, Tim





[DDC-1675] PDO::FETCH_GROUP Created: 01/Mar/12  Updated: 01/Mar/12

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

Type: New Feature Priority: Minor
Reporter: Henrik Bjornskov Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

PDO supports grouping by a field when doing a fetchAll() by using PDO::FETCH_GROUP. This can in many places be useful. http://blog.stealth35.com/2011/08/17/pdo-fetch-group.html desribes the behavior quite well.






[DDC-712] allow RIGHT JOIN or specifying the root class of the hydratation tree Created: 21/Jul/10  Updated: 22/Jul/10

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

Type: Improvement Priority: Minor
Reporter: Mihai Ilinca Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Hi! Let me start by saying you guys did a great job with Doctrine 1 and that I can't wait to start using Doctrine2

I will explain this feature request with an example. I have a User entity wich relates one to many to a Picture entity. Picture has a " is main picture" boolean field. Not all users have a main picture. I would like to be able to select all Users, each with their main picutre, if that exists, or some Null value, if it does not exists, in one query, using join. I would also like for the result collection to contain Picture entities on the first level, with the User beinng accessible as an aggregate of Picture.

The way I can think doing this is by using a RIGHT or LEFT join (not INNER) as to also select Users that don't have a main picture. I can do this by selecting

SELECT Picture p, p.User u FROM p RIGHT JOIN u WITH p.main=1

but right joins afik are not available atm in either version of Doctrine, or by selecting

SELECT User u, u.Picture p FROM u LEFT JOIN p WITH p.main=1

and somehow instructing the hydrator to consider Picture as the root object for the generated object tree and User as a "child" of Picture.

For users without a picture, the Picture object would somehow indicate it is NULL, while still holding a refference to the User.

Makes sense? If there is an alternate way to achieve this, please enlighten me, tough I think it would still add felxibility if we could hint the hydrator for the root object in a tree.



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

Why don't you model that as ManyToOne for the Main Picture and OneToMany for all pictures? Makes much more sense from an ORM perspsective, you would have your own property "User::$mainPicture"

Comment by Mihai Ilinca [ 22/Jul/10 ]

Thanks for the suggestion. However, this was just an example to demonstrate some lack of flexibility, I am not strictly looking for a solution to this example, but to the concept behind it.

Also, how would I get the result with Picture on the top level and User aggregated to Picture with the model you suggested? Unless I am missing something, wouldn't I end up in the same situation?

I can post-process the results myself and create a new collection easily, ofc, but it would be better (and more optimal) if I could tell the hydrator to do this, similar to how INDEXBY is passed as an option to the hydrator.





Add the notion of read-only entities (DDC-209)

[DDC-691] doctrine.readOnly query hint Created: 15/Jul/10  Updated: 31/May/12

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

Type: Sub-task Priority: Minor
Reporter: Roman S. Borschel Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 6
Labels: None


 Description   

Setting such a query hint to TRUE should result in all entities being retrieved by that query to be read-only for the purposes of change-tracking. Note that the entities themselves need not necessarily be read-only in general.

This feature is a flush performance tweak that can be used to query for objects but not let the returned objects run through change-tracking on flush. Any other managed objects are tracked as usual so you can do a read-only query for 100 entities and persist a new entity in the same unit of work with optimal flushing performance.



 Comments   
Comment by Konstantin [ 26/Dec/11 ]

Any news?
Why query hint? What about temporary switching like fetch mode changing via query object?

Comment by Gigi Largeanus [ 31/May/12 ]

Any news on this?

I think this is a must have feature. Thanks for all your work.





[DDC-3154] Conditions with Value Objects Created: 05/Jun/14  Updated: 05/Jun/14

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

Type: Improvement Priority: Minor
Reporter: Erik A. Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: value-objects


 Description   

I'm quite enthousiastic about Embeddables being added to Doctrine, but it's a pity that true Value Objects, which are compared by their properties, are not supported yet.

Given a Value Object Address with properties street and house number that you can instantiate with new Address("High Street", 1), and a User class that has an Address as Embeddable.

Then, the following is now supported:
DQL1:

SELECT u FROM User u WHERE (u.address.street = :street AND u.address.nr = :number)
    with { 'street' => 'High Street', 'number' => 1 }

Disadvantage: you should know the internal properties when writing your query. That's not how Value Objects usually are compared.

Instead, I expect to be able to do this:
DQL2:

SELECT u FROM User u WHERE (u.address = :address)
    with { 'address' => new Address("High Street", 1)  }

Internally, DQL2 could simply be transformed to the equivalent DQL1 by replacing the condition with conditions for each internal property. The advantage is that the one writing the query does not have to refer to the internal fields; the transformation is hidden.

A complicating factor is that Value Objects are Embeddables, but not every Embeddable is a Value Object. So there is always the question if objects need to be compared by reference or by their properties.

So, perhaps it's an idea to introduce a special operator ~ for comparing objects by their value to make the distinction explicit? Like so:
DQL3:

SELECT u FROM User u WHERE (u.address ~ :address)
    with { 'address' => new Address("High Street", 1)  }.

I created a pull request that contains an idea how the same concept (the ~ operator) might be applied to criterias on in-memory collections.

Just some thoughts and ideas. I'd love to hear some discussion on this as I think it would make Doctrine really powerful in supporting rich, expressive domain models. It would be great if both in-memory collections and DQL supported this!



 Comments   
Comment by Guilherme Blanco [ 05/Jun/14 ]

It should be the same operator, not a new one.
So this is the intended and desired behavior:

SELECT u FROM User u WHERE (u.address = :address)
    with { 'address' => new Address("High Street", 1)  }
Comment by Christophe Coevoet [ 05/Jun/14 ]

This would require to change the DQL to SQL conversion based on the fact that u.address is the path to an embeddable. It might impact performances
Using a separate operator would at least allow to know that it needs a special handling, without having to do complex changes to all places using the = operator.

A complicating factor is that Value Objects are Embeddables, but not every Embeddable is a Value Object. So there is always the question if objects need to be compared by reference or by their properties.

Embeddables cannot be compared by reference. They don't have an identity in the database. The only thing we have to compare them are their properties.

Comment by Erik A. [ 05/Jun/14 ]

True, if we look at the database level, we can only compare by reference. However, if you look beyond ORM and also to the Collections package, then if you want to do a matching on a collection of entities that have an Embeddable by using a Criteria on that Embeddable, then you do have both options (see my referenced pull request). Then two operators might come in handy, so that the additional operator can be introduced to both ORM as well as Collections.

If we would go for one operator (=), then I think the Criteria in Collection also needs to be changed so that it performs a loose comparison on objects and a strict comparison only on scalars. Perhaps that is already out of the scope of the current issue, but either way it would be preferrable to have a consistent solution.

Comment by Christophe Coevoet [ 05/Jun/14 ]

No, saying that we can only compare by reference is wrong. We *cannot* compare by reference (there is no way to reference them).

And talking about the needs of the criteria here is irrelevant, as this discussion is about building the DQL language, not about building the Criteria API. The criteria API can still have a separate operator to deal with value object even if the DQL uses = to compare embeddables. (btw, changing the Criteria comparison to loose on objects would break the comparison of relations, so it is totally impossible as it would be a BC break)

Comment by Guilherme Blanco [ 05/Jun/14 ]

Christophe Coevoet not a performance impact since DQL => SQL is cached.
Adding a new operator resolution requires bigger efforts and I'm pretty sure it'll be slower than converting u.address to multiple clauses (we do it already with composite identifiers).





[DDC-3159] CONCAT expression for PostGreSql Created: 10/Jun/14  Updated: 10/Jun/14

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

Type: Improvement Priority: Minor
Reporter: Maxime Colin Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: concat, dql, postgresql
Environment:

PostGreSQL



 Description   

For PostGreSQL, the CONCAT DQL function is translated in concatenation with || operator (which is the default behavior in AbstractPlatform class).

Is there a particular reason to not use the CONCAT PostGreSQL function instead like in MySqlPlatform ?

I ask this cause the concatenation with || operator return null if one of the part is null, whereas CONCAT function will simply ignore null values.






[DDC-2633] How i can use arithmetic expression in the ORDER BY clause? Created: 26/Aug/13  Updated: 26/Aug/13

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

Type: Documentation Priority: Trivial
Reporter: Liverbool Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

I found solution in this site: http://michelsalib.com/2012/03/04/doctrine2-ninja-with-the-hidden-keyword/

I want to use:
... ORDER BY DATE_FORMAT(field, '%Y')
or
... ORDER BY CONVERT(field USING [CHARSET])

and it catch exception like:

<br />
<b>Fatal error</b>: Uncaught exception 'Doctrine\ORM\Query\QueryException' with message 'SELECT t.id, t.label, t.id AS value, t.label AS text FROM Entities\Repair\ProductType t WHERE t.bch_id=?1 ORDER BY DATE_FORMAT(t.create_date,'%Y') ASC' in /home/joyprice.core/Vendor/Doctrine/orm/lib/Doctrine/ORM/Query/QueryException.php:39
Stack trace:
#0 /home/joyprice.core/Vendor/Doctrine/orm/lib/Doctrine/ORM/Query/Parser.php(396): Doctrine\ORM\Query\QueryException::dqlError('SELECT t.id, t....')
#1 /home/joyprice.core/Vendor/Doctrine/orm/lib/Doctrine/ORM/Query/Parser.php(744): Doctrine\ORM\Query\Parser->syntaxError('end of string')
#2 /home/joyprice.core/Vendor/Doctrine/orm/lib/Doctrine/ORM/Query/Parser.php(229): Doctrine\ORM\Query\Parser->QueryLanguage()
#3 /home/joyprice.core/Vendor/Doctrine/orm/lib/Doctrine/ORM/Query/Parser.php(304): Doctrine\ORM\Query\Parser->getAST()
#4 /home/joyprice.core/Vendor/Doctrine/orm/lib/Doctrine/ORM/Query.php(233): Doctrine\ORM\Query\Parser->parse()

But have solution from DQL?

Sorry to ask the question in Issues Tracker.
Thanks






[DDC-1761] Small error on DQL documentation page Created: 03/Apr/12  Updated: 03/Apr/12

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

Type: Documentation Priority: Trivial
Reporter: Tim Roediger Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

On this document page:
http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/dql-doctrine-query-language.html#dql-select-examples

The following lines are present:
$query = $em->createQuery('SELECT u.username, u.name FROM CmsUser u');
$users = $query->getResults(); // array of CmsUser username and name values
echo $users[0]['username'];

There is an error in:
$query->getResults();

It should read
$query->getResult();






[DDC-1466] Entity ID hash generation improvement in UnitOfWork Created: 03/Nov/11  Updated: 03/Nov/11

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

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


 Description   

Currently ID hash is generated using implode function with space character. I would like to point out that problems may raise if the ID column values are allowed to contain the space themselves - different objects could return equal ID hash values.

The trivial one-line solution would be to serialize the array instead. Cheaper solution from performance perspective would be escaping the space character for ID values.






[DDC-3007] ManyToMany does not respect all column attributes for the jointable Created: 03/Mar/14  Updated: 03/Mar/14

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

Type: Bug Priority: Major
Reporter: Michael Kühn Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Given following 2 entities:

<?php
class Role {
    /**
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="UUID")
     * @ORM\Column(name="id", type="guid", nullable=false, unique=true, length=36, options={"fixed"=true})
     */
    protected $id;

    /**
     * @ORM\ManyToMany(targetEntity="User", mappedBy="roleList")
     */
    private $userList;
}
<?php
class User {
    /**
     * @ORM\Column(name="id", type="guid", nullable=false, unique=true, length=36, options={"fixed"=true})
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="UUID")
     */
    protected $id;

    /**     *
     * @ORM\ManyToMany(targetEntity="Role", inversedBy="userList")
     * @ORM\JoinTable(name="user_role")
    protected $roleList;
}

It should create a table "user_role" with 2 columns which are CHAR(36).

But it ignores the Column-Attributes and creates a table "user_role" with 2 CHAR(255) columns.

This has various downsides:

  • It's unusable when using MyISAM, because of limited index size. (CREATE TABLE fails, see DBAL-423)
  • If using GUID-Type (see DBAL-423 with the changes from the linked ull request) and specify "length=36" and "fixed=true" on the Column-Annotation, no changes for the entity-tables itself are generated when running orm:schema-tool:update. However, there are still changes for the many-to-many-table generated (because internal "fixed" is false and length is unset) which represent the current state of the columns. These changes are always generated.





[DDC-2791] Constant value in JoinColumn Created: 13/Nov/13  Updated: 13/Nov/13

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

Type: New Feature Priority: Major
Reporter: Pavel S. Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: joins, mapping, orm

Attachments: JPEG File realty_reference.jpeg    

 Description   

My situation:
I have realty entities (flat, house, ...) they have hundreds parameters, wich title places in REFERENCE table. For example House has a few floor materials (stone, wood, etc.) and I want to get them. But each parameter type defined by type_id field in REFERENCE table, for example for floor material is's 115. My raw SQL:
SELECT h.id,... FROM HOUSE h
LEFT JOIN object_detail mf /material_floor/ ON mf.realty_id = h.id AND mf.data_class = h.data_class AND mf.type_id = 115
LEFT JOIN Reference mfr ON mfr.city_id = h.city_id AND mfr.id = mf.detail_id

And its not possible to set type_id directly in join table






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

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

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

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



 Description   

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

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

Example:
CO_SEQ_NOMEGIGANTEPRAKCTMEUDEUS

Alias formed was
_SEQ_NOMEGIGANTEPRAKCTMEUDEUS101

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



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

Hi there!

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

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

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

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

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

What do you guys think?

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

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

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

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

Pablo,

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

The current code create a sql:
DT_VERIFICACAO_SITUACAO_ACESSO AS _VERIFICACAO_SITUACAO_ACESSO23,

My sugestion will produce:
DT_VERIFICACAO_SITUACAO_ACESSO AS DT_VERIFICACAO_SITUACAO_ACES23,

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

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

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

Comment by Benjamin Eberlei [ 26/Oct/13 ]

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





[DDC-2742] 2 ManyToMany relations to the same target entity make the schema update fail by default Created: 15/Oct/13  Updated: 15/Oct/13

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

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


 Description   

At some point in the Doctrine releases (I don't remember which version it was), the default naming of the join table of a ManyToMany relation changed from using the property name to using the name of the target entity.

This makes it impossible to use multiple ManyToMany relations to the same target entity in a class without naming join tables explicitly. A SchemaException is thrown by the SchemaTool when trying to update the schema.

Note that this issue is not caught by the SchemaValidator. It will display us that the mapping files are correct (before throwing the above exception in the second step when trying to compare it to the existing database)






[DDC-2671] YAML mapping: entity generation with inheritance does work Created: 11/Sep/13  Updated: 11/Sep/13

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

Type: Bug Priority: Major
Reporter: Peter Tulala Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: inheritance, mapping, yaml


 Description   

Entities inherited from parent entities should be defined as class Foo extends Bar. However YAML driver ignores inheritance hierarchy and does not use "extends" keyword at all.






[DDC-2617] OneToMany annotation should not work with MappedSuperclass Created: 18/Aug/13  Updated: 08/Sep/13

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

Type: Bug Priority: Major
Reporter: jonathan bensaid Assignee: Fabio B. Silva
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Using annotations in my model mapped to "mapped superclass" I can use one to many relations et every bidirectional relation I want.
Using yaml or xml it suddenly doesn't work and throw me an error. Annotations should work the same way and should not authorize one to many or any bidirectional relation.



 Comments   
Comment by Benjamin Eberlei [ 08/Sep/13 ]

Its actually the other way around, yml and xml need to allow this, because it works with association overrides.

Comment by Benjamin Eberlei [ 08/Sep/13 ]

Assigning Fabio





[DDC-2387] convert-mapping not working correctly with composite primary keys/foreign keys in 2.4.0-RC1 Created: 03/Apr/13  Updated: 01/Jul/13

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

Type: Bug Priority: Major
Reporter: Nicholas Van Dusen Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 4
Labels: None
Environment:

Symfony 2.2.0, MySQL 5.1



 Description   

(Apologies if this is somehow a Symfony-specific issue)

I updated my application via Composer yesterday, and received Doctrine 2.4.0-RC1. After this update, generating entities has been problematic under certain circumstances.

Here is an example table in MySQL:

CREATE TABLE `user_email` (
  `user_id` int(10) unsigned NOT NULL COMMENT 'FK to user',
  `email` varchar(254) NOT NULL,
  `email_datasource` smallint(1) unsigned NOT NULL COMMENT 'FK to datasource_code',
  `insert_date` datetime NOT NULL,
  PRIMARY KEY (`user_id`,`email`,`email_datasource`),
  KEY `FK_UserEmail_DataSourceCode` (`email_datasource`),
  CONSTRAINT `FK_UserEmail_User` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

In Doctrine 2.3, the mapping works correctly, and you end up with a 3-part primary key, with a user property mapped to the User entity, and a datasourceCode property mapped to the DatasourceCode entity. All good.

In 2.4, the following error is given: Single id is not allowed on composite primary key in entity UserEmail.

Removing one of the foreign keys in the table (either to User or DatasourceCode) but keeping the primary key set to all 3 columns allows the mapping to work. But, if you then remove one of the columns from the primary key (say, email_datasource) it fails again.



 Comments   
Comment by Benjamin Eberlei [ 04/Apr/13 ]

Can you provide the full stack trace to the exception please?

$e->getTraceAsString();
Comment by Nicholas Van Dusen [ 11/Apr/13 ]

Benjamin, I'm not sure how to get the trace for you, since I'm running from inside the Symfony2 doctrine:mapping:import command line item.

Comment by Christophe Coevoet [ 11/Apr/13 ]

Use the --verbose option when running the command

Comment by Nicholas Van Dusen [ 11/Apr/13 ]

I was able to get a trace for you:

#0 /var/www/html/voxrepublic/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php(1571): Doctrine\ORM\Mapping\MappingException::singleIdNotAllowedOnCompositePrimaryKey('UserEmail')
#1 /var/www/html/voxrepublic/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php(422): Doctrine\ORM\Mapping\ClassMetadataInfo->getSingleIdentifierFieldName()
#2 /var/www/html/voxrepublic/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php(136): Doctrine\ORM\Mapping\ClassMetadataFactory->completeIdGeneratorMapping(Object(Doctrine\ORM\Mapping\ClassMetadata))
#3 /var/www/html/voxrepublic/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php(302): Doctrine\ORM\Mapping\ClassMetadataFactory->doLoadMetadata(Object(Doctrine\ORM\Mapping\ClassMetadata), NULL, false, Array)
#4 /var/www/html/voxrepublic/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php(212): Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory->loadMetadata('UserEmail')
#5 /var/www/html/voxrepublic/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php(112): Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory->getMetadataFor('UserEmail')
#6 /var/www/html/voxrepublic/vendor/doctrine/doctrine-bundle/Doctrine/Bundle/DoctrineBundle/Command/ImportMappingDoctrineCommand.php(108): Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory->getAllMetadata()
#7 /var/www/html/voxrepublic/vendor/symfony/symfony/src/Symfony/Component/Console/Command/Command.php(240): Doctrine\Bundle\DoctrineBundle\Command\ImportMappingDoctrineCommand->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#8 /var/www/html/voxrepublic/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php(195): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#9 /var/www/html/voxrepublic/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Console/Application.php(78): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#10 /var/www/html/voxrepublic/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php(106): Symfony\Bundle\FrameworkBundle\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#11 /var/www/html/voxrepublic/app/console(22): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput))
#12 {main}
Comment by Benjamin Eberlei [ 14/Apr/13 ]

The problem is that Doctrine seems to detect that you only have on id field on this entity and then a new function of 2.4 throws this error. I will try to reproduce this with your table. Until then could you show me the var_dump() of the $class variable in Doctrine\ORM\ClassMetadataFactory#completeIdGeneratorMapping()? This would help very much already.

Comment by Maximilian Beck [ 15/Apr/13 ]

I have the same error when using "doctrine:mapping:import"

CREATE  TABLE IF NOT EXISTS `dev_Recipe`.`step` (

  `recipe_id` INT NOT NULL ,

  `step_number` INT NOT NULL ,

  `description` TEXT NULL ,

  `timer` INT NULL ,

  `image` VARCHAR(100) NULL ,

  PRIMARY KEY (`recipe_id`, `step_number`) ,

  INDEX `recipe_id_idx` (`recipe_id` ASC) ,

  INDEX `step_number` (`step_number` ASC) ,

  CONSTRAINT `step_recipe_id`

    FOREIGN KEY (`recipe_id` )

    REFERENCES `dev_Recipe`.`recipe` (`recipe_id` )

    ON DELETE NO ACTION

    ON UPDATE NO ACTION)

ENGINE = InnoDB;
Exception trace:
 () at \htdocs\SF2\vendor\doctrine\orm\lib\Doctrine\ORM\Mapping\MappingException.php:258
 Doctrine\ORM\Mapping\MappingException::singleIdNotAllowedOnCompositePrimaryKey() at \htdocs\SF2\vendor\doctrine\orm\lib\Doctrine\ORM\Mapping\ClassMetadataInfo.php:1571
 Doctrine\ORM\Mapping\ClassMetadataInfo->getSingleIdentifierFieldName() at \htdocs\SF2\vendor\doctrine\orm\lib\Doctrine\ORM\Mapping\ClassMetadataFactory.php:422
 Doctrine\ORM\Mapping\ClassMetadataFactory->completeIdGeneratorMapping() at \htdocs\SF2\vendor\doctrine\orm\lib\Doctrine\ORM\Mapping\ClassMetadataFactory.php:136
 Doctrine\ORM\Mapping\ClassMetadataFactory->doLoadMetadata() at \htdocs\SF2\vendor\doctrine\common\lib\Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory.php:302
 Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory->loadMetadata() at \htdocs\SF2\vendor\doctrine\common\lib\Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory.php:212
 Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory->getMetadataFor() at \htdocs\SF2\vendor\doctrine\common\lib\Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory.php:112
 Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory->getAllMetadata() at \htdocs\SF2\vendor\doctrine\orm\lib\Doctrine\ORM\Tools\Console\Command\ConvertMappingCommand.php:126
 Doctrine\ORM\Tools\Console\Command\ConvertMappingCommand->execute() at \htdocs\SF2\vendor\doctrine\doctrine-bundle\Doctrine\Bundle\DoctrineBundle\Command\Proxy\ConvertMappingDoctrineCommand.php:59
 Doctrine\Bundle\DoctrineBundle\Command\Proxy\ConvertMappingDoctrineCommand->execute() at \htdocs\SF2\vendor\symfony\symfony\src\Symfony\Component\Console\Command\Command.php:240
 Symfony\Component\Console\Command\Command->run() at \htdocs\SF2\vendor\symfony\symfony\src\Symfony\Component\Console\Application.php:193
 Symfony\Component\Console\Application->doRun() at \htdocs\SF2\vendor\symfony\symfony\src\Symfony\Bundle\FrameworkBundle\Console\Application.php:78
 Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at \htdocs\SF2\vendor\symfony\symfony\src\Symfony\Component\Console\Application.php:106
 Symfony\Component\Console\Application->run() at \htdocs\SF2\app\console:22

"var_dump($class);" returns:

object(Doctrine\ORM\Mapping\ClassMetadata)#470 (36) {
  ["name"]=>
  string(10) "Ingredient"
  ["namespace"]=>
  string(0) ""
  ["rootEntityName"]=>
  string(10) "Ingredient"
  ["customGeneratorDefinition"]=>
  NULL
  ["customRepositoryClassName"]=>
  NULL
  ["isMappedSuperclass"]=>
  bool(false)
  ["parentClasses"]=>
  array(0) {
  }
  ["subClasses"]=>
  array(0) {
  }
  ["namedQueries"]=>
  array(0) {
  }
  ["namedNativeQueries"]=>
  array(0) {
  }
  ["sqlResultSetMappings"]=>
  array(0) {
  }
  ["identifier"]=>
  array(1) {
    [0]=>
    string(12) "ingredientId"
  }
  ["inheritanceType"]=>
  int(1)
  ["generatorType"]=>
  int(1)
  ["fieldMappings"]=>
  array(4) {
    ["ingredientId"]=>
    array(6) {
      ["id"]=>
      bool(true)
      ["fieldName"]=>
      string(12) "ingredientId"
      ["columnName"]=>
      string(13) "ingredient_id"
      ["type"]=>
      string(7) "integer"
      ["unsigned"]=>
      bool(false)
      ["nullable"]=>
      bool(false)
    }
    ["name"]=>
    array(6) {
      ["fieldName"]=>
      string(4) "name"
      ["columnName"]=>
      string(4) "name"
      ["type"]=>
      string(6) "string"
      ["length"]=>
      int(45)
      ["fixed"]=>
      bool(false)
      ["nullable"]=>
      bool(false)
    }
    ["color"]=>
    array(5) {
      ["fieldName"]=>
      string(5) "color"
      ["columnName"]=>
      string(5) "color"
      ["type"]=>
      string(7) "integer"
      ["unsigned"]=>
      bool(false)
      ["nullable"]=>
      bool(false)
    }
    ["img"]=>
    array(6) {
      ["fieldName"]=>
      string(3) "img"
      ["columnName"]=>
      string(3) "img"
      ["type"]=>
      string(6) "string"
      ["length"]=>
      int(45)
      ["fixed"]=>
      bool(false)
      ["nullable"]=>
      bool(true)
    }
  }
  ["fieldNames"]=>
  array(4) {
    ["ingredient_id"]=>
    string(12) "ingredientId"
    ["name"]=>
    string(4) "name"
    ["color"]=>
    string(5) "color"
    ["img"]=>
    string(3) "img"
  }
  ["columnNames"]=>
  array(4) {
    ["ingredientId"]=>
    string(13) "ingredient_id"
    ["name"]=>
    string(4) "name"
    ["color"]=>
    string(5) "color"
    ["img"]=>
    string(3) "img"
  }
  ["discriminatorValue"]=>
  NULL
  ["discriminatorMap"]=>
  array(0) {
  }
  ["discriminatorColumn"]=>
  NULL
  ["table"]=>
  array(1) {
    ["name"]=>
    string(10) "ingredient"
  }
  ["lifecycleCallbacks"]=>
  array(0) {
  }
  ["associationMappings"]=>
  array(1) {
    ["ingredientCategory"]=>
    array(15) {
      ["fieldName"]=>
      string(18) "ingredientCategory"
      ["targetEntity"]=>
      string(18) "IngredientCategory"
      ["mappedBy"]=>
      string(10) "ingredient"
      ["type"]=>
      int(8)
      ["inversedBy"]=>
      NULL
      ["isOwningSide"]=>
      bool(false)
      ["sourceEntity"]=>
      string(10) "Ingredient"
      ["fetch"]=>
      int(2)
      ["cascade"]=>
      array(0) {
      }
      ["isCascadeRemove"]=>
      bool(false)
      ["isCascadePersist"]=>
      bool(false)
      ["isCascadeRefresh"]=>
      bool(false)
      ["isCascadeMerge"]=>
      bool(false)
      ["isCascadeDetach"]=>
      bool(false)
      ["orphanRemoval"]=>
      bool(false)
    }
  }
  ["isIdentifierComposite"]=>
  bool(false)
  ["containsForeignIdentifier"]=>
  bool(false)
  ["idGenerator"]=>
  NULL
  ["sequenceGeneratorDefinition"]=>
  NULL
  ["tableGeneratorDefinition"]=>
  NULL
  ["changeTrackingPolicy"]=>
  int(1)
  ["isVersioned"]=>
  NULL
  ["versionField"]=>
  NULL
  ["reflClass"]=>
  NULL
  ["isReadOnly"]=>
  bool(false)
  ["namingStrategy":protected]=>
  object(Doctrine\ORM\Mapping\DefaultNamingStrategy)#258 (0) {
  }
  ["reflFields"]=>
  array(0) {
  }
  ["_prototype":"Doctrine\ORM\Mapping\ClassMetadataInfo":private]=>
  NULL
}
object(Doctrine\ORM\Mapping\ClassMetadata)#472 (36) {
  ["name"]=>
  string(18) "IngredientCategory"
  ["namespace"]=>
  string(0) ""
  ["rootEntityName"]=>
  string(18) "IngredientCategory"
  ["customGeneratorDefinition"]=>
  NULL
  ["customRepositoryClassName"]=>
  NULL
  ["isMappedSuperclass"]=>
  bool(false)
  ["parentClasses"]=>
  array(0) {
  }
  ["subClasses"]=>
  array(0) {
  }
  ["namedQueries"]=>
  array(0) {
  }
  ["namedNativeQueries"]=>
  array(0) {
  }
  ["sqlResultSetMappings"]=>
  array(0) {
  }
  ["identifier"]=>
  array(1) {
    [0]=>
    string(2) "id"
  }
  ["inheritanceType"]=>
  int(1)
  ["generatorType"]=>
  int(1)
  ["fieldMappings"]=>
  array(3) {
    ["id"]=>
    array(6) {
      ["id"]=>
      bool(true)
      ["fieldName"]=>
      string(2) "id"
      ["columnName"]=>
      string(2) "id"
      ["type"]=>
      string(7) "integer"
      ["unsigned"]=>
      bool(false)
      ["nullable"]=>
      bool(false)
    }
    ["name"]=>
    array(6) {
      ["fieldName"]=>
      string(4) "name"
      ["columnName"]=>
      string(4) "name"
      ["type"]=>
      string(6) "string"
      ["length"]=>
      int(255)
      ["fixed"]=>
      bool(false)
      ["nullable"]=>
      bool(false)
    }
    ["description"]=>
    array(4) {
      ["fieldName"]=>
      string(11) "description"
      ["columnName"]=>
      string(11) "description"
      ["type"]=>
      string(4) "text"
      ["nullable"]=>
      bool(true)
    }
  }
  ["fieldNames"]=>
  array(3) {
    ["id"]=>
    string(2) "id"
    ["name"]=>
    string(4) "name"
    ["description"]=>
    string(11) "description"
  }
  ["columnNames"]=>
  array(3) {
    ["id"]=>
    string(2) "id"
    ["name"]=>
    string(4) "name"
    ["description"]=>
    string(11) "description"
  }
  ["discriminatorValue"]=>
  NULL
  ["discriminatorMap"]=>
  array(0) {
  }
  ["discriminatorColumn"]=>
  NULL
  ["table"]=>
  array(1) {
    ["name"]=>
    string(19) "ingredient_category"
  }
  ["lifecycleCallbacks"]=>
  array(0) {
  }
  ["associationMappings"]=>
  array(2) {
    ["ingredient"]=>
    array(19) {
      ["fieldName"]=>
      string(10) "ingredient"
      ["targetEntity"]=>
      string(10) "Ingredient"
      ["inversedBy"]=>
      string(18) "ingredientCategory"
      ["joinTable"]=>
      array(3) {
        ["name"]=>
        string(30) "ingredient_category_ingredient"
        ["joinColumns"]=>
        array(1) {
          [0]=>
          array(2) {
            ["name"]=>
            string(22) "ingredient_category_id"
            ["referencedColumnName"]=>
            string(2) "id"
          }
        }
        ["inverseJoinColumns"]=>
        array(1) {
          [0]=>
          array(2) {
            ["name"]=>
            string(13) "ingredient_id"
            ["referencedColumnName"]=>
            string(13) "ingredient_id"
          }
        }
      }
      ["type"]=>
      int(8)
      ["mappedBy"]=>
      NULL
      ["isOwningSide"]=>
      bool(true)
      ["sourceEntity"]=>
      string(18) "IngredientCategory"
      ["fetch"]=>
      int(2)
      ["cascade"]=>
      array(0) {
      }
      ["isCascadeRemove"]=>
      bool(false)
      ["isCascadePersist"]=>
      bool(false)
      ["isCascadeRefresh"]=>
      bool(false)
      ["isCascadeMerge"]=>
      bool(false)
      ["isCascadeDetach"]=>
      bool(false)
      ["joinTableColumns"]=>
      array(2) {
        [0]=>
        string(22) "ingredient_category_id"
        [1]=>
        string(13) "ingredient_id"
      }
      ["relationToSourceKeyColumns"]=>
      array(1) {
        ["ingredient_category_id"]=>
        string(2) "id"
      }
      ["relationToTargetKeyColumns"]=>
      array(1) {
        ["ingredient_id"]=>
        string(13) "ingredient_id"
      }
      ["orphanRemoval"]=>
      bool(false)
    }
    ["parent"]=>
    array(19) {
      ["fieldName"]=>
      string(6) "parent"
      ["targetEntity"]=>
      string(18) "IngredientCategory"
      ["joinColumns"]=>
      array(1) {
        [0]=>
        array(2) {
          ["name"]=>
          string(9) "parent_id"
          ["referencedColumnName"]=>
          string(2) "id"
        }
      }
      ["type"]=>
      int(2)
      ["mappedBy"]=>
      NULL
      ["inversedBy"]=>
      NULL
      ["isOwningSide"]=>
      bool(true)
      ["sourceEntity"]=>
      string(18) "IngredientCategory"
      ["fetch"]=>
      int(2)
      ["cascade"]=>
      array(0) {
      }
      ["isCascadeRemove"]=>
      bool(false)
      ["isCascadePersist"]=>
      bool(false)
      ["isCascadeRefresh"]=>
      bool(false)
      ["isCascadeMerge"]=>
      bool(false)
      ["isCascadeDetach"]=>
      bool(false)
      ["sourceToTargetKeyColumns"]=>
      array(1) {
        ["parent_id"]=>
        string(2) "id"
      }
      ["joinColumnFieldNames"]=>
      array(1) {
        ["parent_id"]=>
        string(9) "parent_id"
      }
      ["targetToSourceKeyColumns"]=>
      array(1) {
        ["id"]=>
        string(9) "parent_id"
      }
      ["orphanRemoval"]=>
      bool(false)
    }
  }
  ["isIdentifierComposite"]=>
  bool(false)
  ["containsForeignIdentifier"]=>
  bool(false)
  ["idGenerator"]=>
  NULL
  ["sequenceGeneratorDefinition"]=>
  NULL
  ["tableGeneratorDefinition"]=>
  NULL
  ["changeTrackingPolicy"]=>
  int(1)
  ["isVersioned"]=>
  NULL
  ["versionField"]=>
  NULL
  ["reflClass"]=>
  NULL
  ["isReadOnly"]=>
  bool(false)
  ["namingStrategy":protected]=>
  object(Doctrine\ORM\Mapping\DefaultNamingStrategy)#258 (0) {
  }
  ["reflFields"]=>
  array(0) {
  }
  ["_prototype":"Doctrine\ORM\Mapping\ClassMetadataInfo":private]=>
  NULL
}
object(Doctrine\ORM\Mapping\ClassMetadata)#474 (36) {
  ["name"]=>
  string(6) "Recipe"
  ["namespace"]=>
  string(0) ""
  ["rootEntityName"]=>
  string(6) "Recipe"
  ["customGeneratorDefinition"]=>
  NULL
  ["customRepositoryClassName"]=>
  NULL
  ["isMappedSuperclass"]=>
  bool(false)
  ["parentClasses"]=>
  array(0) {
  }
  ["subClasses"]=>
  array(0) {
  }
  ["namedQueries"]=>
  array(0) {
  }
  ["namedNativeQueries"]=>
  array(0) {
  }
  ["sqlResultSetMappings"]=>
  array(0) {
  }
  ["identifier"]=>
  array(1) {
    [0]=>
    string(8) "recipeId"
  }
  ["inheritanceType"]=>
  int(1)
  ["generatorType"]=>
  int(1)
  ["fieldMappings"]=>
  array(3) {
    ["recipeId"]=>
    array(6) {
      ["id"]=>
      bool(true)
      ["fieldName"]=>
      string(8) "recipeId"
      ["columnName"]=>
      string(9) "recipe_id"
      ["type"]=>
      string(7) "integer"
      ["unsigned"]=>
      bool(false)
      ["nullable"]=>
      bool(false)
    }
    ["name"]=>
    array(6) {
      ["fieldName"]=>
      string(4) "name"
      ["columnName"]=>
      string(4) "name"
      ["type"]=>
      string(6) "string"
      ["length"]=>
      int(255)
      ["fixed"]=>
      bool(false)
      ["nullable"]=>
      bool(false)
    }
    ["description"]=>
    array(4) {
      ["fieldName"]=>
      string(11) "description"
      ["columnName"]=>
      string(11) "description"
      ["type"]=>
      string(4) "text"
      ["nullable"]=>
      bool(true)
    }
  }
  ["fieldNames"]=>
  array(3) {
    ["recipe_id"]=>
    string(8) "recipeId"
    ["name"]=>
    string(4) "name"
    ["description"]=>
    string(11) "description"
  }
  ["columnNames"]=>
  array(3) {
    ["recipeId"]=>
    string(9) "recipe_id"
    ["name"]=>
    string(4) "name"
    ["description"]=>
    string(11) "description"
  }
  ["discriminatorValue"]=>
  NULL
  ["discriminatorMap"]=>
  array(0) {
  }
  ["discriminatorColumn"]=>
  NULL
  ["table"]=>
  array(1) {
    ["name"]=>
    string(6) "recipe"
  }
  ["lifecycleCallbacks"]=>
  array(0) {
  }
  ["associationMappings"]=>
  array(2) {
    ["recipeCategory"]=>
    array(15) {
      ["fieldName"]=>
      string(14) "recipeCategory"
      ["targetEntity"]=>
      string(14) "RecipeCategory"
      ["mappedBy"]=>
      string(6) "recipe"
      ["type"]=>
      int(8)
      ["inversedBy"]=>
      NULL
      ["isOwningSide"]=>
      bool(false)
      ["sourceEntity"]=>
      string(6) "Recipe"
      ["fetch"]=>
      int(2)
      ["cascade"]=>
      array(0) {
      }
      ["isCascadeRemove"]=>
      bool(false)
      ["isCascadePersist"]=>
      bool(false)
      ["isCascadeRefresh"]=>
      bool(false)
      ["isCascadeMerge"]=>
      bool(false)
      ["isCascadeDetach"]=>
      bool(false)
      ["orphanRemoval"]=>
      bool(false)
    }
    ["users"]=>
    array(19) {
      ["fieldName"]=>
      string(5) "users"
      ["targetEntity"]=>
      string(5) "Users"
      ["inversedBy"]=>
      string(12) "recipeRecipe"
      ["joinTable"]=>
      array(3) {
        ["name"]=>
        string(13) "users_recipes"
        ["joinColumns"]=>
        array(1) {
          [0]=>
          array(2) {
            ["name"]=>
            string(16) "recipe_recipe_id"
            ["referencedColumnName"]=>
            string(9) "recipe_id"
          }
        }
        ["inverseJoinColumns"]=>
        array(1) {
          [0]=>
          array(2) {
            ["name"]=>
            string(8) "users_id"
            ["referencedColumnName"]=>
            string(2) "id"
          }
        }
      }
      ["type"]=>
      int(8)
      ["mappedBy"]=>
      NULL
      ["isOwningSide"]=>
      bool(true)
      ["sourceEntity"]=>
      string(6) "Recipe"
      ["fetch"]=>
      int(2)
      ["cascade"]=>
      array(0) {
      }
      ["isCascadeRemove"]=>
      bool(false)
      ["isCascadePersist"]=>
      bool(false)
      ["isCascadeRefresh"]=>
      bool(false)
      ["isCascadeMerge"]=>
      bool(false)
      ["isCascadeDetach"]=>
      bool(false)
      ["joinTableColumns"]=>
      array(2) {
        [0]=>
        string(16) "recipe_recipe_id"
        [1]=>
        string(8) "users_id"
      }
      ["relationToSourceKeyColumns"]=>
      array(1) {
        ["recipe_recipe_id"]=>
        string(9) "recipe_id"
      }
      ["relationToTargetKeyColumns"]=>
      array(1) {
        ["users_id"]=>
        string(2) "id"
      }
      ["orphanRemoval"]=>
      bool(false)
    }
  }
  ["isIdentifierComposite"]=>
  bool(false)
  ["containsForeignIdentifier"]=>
  bool(false)
  ["idGenerator"]=>
  NULL
  ["sequenceGeneratorDefinition"]=>
  NULL
  ["tableGeneratorDefinition"]=>
  NULL
  ["changeTrackingPolicy"]=>
  int(1)
  ["isVersioned"]=>
  NULL
  ["versionField"]=>
  NULL
  ["reflClass"]=>
  NULL
  ["isReadOnly"]=>
  bool(false)
  ["namingStrategy":protected]=>
  object(Doctrine\ORM\Mapping\DefaultNamingStrategy)#258 (0) {
  }
  ["reflFields"]=>
  array(0) {
  }
  ["_prototype":"Doctrine\ORM\Mapping\ClassMetadataInfo":private]=>
  NULL
}
object(Doctrine\ORM\Mapping\ClassMetadata)#476 (36) {
  ["name"]=>
  string(14) "RecipeCategory"
  ["namespace"]=>
  string(0) ""
  ["rootEntityName"]=>
  string(14) "RecipeCategory"
  ["customGeneratorDefinition"]=>
  NULL
  ["customRepositoryClassName"]=>
  NULL
  ["isMappedSuperclass"]=>
  bool(false)
  ["parentClasses"]=>
  array(0) {
  }
  ["subClasses"]=>
  array(0) {
  }
  ["namedQueries"]=>
  array(0) {
  }
  ["namedNativeQueries"]=>
  array(0) {
  }
  ["sqlResultSetMappings"]=>
  array(0) {
  }
  ["identifier"]=>
  array(1) {
    [0]=>
    string(2) "id"
  }
  ["inheritanceType"]=>
  int(1)
  ["generatorType"]=>
  int(1)
  ["fieldMappings"]=>
  array(3) {
    ["id"]=>
    array(6) {
      ["id"]=>
      bool(true)
      ["fieldName"]=>
      string(2) "id"
      ["columnName"]=>
      string(2) "id"
      ["type"]=>
      string(7) "integer"
      ["unsigned"]=>
      bool(false)
      ["nullable"]=>
      bool(false)
    }
    ["name"]=>
    array(6) {
      ["fieldName"]=>
      string(4) "name"
      ["columnName"]=>
      string(4) "name"
      ["type"]=>
      string(6) "string"
      ["length"]=>
      int(45)
      ["fixed"]=>
      bool(false)
      ["nullable"]=>
      bool(false)
    }
    ["description"]=>
    array(6) {
      ["fieldName"]=>
      string(11) "description"
      ["columnName"]=>
      string(11) "description"
      ["type"]=>
      string(6) "string"
      ["length"]=>
      int(45)
      ["fixed"]=>
      bool(false)
      ["nullable"]=>
      bool(true)
    }
  }
  ["fieldNames"]=>
  array(3) {
    ["id"]=>
    string(2) "id"
    ["name"]=>
    string(4) "name"
    ["description"]=>
    string(11) "description"
  }
  ["columnNames"]=>
  array(3) {
    ["id"]=>
    string(2) "id"
    ["name"]=>
    string(4) "name"
    ["description"]=>
    string(11) "description"
  }
  ["discriminatorValue"]=>
  NULL
  ["discriminatorMap"]=>
  array(0) {
  }
  ["discriminatorColumn"]=>
  NULL
  ["table"]=>
  array(1) {
    ["name"]=>
    string(15) "recipe_category"
  }
  ["lifecycleCallbacks"]=>
  array(0) {
  }
  ["associationMappings"]=>
  array(2) {
    ["recipe"]=>
    array(19) {
      ["fieldName"]=>
      string(6) "recipe"
      ["targetEntity"]=>
      string(6) "Recipe"
      ["inversedBy"]=>
      string(14) "recipeCategory"
      ["joinTable"]=>
      array(3) {
        ["name"]=>
        string(22) "recipe_category_recipe"
        ["joinColumns"]=>
        array(1) {
          [0]=>
          array(2) {
            ["name"]=>
            string(18) "recipe_category_id"
            ["referencedColumnName"]=>
            string(2) "id"
          }
        }
        ["inverseJoinColumns"]=>
        array(1) {
          [0]=>
          array(2) {
            ["name"]=>
            string(9) "recipe_id"
            ["referencedColumnName"]=>
            string(9) "recipe_id"
          }
        }
      }
      ["type"]=>
      int(8)
      ["mappedBy"]=>
      NULL
      ["isOwningSide"]=>
      bool(true)
      ["sourceEntity"]=>
      string(14) "RecipeCategory"
      ["fetch"]=>
      int(2)
      ["cascade"]=>
      array(0) {
      }
      ["isCascadeRemove"]=>
      bool(false)
      ["isCascadePersist"]=>
      bool(false)
      ["isCascadeRefresh"]=>
      bool(false)
      ["isCascadeMerge"]=>
      bool(false)
      ["isCascadeDetach"]=>
      bool(false)
      ["joinTableColumns"]=>
      array(2) {
        [0]=>
        string(18) "recipe_category_id"
        [1]=>
        string(9) "recipe_id"
      }
      ["relationToSourceKeyColumns"]=>
      array(1) {
        ["recipe_category_id"]=>
        string(2) "id"
      }
      ["relationToTargetKeyColumns"]=>
      array(1) {
        ["recipe_id"]=>
        string(9) "recipe_id"
      }
      ["orphanRemoval"]=>
      bool(false)
    }
    ["parent"]=>
    array(19) {
      ["fieldName"]=>
      string(6) "parent"
      ["targetEntity"]=>
      string(14) "RecipeCategory"
      ["joinColumns"]=>
      array(1) {
        [0]=>
        array(2) {
          ["name"]=>
          string(9) "parent_id"
          ["referencedColumnName"]=>
          string(2) "id"
        }
      }
      ["type"]=>
      int(2)
      ["mappedBy"]=>
      NULL
      ["inversedBy"]=>
      NULL
      ["isOwningSide"]=>
      bool(true)
      ["sourceEntity"]=>
      string(14) "RecipeCategory"
      ["fetch"]=>
      int(2)
      ["cascade"]=>
      array(0) {
      }
      ["isCascadeRemove"]=>
      bool(false)
      ["isCascadePersist"]=>
      bool(false)
      ["isCascadeRefresh"]=>
      bool(false)
      ["isCascadeMerge"]=>
      bool(false)
      ["isCascadeDetach"]=>
      bool(false)
      ["sourceToTargetKeyColumns"]=>
      array(1) {
        ["parent_id"]=>
        string(2) "id"
      }
      ["joinColumnFieldNames"]=>
      array(1) {
        ["parent_id"]=>
        string(9) "parent_id"
      }
      ["targetToSourceKeyColumns"]=>
      array(1) {
        ["id"]=>
        string(9) "parent_id"
      }
      ["orphanRemoval"]=>
      bool(false)
    }
  }
  ["isIdentifierComposite"]=>
  bool(false)
  ["containsForeignIdentifier"]=>
  bool(false)
  ["idGenerator"]=>
  NULL
  ["sequenceGeneratorDefinition"]=>
  NULL
  ["tableGeneratorDefinition"]=>
  NULL
  ["changeTrackingPolicy"]=>
  int(1)
  ["isVersioned"]=>
  NULL
  ["versionField"]=>
  NULL
  ["reflClass"]=>
  NULL
  ["isReadOnly"]=>
  bool(false)
  ["namingStrategy":protected]=>
  object(Doctrine\ORM\Mapping\DefaultNamingStrategy)#258 (0) {
  }
  ["reflFields"]=>
  array(0) {
  }
  ["_prototype":"Doctrine\ORM\Mapping\ClassMetadataInfo":private]=>
  NULL
}
object(Doctrine\ORM\Mapping\ClassMetadata)#478 (36) {
  ["name"]=>
  string(4) "Step"
  ["namespace"]=>
  string(0) ""
  ["rootEntityName"]=>
  string(4) "Step"
  ["customGeneratorDefinition"]=>
  NULL
  ["customRepositoryClassName"]=>
  NULL
  ["isMappedSuperclass"]=>
  bool(false)
  ["parentClasses"]=>
  array(0) {
  }
  ["subClasses"]=>
  array(0) {
  }
  ["namedQueries"]=>
  array(0) {
  }
  ["namedNativeQueries"]=>
  array(0) {
  }
  ["sqlResultSetMappings"]=>
  array(0) {
  }
  ["identifier"]=>
  array(2) {
    [0]=>
    string(10) "stepNumber"
    [1]=>
    string(6) "recipe"
  }
  ["inheritanceType"]=>
  int(1)
  ["generatorType"]=>
  int(1)
  ["fieldMappings"]=>
  array(4) {
    ["stepNumber"]=>
    array(6) {
      ["id"]=>
      bool(true)
      ["fieldName"]=>
      string(10) "stepNumber"
      ["columnName"]=>
      string(11) "step_number"
      ["type"]=>
      string(7) "integer"
      ["unsigned"]=>
      bool(false)
      ["nullable"]=>
      bool(false)
    }
    ["description"]=>
    array(4) {
      ["fieldName"]=>
      string(11) "description"
      ["columnName"]=>
      string(11) "description"
      ["type"]=>
      string(4) "text"
      ["nullable"]=>
      bool(true)
    }
    ["timer"]=>
    array(5) {
      ["fieldName"]=>
      string(5) "timer"
      ["columnName"]=>
      string(5) "timer"
      ["type"]=>
      string(7) "integer"
      ["unsigned"]=>
      bool(false)
      ["nullable"]=>
      bool(true)
    }
    ["image"]=>
    array(6) {
      ["fieldName"]=>
      string(5) "image"
      ["columnName"]=>
      string(5) "image"
      ["type"]=>
      string(6) "string"
      ["length"]=>
      int(100)
      ["fixed"]=>
      bool(false)
      ["nullable"]=>
      bool(true)
    }
  }
  ["fieldNames"]=>
  array(4) {
    ["step_number"]=>
    string(10) "stepNumber"
    ["description"]=>
    string(11) "description"
    ["timer"]=>
    string(5) "timer"
    ["image"]=>
    string(5) "image"
  }
  ["columnNames"]=>
  array(4) {
    ["stepNumber"]=>
    string(11) "step_number"
    ["description"]=>
    string(11) "description"
    ["timer"]=>
    string(5) "timer"
    ["image"]=>
    string(5) "image"
  }
  ["discriminatorValue"]=>
  NULL
  ["discriminatorMap"]=>
  array(0) {
  }
  ["discriminatorColumn"]=>
  NULL
  ["table"]=>
  array(1) {
    ["name"]=>
    string(4) "step"
  }
  ["lifecycleCallbacks"]=>
  array(0) {
  }
  ["associationMappings"]=>
  array(1) {
    ["recipe"]=>
    array(20) {
      ["fieldName"]=>
      string(6) "recipe"
      ["targetEntity"]=>
      string(6) "Recipe"
      ["id"]=>
      bool(true)
      ["joinColumns"]=>
      array(1) {
        [0]=>
        array(2) {
          ["name"]=>
          string(9) "recipe_id"
          ["referencedColumnName"]=>
          string(9) "recipe_id"
        }
      }
      ["type"]=>
      int(1)
      ["mappedBy"]=>
      NULL
      ["inversedBy"]=>
      NULL
      ["isOwningSide"]=>
      bool(true)
      ["sourceEntity"]=>
      string(4) "Step"
      ["fetch"]=>
      int(2)
      ["cascade"]=>
      array(0) {
      }
      ["isCascadeRemove"]=>
      bool(false)
      ["isCascadePersist"]=>
      bool(false)
      ["isCascadeRefresh"]=>
      bool(false)
      ["isCascadeMerge"]=>
      bool(false)
      ["isCascadeDetach"]=>
      bool(false)
      ["sourceToTargetKeyColumns"]=>
      array(1) {
        ["recipe_id"]=>
        string(9) "recipe_id"
      }
      ["joinColumnFieldNames"]=>
      array(1) {
        ["recipe_id"]=>
        string(9) "recipe_id"
      }
      ["targetToSourceKeyColumns"]=>
      array(1) {
        ["recipe_id"]=>
        string(9) "recipe_id"
      }
      ["orphanRemoval"]=>
      bool(false)
    }
  }
  ["isIdentifierComposite"]=>
  bool(true)
  ["containsForeignIdentifier"]=>
  bool(true)
  ["idGenerator"]=>
  NULL
  ["sequenceGeneratorDefinition"]=>
  NULL
  ["tableGeneratorDefinition"]=>
  NULL
  ["changeTrackingPolicy"]=>
  int(1)
  ["isVersioned"]=>
  NULL
  ["versionField"]=>
  NULL
  ["reflClass"]=>
  NULL
  ["isReadOnly"]=>
  bool(false)
  ["namingStrategy":protected]=>
  object(Doctrine\ORM\Mapping\DefaultNamingStrategy)#258 (0) {
  }
  ["reflFields"]=>
  array(0) {
  }
  ["_prototype":"Doctrine\ORM\Mapping\ClassMetadataInfo":private]=>
  NULL
}
Comment by Benjamin Eberlei [ 09/May/13 ]

Fixed and merged back to 2.3

Comment by Nicholas Van Dusen [ 29/May/13 ]

I tested this again using 2.3.4 (the version which contains this fix) and it is still occurring. Attempting to import mapping for a table with 2 foreign keys in the primary key results in the error "Database does not have any mapping information." Adding a third column on the primary key "fixes" the issue.

Currently our developers are being asked to add a fake third part to the key to work around the issue, then delete that key once they get into the entity class. This is a bit tedious and I'd love to see a fix!

Comment by Nicholas Van Dusen [ 29/May/13 ]

Issue still present in 2.3.4 and 2.4.0-RC1

Comment by Guillermo [ 11/Jun/13 ]

The database engine I use is PostgreSQL. I'm having problems when mapping entities with composite primary keys in other tables.

CREATE TABLE public.establecimiento
    (
      id_establecimiento integer NOT NULL,
      establecimiento character varying(100) NOT NULL,
      CONSTRAINT pk_establecimiento PRIMARY KEY (id_establecimiento )
    )
    WITH (
      OIDS=FALSE
    );
    CREATE TABLE public.establecimiento_sec
    (
      id_establecimiento_sec integer NOT NULL,
      id_establecimiento integer NOT NULL,
      det_seccion character varying(40) NOT NULL,
      plano character varying(100),
      sector_ingreso character varying(254),
      sponsor_imagen_sec character varying(96000),
      CONSTRAINT pk_establecimientos_sec PRIMARY KEY (id_establecimiento_sec , id_establecimiento ),
      CONSTRAINT fk_establec_reference_establec FOREIGN KEY (id_establecimiento)
          REFERENCES public.establecimiento (id_establecimiento) MATCH SIMPLE
          ON UPDATE RESTRICT ON DELETE RESTRICT
    )
    WITH (
      OIDS=TRUE
    );
    CREATE TABLE public.establecimiento_sec_plano
    (
      id_establecimiento_sec_plano integer NOT NULL,
      id_establecimiento_sec integer NOT NULL,
      id_establecimiento integer NOT NULL,
      det_plano character varying(512),
      cantidad integer NOT NULL,
      precio double precision,
      insert_charge double precision DEFAULT 0,
      descr character varying(254),
      CONSTRAINT pk_establecimiento_sec_plano PRIMARY KEY (id_establecimiento_sec_plano , id_establecimiento_sec , id_establecimiento ),
      CONSTRAINT fk_establecimiento_sec FOREIGN KEY (id_establecimiento, id_establecimiento_sec)
          REFERENCES public.establecimiento_sec (id_establecimiento, id_establecimiento_sec) MATCH SIMPLE
          ON UPDATE NO ACTION ON DELETE CASCADE
    )
    WITH (
      OIDS=FALSE
    );

Defining the entity establecimientoSecPlano, $establecimientoSec variable containing the keys $establecimiento and $id_establecimiento_sec

//Entity/EstablecimientosSecPlano

/**
     * @ORM\Id
     * @ORM\ManyToOne(targetEntity="Ticketway\PruebaBundle\Entity\EstablecimientosSec")
     * @ORM\JoinColumns(
     *      @ORM\JoinColumn(name="id_establecimiento_sec", referencedColumnName="id_establecimiento_sec"),
     *      @ORM\JoinColumn(name="id_establecimiento", referencedColumnName="id_establecimiento")) 
     */
    private $establecimientoSec;

//Entity/EstablecimientosSec

/**
     * @ORM\Id
     * @ORM\ManyToOne(targetEntity="Ticketway\PruebaBundle\Entity\Establecimientos")
     * @ORM\JoinColumn(name="id_establecimiento", referencedColumnName="id_establecimiento") 
     */
    private $establecimiento;

When executing the command doctrine: mapping: import I get the following error

[Doctrine\ORM\Mapping\MappingException]
It is not possible to map entity 'EstablecimientoSec' with a composite primary key as part of the
primary key of another entity 'EstablecimientoSecPlano#idEstablecimiento'.

Comment by Sam Van der Borght [ 28/Jun/13 ]

We are having the same problem as Guillermo. Any idea on how to fix this issue?
Does anybody know why this problem occurs? I have been looking in the code but havent had much success.

Comment by Diego Antunes [ 01/Jul/13 ]

Doesn't work for me either, composite keys aren't working in 2.3.4

Can we get a fix for this?





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

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

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

Attachments: Text File persister.patch    

 Description   

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






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

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

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

Linux 3.6.6-1.fc17.x86_64


Attachments: Text File error.log    

 Description   

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



 Comments   
Comment by kluk [ 15/Nov/12 ]

error log from orm:validate-schema

Comment by Marco Pivetta [ 23/Jan/13 ]

Copying from pastebin:

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

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

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

the same error when using simple annotation.

 
<?php

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

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

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

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

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

}

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

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

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

Comment by Benjamin Eberlei [ 04/May/13 ]

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

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

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




[DDC-1957] DB -> Entity: Reverse engeniering with two relations between two tables Created: 29/Jul/12  Updated: 29/Jul/12

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

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

windows 7, php 5.3, symfony 2.1



 Description   

i use the cli from the symfony 2.1 project to reverse from DB to Entity:

php app/console doctrine:mapping:convert xml ./src/Acme/StoreBundle/Resources/config/doctrine/metadata/orm --from-database --force

and i get tis error:

[Doctrine\ORM\Mapping\MappingException]
Property "radUser" in "RadAttribute" was already declared, but it must be declared only once

so i have a table "radUser" with two m:n relations to the same table "radAttributes":

Table radUser:
check => radAttributes
reply => radAttributes

so doctrine reverse mapping try to generate the radAttribute entity with two mapping to radUser with the same field name "radUser", what can i do to prevent this issue ?






[DDC-1817] Allowing to specify MySQL Collation on Field Basis Created: 08/May/12  Updated: 11/Feb/14

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

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


 Description   

It would be nice to be able to specify which collation to use on a field basis.

This would for example be useful when you have case-sensitive (utf8_bin), and case-insensitive (utf8_general_ci) values. Right now, this needs to be manually added to migration files (which is ok for projects, but it is not so nice for distributable libraries).



 Comments   
Comment by Steve Müller [ 26/Nov/13 ]

See the following PRs:

https://github.com/doctrine/dbal/pull/274
https://github.com/doctrine/dbal/pull/245
https://github.com/doctrine/dbal/pull/282

This will be available via column's customSchemaOptions.

Comment by Doctrine Bot [ 11/Feb/14 ]

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





[DDC-1738] Allow multiple Generators per class Created: 29/Mar/12  Updated: 07/Sep/13

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

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


 Description   

We should be able to support multiple generators per class.
When doing partition per table, the partitioned column must be part of PK, which may enter in our limitation.

Currently we only support 1 generator per class.






[DDC-1308] Add cache for transient information and invalidation for ClassMetadata Created: 31/Jul/11  Updated: 20/Dec/11

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

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


 Description   

Two different things have to be improved in the caching:

1. The information isTransient() has to be moved to the ClassMetadataFactory and cached there.
2. The information getAllClassMetadataNames() can be cached
3. A debug/development mode should be introduced, leading to filemtime caching and checks so that you can use ApcCache and such in development.



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

Updating fix version





[DDC-1178] Have access to "original" metadata in events subscribed to loadClassMetadata Created: 27/May/11  Updated: 27/May/11

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

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


 Description   

If you subscribe to loadClassMetadata you will usually modify the metadata for some classes.
The problem is, that that data has to be loaded from somewhere. But later down the chain you can't get to it. Now data specific to what you need in your loadClassMetadata would ideally reside in the same location.
If we take for example a file, than all data for a specific entity is in the same file.

My proposal would be to add function get(Original|Raw)MappingData into interface Doctrine\ORM\Mapping\Driver\Driver which would either return raw data or data in a object specific for that Driver or null if it doesn't make sense for that driver. Please note, that when loading from e.g XmlDriver we should return simplexmlnode or dom node as loadClassMetadata should be in its own namespace and not pollute the Doctrine one.



 Comments   
Comment by Gediminas Morkevicius [ 27/May/11 ]

Sounds logic, each driver would expect NULL or data (wrapped specifically for the driver used)





[DDC-930] A table cannot have more than one many to many relationship with the same table when using reverse engineer Created: 13/Dec/10  Updated: 13/Dec/10

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

Type: Improvement Priority: Major
Reporter: Jiri Helmich Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 0
Labels: None
Environment:

FreeBSD, PostgreSQL 8.4



 Description   

This is caused by taking the join column name as the identifier while generating a property name for annotation. The mapping driver detects that the same property is already defined and ends the convert process. A little bit smarter approach for me was to take the local table name. But this assumes a specific style of join table naming convention.

Doctrine\ORM\Mapping\Driver\DatabaseDriver::loadMetadataForClass()

Replace:

$associationMapping['fieldName'] = Inflector::camelize(str_replace('_id', '', strtolower(current($otherFk->getColumns()))));

With:

$name = explode("_",$myFk->getLocalTableName());
if (count($name) > 1)
{
array_shift($name);
}
$name = implode("_", $name);

$associationMapping['fieldName'] = Inflector::camelize(str_replace('_id', '', strtolower($name)));

Maybe to switch to this behavior with an additional option?






[DDC-3195] indexBy implementation on containsKey of PersistentCollection in EXTRA LAZY mode uses property name as column name instead of column name Created: 26/May/14  Updated: 26/Jun/14

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

Type: Bug Priority: Major
Reporter: jos de witte Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Any



 Description   

indexBy implementation on containsKey (and possibly other EXTRA LAZY implemented methods) of PersistentCollection in EXTRA LAZY mode uses property name as column name instead of column name for OneToMany collections

For example property = fieldName, column name field_name.
Set indexBy on OneToMany annotation to fieldName (as it should be ) and it tries to use fieldName in backend instead of field_name






[DDC-3109] [Doctrine\ORM\Mapping\MappingException] Invalid field override named 'xxx' for class 'Entity\xxx' Created: 30/Apr/14  Updated: 26/Jun/14

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

Type: Bug Priority: Major
Reporter: david pichsenmeister Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: None
Environment:

kubuntu 14.04, php 5.5.9, MySQL 5.5


Attachments: File Organization.php     File User.php    
Issue Links:
Duplicate
duplicates DDC-2693 Attribute/association overrides shoul... Open

 Description   

Subclass should override association, but on generating entities, error:

[Doctrine\ORM\Mapping\MappingException]
Invalid field override named 'settings' for class 'Entity\Organization'.

is thrown. also, when updating schema, the assocations in the subclass are ignored (means are not present in the database).



 Comments   
Comment by Alexandre PAIXAO [ 23/May/14 ]

I think it is a duplicate of this bug : http://www.doctrine-project.org/jira/browse/DDC-2693





[DDC-3211] Annotation @ORM\Table(name="schema.table") don't generate sql using OCI8 Created: 09/Jul/14  Updated: 12/Jul/14

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

Type: Bug Priority: Major
Reporter: Jorge Potosme Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: cli, mapping, oci8, oracle, orm, symfony
Environment:

OS: Fedora 20
Web Server: Apache
DBMS: Oracle 12c
Framework: Symfony2
PHP version: 5.5.14
DBMS Driver: OCI8



 Description   

Using Symfony and "doctrine/orm": "2.4.@dev", "doctrine/doctrine-bundle": "1.3.@dev", with OCI8(Oracle Call Interface)
I have an entity
/**
* @ORM\Entity
* @ORM\Table(name="rrhh.usuario")
*/
class Usuario implements UserInterface

{ ... }

When i use de CLI (php app/console doctrine:schema:create --dump-sql) this don't show nothing, the output is empty.

If i change (name="rrhh.usuario") to (name="usuario", schema="rrhh") the CLI show the sql query but without the schema.



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

Duplicates this issue





[DDC-2840] Allow "options" on the id element for XmlDriver and AnnotationDriver Created: 06/Dec/13  Updated: 06/Dec/13

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

Type: Improvement Priority: Minor
Reporter: Marcus Dahlström Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

XmlDriver and AnnotationDriver does not allow for "options" on the "id" element, which the YamlDriver does.

This would help, since specifying "unsigned integer" using column-definition will make the doctrine orm:schema-tool:update think that the unsigned column in the database table doesn't match the signed integer in the mapping.

"From the YamlDriver"
    if (isset($idElement['options'])) {
        $mapping['options'] = $idElement['options'];
    }

Changes would need to take place in Doctrine\ORM\XmlDriver, doctrine-mapping.xsd and Doctrine\ORM\AnnotationDriver

I've come around this by extending the XmlDriver to parse the "options" element, and using a modified xsd file, but it would be helpful it it was actually part of doctrine.






[DDC-2721] CLONE - doctrine-mapping.xsd sequence relation-entities Created: 03/Oct/13  Updated: 03/Oct/13

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

Type: Bug Priority: Minor
Reporter: Benoît Burnichon Assignee: Guilherme Blanco
Resolution: Unresolved Votes: 0
Labels: None


 Description   

I noticed some problems with
the doctrine-mapping.xsd (which apparently is not used to validate the
mapping, but only provided to support code completion in your xml-
editor)

The order in which you define the elements like cascade and join-
column(s) for the relation-entities is currently important since it is
a sequence, but is this really desired? Why force this order? defining
cascade before join-column would make perfect sense as well, doesn't
it.

I looked in the repository and it seems xsd is not valid for all branches 2.1.x, 2.2, 2.3.4, 2.4.0-RC2 and master



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

Yes, order is not enforced in the driver itself either, so it could eventually be removed.





[DDC-2669] YAML mapping: discriminator map exception Created: 10/Sep/13  Updated: 10/Sep/13

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

Type: Bug Priority: Minor
Reporter: Peter Tulala Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: mapping, yaml


 Description   

I'm getting this exception when I generate all entities from YAML using orm:generate-entities:

[Doctrine\ORM\Mapping\MappingException]
Entity class 'Entity\PersonIndividual' used in the discriminator map of class 'Entity\Person' does not exist.

My discriminator map defined in Entity.Person.dcm.yml:

discriminatorMap:
  1: PersonIndividual
  2: PersonCompany
  3: PersonSelfEmployed

Mapping driver probably generates entities in wrong order, so entities defined in discriminator map does not exist when entity Person is being generated.

Note: The easiest workaround is to temporarily remove discriminatorMap definition from entity, generate entities, then put discriminatorMap back and then generate entities again. It would be great if it would be possible to generate all entities in only one step.






[DDC-2632] Doctrine reverse engineer doesn't honor NOT NULL foreign keys Created: 24/Aug/13  Updated: 24/Aug/13

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

Type: Bug Priority: Minor
Reporter: Paolo Avezzano Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: engineer, mysql, null, nullable, reverse, yaml
Environment:

MAMP, latest version. Symfony up to date



 Description   

In this table, the two foreign keys (which I had to downgrade from primary keys because of Doctrine and then added a separate PK named 'Id') called 'Oggetto' and 'Sistema' have been set as NOT NULL.


-- -----------------------------------------------------
-- Table `mydb`.`Composizione`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`Composizione` ;

CREATE  TABLE IF NOT EXISTS `mydb`.`Composizione` (
  `Id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
  `Oggetto` INT UNSIGNED NOT NULL ,
  `Sistema` INT NOT NULL ,
  INDEX `fk_Oggetto_has_Sistema_Sistema1_idx` (`Sistema` ASC) ,
  INDEX `fk_Oggetto_has_Sistema_Oggetto1_idx` (`Oggetto` ASC) ,
  PRIMARY KEY (`Id`) ,
  CONSTRAINT `fk_Oggetto_has_Sistema_Oggetto1`
    FOREIGN KEY (`Oggetto` )
    REFERENCES `mydb`.`Oggetto` (`Id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_Oggetto_has_Sistema_Sistema1`
    FOREIGN KEY (`Sistema` )
    REFERENCES `mydb`.`Sistema` (`Id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

Converting into Yaml here it is what I get.

    type: entity
    table: Composizione
    fields:
        id:
            id: true
            type: integer
            unsigned: true
            nullable: false
            column: Id
            generator:
                strategy: IDENTITY
    manyToOne:
        oggetto:
            targetEntity: Oggetto
            cascade:      {  }
            mappedBy:     null
            inversedBy:   null
            joinColumns:
                Oggetto:
                    referencedColumnName: Id
            orphanRemoval: false
        sistema:
            targetEntity: Sistema
            cascade:      {  }
            mappedBy:     null
            inversedBy:   null
            joinColumns:
                Sistema:
                    referencedColumnName: Id
            orphanRemoval: false
    lifecycleCallbacks: {  }

Basically it lost in translation the NOT NULL part.
To make it work I had to manually add two "nullable: false" lines as I did below:

    type: entity
    table: Composizione
    fields:
        id:
            id: true
            type: integer
            unsigned: true
            nullable: false
            column: Id
            generator:
                strategy: IDENTITY
    manyToOne:
        oggetto:
            targetEntity: Oggetto
            cascade:      {  }
            mappedBy:     null
            inversedBy:   null
            joinColumns:
                Oggetto:
                    referencedColumnName: Id
                    nullable:     false
            orphanRemoval: false
        sistema:
            targetEntity: Sistema
            cascade:      {  }
            mappedBy:     null
            inversedBy:   null
            joinColumns:
                Sistema:
                    referencedColumnName: Id
                    nullable:     false
            orphanRemoval: false
    lifecycleCallbacks: {  }

Is it a bug or am I missing something?

Regards,
Paolo Avezzano






[DDC-2467] Incorrect work with default values, indexes, autoincrement (patch attached) Created: 23/May/13  Updated: 28/May/13

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

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

Attachments: Text File ORM.patch    

 Description   

If you use in your MySQL database default values, indexes or string primary key, you get incorrect mapping by mapping generator. For get it - just use in database one or more from listed abilities, generate mapping for that and then try to dump-sql with schema-tool:update.

Hope you fix it. Tnx!



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

Marked as minor improvement - thank you for the patch!

Comment by And [ 28/May/13 ]

When it will be merged? Maybe, planned version?

Comment by Marco Pivetta [ 28/May/13 ]

And such a patch requires failing tests before being applied - that's up to whoever picks it up.

Comment by And [ 28/May/13 ]

So if I add patch with tests - it will be merged? =)

Comment by Marco Pivetta [ 28/May/13 ]

Most probably - you can open a pull request against the current ORM master for that





[DDC-2308] Naming Strategy for Reverse Engeneering Created: 21/Feb/13  Updated: 21/Feb/13

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

Type: Improvement Priority: Minor
Reporter: Andreas Prucha Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Unfortunately DatabaseDriver::getClassNameForTable() is declared as private method, which makes it quite difficult to change the naming strategy for reverse engeneering.

IMO this sould be declared protected. An even better way would be to extend the interface of the Naming Strategy objects to support the reverse direction:

classToTableName -> tableToClassName
propertyToColumnName -> columnToPropertyName.

This way we would have a consistent name-mapping






[DDC-2281] Validation against database-first generated xml requires that the column order within a composite primary key match the order the columns are in in mapping xml Created: 06/Feb/13  Updated: 09/May/13

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

Type: Bug Priority: Minor
Reporter: Aaron Moore Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

In using a database-first approach utilizing orm:convert-mapping to generate xml, the validation and schema-tool reports that my composite primary key (ex. Columns A, C, B) be dropped and added in the order in which the mapping appears in the xml (ex. Columns A, B, C).

These columns are not auto-increment and are simply a mixture of int and varchar.



 Comments   
Comment by Benjamin Eberlei [ 09/May/13 ]

Is the composite key a mix of association and field types?

Comment by Aaron Moore [ 09/May/13 ]

I'm trying to remember the usage as it was a short term project but I believe it is.

For example a user has a userid.

The table in question might have a primary key consisting of the userid and an int representing a year..





[DDC-2288] Schema Tool doesn't update collation on table level Created: 08/Feb/13  Updated: 08/Feb/13

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

Type: Improvement Priority: Minor
Reporter: Rickard Andersson Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: collation, schematool


 Description   

In Symfony2, when updating the collation option of a table, the schema tool doesn't recognize the change:

Changing from:

 
* @ORM\Table()

To:

 
* @ORM\Table(options={"collate"="utf8_swedish_ci"})

Results in:

 
$ php app/console doctrine:schema:update --dump-sql
Nothing to update - your database is already in sync with the current entity metadata.





[DDC-2053] [GH-460] added support to extend strategies for IdGenerators Created: 02/Oct/12  Updated: 22/Dec/13

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

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


 Description   

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

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

Message:

Mapping drivers now use extended classmetadata class to find constants of generator types.
Method completeIdGeneratorMapping is now protected and can be extended



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

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

Comment by Doctrine Bot [ 22/Dec/13 ]

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





[DDC-2035] XML Mapping : add attribute "length" for tag "id" Created: 20/Sep/12  Updated: 29/Sep/12

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

Type: New Feature Priority: Minor
Reporter: Erik Müller Assignee: Fabio B. Silva
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Linux, Doctrine ORM 2.3.0, MySQL



 Description   

XML mapping :

<id name="id" type="string" length="16"/>

Generate SQL :

id varchar(255) not null

It's not possible with XML mapping to have :

 id varchar(16) not null

Because tag "id" doesn't support "length" attribute.
Please add this attribute



 Comments   
Comment by Fabio B. Silva [ 20/Sep/12 ]

Hi Erik,

The atribute "id" arealdy support "length" in the current doctrine version
: https://github.com/doctrine/doctrine2/blob/2.3/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php#L259

Which version are you using ?





[DDC-2030] better way to detect class parents Created: 13/Sep/12  Updated: 13/Sep/12

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

Type: Improvement Priority: Minor
Reporter: Asmir Mustafic Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Hi!
Currently i'm heavy using doctrine to generate entities starting form database schema (aprox 500 tables with thousand of relations).

I'm trying to detect some inheritance cases, but there is a problem.

Doctrine always uses PHP class inheritance to detect entity hierarchy, but generating entities starting from database, i have not yet any php class.

There is a better way to detect entities hierarchy? Without php classes...
Mapping files should be self-sufficient, even without php files.

The practical case is:
in DatabaseDriver i'm trying to call $metadata->addDiscriminatorMapClass($name, $className) method, but it raises an exception if $classNam does not exists.

Even if i manualy create XML mapping files, and then i try to generate php entityes. There is the same problem. XmlDriver tries to call setDiscriminatorMap method that raises the same exception.






[DDC-1993] New method required: ClassMetadataInfo::isAssociationNullable() Created: 22/Aug/12  Updated: 22/Aug/12

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

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


 Description   

Hi,

I'm working with Symfony 2.1, and I need to know if an association is nullable for a given entity (to know if a form field should be marked as 'required'). So I'd like to have a isAssociationNullable() method in the ClassMetadataInfo class, that should do the same thing that the isNullable() method does for fields.

You can see more information about the problem on the Symfony issue.

Thanks.






[DDC-1373] Map file with specific class Created: 13/Sep/11  Updated: 14/Feb/12

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

Type: Improvement Priority: Minor
Reporter: Thomas Tourlourat - Armetiz Assignee: Fabio B. Silva
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Debian LAMP - PHP5.3 - Apache 2



 Description   

Hi there,
AbsractFileDriver is using the filename to know the managed class.

It's a cool feature because it's allow loading on-demand.
The problem is, that the filename must be the name of the Class.

It should be great to be able to manually map XML/YAML File description to a Class, like :
$drivers->addMappingFile ( array ( "filename" => "class", "filename2" => "class2") );

This feature is simple to implement, just add a new array inside AbsractFileDriver to know the mapping.
When using the current method with addPaths, parse the folder to get traditional XML/YAML file where filename corresponding to classname and add it to the mapping array.

AbsractFileDriver->getAllClassNames () just return value of mapping array.
The mapping array is store inside cache.

With this new feature, it allow developers to create a pretty folder that contains entities mapping.

Armetiz.



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

Updating fix version





[DDC-1198] Add PHPDocs to annotationclasses Created: 08/Jun/11  Updated: 08/Jun/11

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

Type: Documentation Priority: Minor
Reporter: Robert Gruendler Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: None


 Description   

If an IDE would like to support annotations, it's currently only possible to display all resolvable classes in a code-hint menu when autocompleting annotations, as
basically any class can be used for annotations.

To make it possible for IDEs to detect classes which are explicitly meant to be used as annotations, it would be nice to agree on some common
way of documenting annotations in PHPDocBlocks.

Here's an example of what this could look like:

https://github.com/pulse00/doctrine2/commit/25a14e9edc406edfd33e54fc38922a191e9cbe83

This way IDEs can prioritize annotated classes in code-hints and add additional information to the user.






[DDC-957] When there is no GeneratedValue strategy on a primary key, setter function should be generated Created: 29/Dec/10  Updated: 29/Dec/10

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

Type: Improvement Priority: Minor
Reporter: Flyn San Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 1
Labels: None
Environment:

PHP 5.3.3



 Description   

In the YAML/XML, if no GeneratedValue strategy is given for the primary key, a setter function is required in the generated entity class. Currently only a getter is made.






[DDC-747] Add support for table, column and indexes comments Created: 13/Aug/10  Updated: 14/Aug/10

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

Type: New Feature Priority: Minor
Reporter: s9e Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 5
Labels: None


 Description   

It would be nice to add support for table comments, column comments and indexes comments, i.e.

@Table(
    name="ecommerce_products",
    comment="Contains products",
    indexes={@index(name="search_idx", comment="Makes finding people by name easier", columns={"name", "email"})}
)

@Column(type="integer", comment="Stores the user's age, in years")

MySQL supports comments via ALTER TABLE since 4.1.
PostgreSQL support comments via COMMENT at least since 7.4.
SQLite doesn't appear to support table, column or indexes comments as of 3.7.
Oracle supports comments on tables and columns via COMMENT at least since 10.1. It doesn't appear to support comments on indexes.

For databases that don't support those persistent comments, you could use normal SQL comments in the table definition. Of course they wouldn't be stored by the database, but at least they would appear in the generated schema, that's better than nothing.






[DDC-3206] Possible to remove inversedBy (use only mappedBy)? Created: 05/Jul/14  Updated: 07/Jul/14

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

Type: Improvement Priority: Minor
Reporter: Ryan Weaver Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Hi guys!

This is another developer experience situation. Here is the flow:

1. I setup the owning side of a relationship (let's use ManyToMany, the hardest one for this)

2. Later, I decide to setup the inverse side of the relationship. When I do this, I of course add the `mappedBy` attribute so that it points to the exact property/relationship we're dealing with

3. Then, I also need to go back to the owning side and add `inversedBy`.

Why is step 3 (inversedBy) needed? Isn't this redundant information, since the `mappedBy` fully maps out that these 2 associations form different sides of the same relationship? I would love to remove this, I hate explaining to people starting with relationships to now go back to the main entity to add this key. It feels like duplication, which I think people sense.

Of course, I very well may be wrong and it may be needed .

Thanks!



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

I'd suggest doing the opposite: dropping mappedBy.

I'm not sure why JPA introduced this sort of bidirectional mapping, but for practical purposes, it makes it possible for us to load metadata for associations on both sides of the associations. Without having both mappedBy and inversedBy we'd be forced to scan through all existing mappings to find which pieces of the jigsaw fit together.

I don't think we have a good solution for this except for a "build mappings" step that warms up a cache, and that's a very radical architectural change that we can only introduce in 3.x

Comment by Maxime Veber [ 07/Jul/14 ]

Hi, please excuse me if what I say is wrong and do not hesitate to correct me, it's my first immertion in Doctrine code .

So I checked a little bit the situation in the code. I don't see the problem dropping inversedBy. It's easier understandable for the final user.
In facts right now the ManyToMany work very well with only `mappedBy` options so the `invertedBy` is clearly a duplicated information.

The problem for the implementation of this feature is that the ownerSide is decided by a single method for every mappings, so she's quite complexe. So the method decide only on using `mappedBy` and `invertedBy`. This behavior should be modifiable without too much troubles.

https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php#L1353

But another problem here is that should be discuss is that it's a big BC Break.





[DDC-1614] On OneToOne mappings with Primary Key same as Foreign Key, using @Id in the foreign association does not carry over when running "generate-entities" with --generate-annotations=1 Created: 22/Jan/12  Updated: 23/Jan/13

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

Type: Improvement Priority: Trivial
Reporter: Ryan Fink Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Fedora 15, php 5.3.8



 Description   

When having a OneToOne mapping that has a primary key that is the same as the foreign key, using the @Id attribute does not carry over when generating entities.

Example code:

class User
{
/**

  • @Id @Column(type="integer", nullable=false, columnDefinition="INT UNSIGNED NOT NULL AUTO_INCREMENT")
  • @GeneratedValue(strategy="AUTO")
    */
    private $id;

/**

  • @OneToOne(targetEntity="User_ExtraAttrs", cascade= {"persist","remove","detach","merge","refresh"}

    , mappedBy="User")

  • @JoinColumn(name="id", referencedColumnName="id")
    */
    private $UserAttrs;
    }

class User_ExtraAttrs
{
/**

  • @OneToOne(targetEntity="User", cascade= {"all"}

    , inversedBy="UserAttrs")

  • @Id
  • @JoinColumn(name="VehicleID", referencedColumnName="VehicleID")
    */
    private $User;
    }

When running "doctrine orm:generate-entities --regenerate-entities=1 --generate-annotations=1", the @Id in User_ExtraAttrs does not carry over. It must be manually inserted.






[DDC-1169] Entities outside of drivers' namespaces only give 'is not a valid entity' Created: 25/May/11  Updated: 25/May/11

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

Type: Improvement Priority: Trivial
Reporter: Jiří Petruželka Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Hi,
in a situation where entity, that EM is to work with, is not inside of any namespace (that should be specified in $chainDriverImpl->addDriver($metadataDriver, 'someNamespace'); )
-> gives error message 'Entity # is not a valid entity or mapped superclass' instead of notifying that the entity's namespace is not added






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

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

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


 Description   

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

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

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

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

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



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

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





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

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

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

Linux and Windows, PHP5


Attachments: File ArrayHydrator.php     File Array_Hydrator_4.2.php     File Array_hydrator_4.2_bugfix.php    

 Description   

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

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

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

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

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

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



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

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

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

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

Comment by Marco Pivetta [ 06/Feb/14 ]

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

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

Version 2.4.2 oryginal file and bugfix

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

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

Comment by Marco Pivetta [ 06/Feb/14 ]

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

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

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

Comment by Marco Pivetta [ 06/Feb/14 ]

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

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

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

Comment by Marco Pivetta [ 06/Feb/14 ]

Mariusz Jaskółka fixed, thanks!

Comment by Marco Pivetta [ 14/Jul/14 ]

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

Comment by Guilherme Blanco [ 14/Jul/14 ]

... and introducing BC breaks.





[DDC-3222] PostUpdate event destroying collectionUpdates Created: 21/Jul/14  Updated: 21/Jul/14

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

Type: Bug Priority: Critical
Reporter: Jacob Spizziri Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Mac OSX, AMP, php 5.3.27



 Description   

I have an entity that contains a Many-To-Many Unidirectional association. When the association is updated and the entity is flushed the changes are not being persisted to the database.

This is because the postUpdate event is being fired on executeUpdates, which is being called before the collection updates are being processed here:

            // Collection updates (deleteRows, updateRows, insertRows)
            foreach ($this->collectionUpdates as $collectionToUpdate) {
                $this->getCollectionPersister($collectionToUpdate->getMapping())->update($collectionToUpdate);
            }

This is occurring in UnitOfWork->commit() lines 333 through 366.

Apparently the postUpdate listener I wrote was causing the collectionUpdates property to be erased.



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

What does the listener actually do? Doesn't look like a bug to me...

Comment by Jacob Spizziri [ 21/Jul/14 ]

I'm using FOSElasticaBundle/ElasticSearch. On the postUpdate event I'm calling fos:elastica:populate on the entity indexes. Heres the code

<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

namespace SRC\Bundle\SearchBundle\EventListener;

use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;
use Doctrine\ORM\Event\LifecycleEventArgs;
use SRC\Bundle\ProductBundle\Entity\Product;
use SRC\Bundle\UserBundle\Entity\User;

/**
 * Description of SearchIndexer
 *
 * @author jacobspizziri
 */
class SearchIndexer
{	
	protected $container;
	protected $logger;
	
	public function __construct($container, $logger) {
		$this->container = $container;
		$this->logger = $logger;
	}
	
	
	public function postUpdate(LifecycleEventArgs $args){
		$this->index($args);
	}
	
	protected function index($args){
		$entity = $args->getEntity();

		$arguments = false;
		$command = new \FOS\ElasticaBundle\Command\PopulateCommand();
		$command->setContainer($this->container);
		
		//TODO: probably need to specify the --env=prod/dev
		// update Elastica on Product update
		if ($entity instanceof Product) {
			$this->logger->info('Updating Product Search Indexes');
			
			$arguments = array(
					'--index'=>'website',
					'--type' => 'product'
					);
		} else if ($entity instanceof User) {
			$this->logger->info('Updating User Search Indexes');

			$arguments = array(
					'--index'=>'website',
					'--type' => 'user'
					);
		}
		
		
		if($command && $arguments){
			$input = new ArrayInput($arguments);
			$output = new NullOutput();
			
			$result = $command->run($input, $output);
			$this->logger->info('Finished Updating Search Indexes with result: '. strval($result));
		}
	}
}
?>

Am I using this event incorrectly? Should I only be using postPersist?





[DDC-3224] getResult(HYDRATE_OBJECT) with joined query is returning reduced number of rows Created: 23/Jul/14  Updated: 23/Jul/14

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

Type: Bug Priority: Critical
Reporter: gondo Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: orm
Environment:

osx, PHP-FPM 5.5.13, nginx/1.6.0, mysql 5.6.19 Homebrew



 Description   

given that i have these 2 entities (pseodocode):

/**
 * @ORM\Table(name="entity1", options={"collate"="utf8_unicode_ci", "charset"="utf8"})
 * @ORM\Entity(repositoryClass="Entity1Repository")
 */
class Entity1 {
    /**
     * @var integer
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @var string
     * @ORM\Column(name="name", type="string")
     */
    protected $name;

    /**
     * @var Entity2[]
     * @ORM\OneToMany(targetEntity="Entity2", mappedBy="entity1")
     */
    protected $entity2;
}

/**
 * @ORM\Table(name="entity2", options={"collate"="utf8_unicode_ci", "charset"="utf8"})
 * @ORM\Entity()
 */
class Entity2 {
    /**
     * @var integer
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @var \DateTime
     * @ORM\Column(name="date", type="datetime")
     */
    protected $date;

    /**
     * @var Entity1
     * @ORM\ManyToOne(targetEntity="Entity1", inversedBy="entity2", fetch="EAGER")
     */
    protected $entity1;
}

tables and data

entity1:

id name
1 Jhon
2 Clare

entity2:

id date entity1_id
1 2011-01-01 00:00:01 1
2 2012-02-02 00:00:02 1
3 2013-03-03 00:00:03 2
4 2014-04-04 00:00:04 2

my query builder

use Doctrine\ORM\EntityRepository;

class Entity1Repository extends EntityRepository
{
    public function getData()
    {
        $qb = $this
            ->createQueryBuilder('Entity1')
            ->select('Entity1, Entity2.date')
            ->join('Entity1.entity2', 'Entity2', Join::WITH, 'Entity2.date > :date')
            ->setParameter('date', '2000-01-01 00:00:01')
        ;
        $result1 = $qb->getQuery()->getArrayResult(); // HYDRATE_ARRAY
        $result = $qb->getQuery()->getResult(); // HYDRATE_OBJECT
        
//        return $result1;
//        return $result2;
    }
}

proper result is this:

id name date
1 Jhon 2011-01-01 00:00:01
1 Jhon 2012-02-02 00:00:02
2 Clare 2013-03-03 00:00:03
2 Clare 2014-04-04 00:00:04

what is happening

$result1 = $qb->getQuery()->getArrayResult(); // HYDRATE_ARRAY

is really returning proper number of rows

BUT and here comes the BUG finally:

$result2 = $qb->getQuery()->getResult(); // HYDRATE_OBJECT

is returning just 2 rows:

id name date
1 Jhon 2011-01-01 00:00:01
2 Clare 2013-03-03 00:00:03

this is because somehow entities are made unique.

my workaround

as a workaround, what i have to do is, to exectute 2 queries. 1st to get just Entity1.ids joined with Entity2.dates by using `getArrayResult()`
and second query to get Entity1 objeces by unique ids from 1st query.
and than manualy join those results in php.



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

I see that you are using Join::WITH, but not providing a conditional in the example. Are you filtering a fetch-joined association?

Comment by gondo [ 23/Jul/14 ]

sorry i've tried to simplify my structure as much as it was possible, there are actually real conditions, one of them is date condition (among many others). i've updated my code

Comment by Marco Pivetta [ 23/Jul/14 ]

There are still some inconsistencies in the issue - where is that query parameter used, for example?

Comment by gondo [ 23/Jul/14 ]

im using it in EntityRepository (sorry, didnt know thats important) i ll update my code
and the whole code is in Symfony2 project (web and command line applications)

Comment by Marco Pivetta [ 23/Jul/14 ]

What I mean is that in

->setParameter('date', new \DateTime('last month'))

, parameter :date does not exist in the DQL.

Comment by gondo [ 23/Jul/14 ]

i see, sorry its part of JOIN condition, i've updated the code





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

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

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


 Description   

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

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

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

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



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

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

Comment by Frank Liepert [ 13/Apr/14 ]

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

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

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

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

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

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

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

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


/** 
 * NEW REQUEST
 */

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

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

Comment by Marco Pivetta [ 13/Apr/14 ]

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

Comment by Frank Liepert [ 13/Apr/14 ]

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





[DDC-3056] Return value mismatch between code under HHVM and Zend Created: 28/Mar/14  Updated: 28/Mar/14

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

Type: Bug Priority: Major
Reporter: Andy hunt Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: hhvm, orm, paginator
Environment:

Two environments:
LAMP stack with PHP 5.4.25 on Ubuntu 12.04
HHVM 3.0.0.-dev (rel) ob Ubuntu 12.04



 Description   

The following code produces differing results under Zend and HHVM runtimes.

// $all::build uses the query builder to select all entities of a type
/** @var \Doctrine\ORM\Query $query **/
$query = $all->build($qb);
$query->setMaxResults($pageSize)->setFirstResult($start);

$paginator = new Paginator($query);
$results = array_values((array)$paginator->getIterator());

Under Zend, $results is a 1-dimensional array containing N elements:
[1, 2, 3].

Under HHVM, $results is a 2-dimensional array containing a single array, containing N elements:
[ [1,3,3] ]



 Comments   
Comment by Christophe Coevoet [ 28/Mar/14 ]

I suggest reporting it to the HHVM team as a bug

Comment by Marco Pivetta [ 28/Mar/14 ]

Also: why are you using an array cast and not iterator_to_array?

Comment by Christophe Coevoet [ 28/Mar/14 ]

@Marco this should be equivalent. Casting a Traversable to array should traverse it. If HHVM does not do it, it is a bug.

Comment by Marco Pivetta [ 28/Mar/14 ]

Christophe Coevoet not really: http://3v4l.org/Z3t4t





[DDC-2995] Joined Inheritance Mapping and Filters Created: 22/Feb/14  Updated: 23/Mar/14

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

Type: Bug Priority: Major
Reporter: Bojidar Hristov Assignee: Marco Pivetta
Resolution: Unresolved Votes: 0
Labels: orm


 Description   

Is there any reason why Inheritance Mapping IS LEFT JOINED not INNER JOINED?

When there is a filter and it's left joined it happens a record might not have parent table record. For example

Class B extends Class A.
Class A have column is_active | and filter activated with is_active = 1 condition.

Final query: LEFT JOIN parent_table s1_ ON p2_.id = s1_.id AND (s1_.is_active = '1')

Record 1 have is_active = false, so result set looks like this:

table_b | table_a
id | id is_active discriminatorColumn
1 | null null null

and occurs exception: The discriminator column ... is missing for ....



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

JTI MUST be left-joined, since not every subclass of the root of the inheritance causes inserts on all of the inheritance tables.

What is the DQL query that is causing the problem?

Comment by Bojidar Hristov [ 22/Feb/14 ]

Hello Marco, I don't query from parent table, but from child. No sense to be LEFT JOINED.

DQL is something like that:

SELECT class1, class2 FROM Class1 class1 JOIN class1.class2 class2;

(Class2 extends Class3)
Class3 have is_active column.

And following filter:

public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias) {
if (!$targetEntity->reflClass->implementsInterface('ActivateableInterface'))

{ return ""; }

return $targetTableAlias . '.is_active = ' . $this->getParameter('isActive');
}

Filter condition is added in LEFT JOINED parent_table. Full example SQL:
SELECT ....
FROM class1 c1
INNER JOIN class2 c2 ON c1.c2_id = c2.id
LEFT JOIN table3 c3 ON c2.id = c3.id AND (c3.is_active = '1')

Comment by Marco Pivetta [ 26/Feb/14 ]

There are two possible solutions here:

  • verify if the selected entity is a leaf of a JTI, and use INNER JOIN on that if possible (probably not optimal, since the selection may be part of a LEFT JOIN itself)
  • add filtering on the discriminator column

Bojidar Hristov can you provide a failing test case to make it easier to work on this?

Comment by Bojidar Hristov [ 26/Feb/14 ]

Yes. Here is it sample failing test.

http://pastebin.com/xi8uUNX5 - Parent Class
http://pastebin.com/XRZLbyGX - Child Class
http://pastebin.com/HuPFb98u - Assoc Class
http://pastebin.com/hGqRk74e - TestCase

Here it should found 0 records because ot JOIN and is_active = true filter.

Comment by Benjamin Eberlei [ 23/Mar/14 ]

Since filters are only available on the root, i guess inner join is really necessary here.





[DDC-2981] Multi get for second level cache (Doctrine Cache related) Created: 13/Feb/14  Updated: 13/Feb/14

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

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


 Description   

Hi every body!

I'm developing an application that is highly based on doctrine second-level cache feature.
Using memcache or redis as cache back-end, doctrine have to query thousand times for the cached values (especially on one-to-many and many-to-many associations).
This introduces a lot of latency (and network traffic)...

I'm thinking to add to Doctrine\Common\Cache\Cache interface a method fetchMulti(array $keys) that fetches multiple items in one call. In this way doctrine orm can ask for many items with just one call (for example, here https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/Cache/DefaultCollectionHydrator.php#L84 this feature can be very useful).

I have made some real-world tests and it can reduce highly the number of total queries (my app runs 190 cache requests instead of 900 cache requests)

Many vendors (memcache, redis, apc ecc) already offer this functionality, but with doctrine-cache we can't use it...

I'm going to implement this feature. Can it be accepted as a pull request?

It may be BC breaking:

  • it can be implemented adding a method inside Doctrine\Common\Cache\Cache interface (more BC breaking but more clean and elegant)
  • it can be implemented adding an interface Doctrine\Common\Cache\MultiCache and later CacheProvider can implement it (less BC breaking)


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

Adding a method to Doctrine\Common\Cache\Cache is not viable because of BC - a new interface would be ok

Comment by Asmir Mustafic [ 13/Feb/14 ]

ok, i agree with you.
But this forces me to check always here https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/Cache/Region/DefaultRegion.php#L95 if $this->cache is instance of MultiCache

Comment by Marco Pivetta [ 13/Feb/14 ]

Asmir Mustafic or you build a MultiCacheRegion

Comment by Asmir Mustafic [ 13/Feb/14 ]

It can be a good approach. I will try it.
I'm thinking to provide a default implementation of fetchMulti directly inside CacheProvider that internally loops over each key and call CacheProvider::fetch($id) to fetch its value.
Later i will overwrite this behavior inside vendor specific driver (ApcCache, RedisCache...)





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

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

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

MySQL, using DoctrineORMModule (zf2 integration)



 Description   

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

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

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

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

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

Doing this:

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

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

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

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

Leads to

integrity constraint violation, b_id can not be null

aka

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

I have no idea why this happens. This works:

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

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

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

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


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

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





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

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

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

Linux and Windows, PHP 5, Oracle(OCI8)


Attachments: File LimitSubqueryOutputWalker.php     File LimitSubqueryOutputWalker_bugfix.php    

 Description   

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

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

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

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

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

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

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

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

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



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

Mariusz Jaskółka this needs more details

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

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

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

I have edited description, maybe additional information will help.

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

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

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

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

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

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





[DDC-2922] Flushing new Entities reachable over several paths that do not all "cascade persist" Created: 17/Jan/14  Updated: 17/Jan/14

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

Type: Bug Priority: Major
Reporter: Matthias Pigulla Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: None


 Description   

Please consider the following associations:

  A <>--> B <-- C  

A is an "aggregate" type object w/ a OneToMany collection of Bs. This association is set to cascade persist operations.

C has a unidirectional OneToOne association to B as well.

Adding a new B to A's collection and flushing the EntityManager works - B is persisted (persistence by reachability).

However, when also creating a new C and pointing it to the new B, adding C to the EntityManager and then flushing leads to an exception because B is discovered as a new Entity through a relationship not set to cascade persist operations.

Obviously the problem here is that there are two paths through which we can discover new Entities. The UoW currently starts search from newly (explicitly) added Entities first before it walks through collections of already-managed entities.

I am unsure if it is just a documentation issue or a deeper problem?

If the UoW worked the other way round, the same problem would occur if the cascade persist was on the other association.

A solution would probably require the UoW to first collect all offending (new) Entities and the link they were discovered through, but later on remove Entities from this list if they are found through another association with the cascade persist option. The exception must not be thrown unless the whole reachability graph has been traversed.






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

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

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


 Description   

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

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

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

Most interesting are rowCount and error related methods.



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

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

Comment by Flip [ 15/Jan/14 ]

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

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

or another situation ..

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





[DDC-2901] entity-listeners are not propagated to children of mapped superclasses Created: 09/Jan/14  Updated: 09/Jan/14

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

Type: Bug Priority: Major
Reporter: Stuart Carnie Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: mapping


 Description   

If I have event-listeners set on the subclass and mapped superclass, event-listeners will not be propagated, per this code. Conversely, lifecycle events are, per this






[DDC-2879] Persisting collections with Composite Primary Keys composed of 2 Foreign Keys and one metadata field Created: 31/Dec/13  Updated: 07/Jan/14

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

Type: Bug Priority: Major
Reporter: Dylan Johnson Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: composite, identity, mapping, orm, postgresql
Environment:

Ubuntu 13.04 and PostgresSQL 9.1.0 on Vagrant Virtual Machine running an application with Symfony2 backend and JavaScript client



 Description   

SYNOPSIS

Bug prevents persisting a collection of entities in a join table with a Composite Primary
Key made up of 2 Foreign Keys and one metadata field. From these mapping instructions:
http://docs.doctrine-project.org/en/latest/tutorials/composite-primary-keys.html#use-case-3-join-table-with-metadata

ISSUE DETAILS

SUCCESS: When FOREIGN KEY 1 is the same across items in a collection to be persisted, and FOREIGN KEY 2 is greater than FOREIGN KEY 2 in any existing PRIMARY KEY, the entity and collection are persisted correctly

    • Example: GPA "add val below" exists and has assessment value
      {"grade_point_average_id":1,"assessment_id":1,"value":4}

      We will try to add a new assessment value where assessment_id > that of any existing assessment value for GPA "add val below"

    • Request Payload:
      {"name":"Add Val Below","courses":[],"assessmentValues":[{"assessment":1,"value":4},{"assessment":3,"value":2}]}
    • Debug Log:
      [2014-01-07 11:48:01] app.INFO: START GRADE_POINT_AVERAGE_REPOSITORY #SAVE [GPA #GET_NAME =ADD VAL BELOW] [] []
      [2014-01-07 11:48:01] app.INFO:   BEGIN OUTPUT FOR GRADE POINT AVERAGE Add Val Below - ASSESSMENT VALUE 1 [] []
      [2014-01-07 11:48:01] app.INFO:         ASSESSMENT_VALUE #GET_GRADE_POINT_AVERAGE #GET_ID: 1 [] []
      [2014-01-07 11:48:01] app.INFO:         GRADE_POINT_AVERAGE #GET_ID: 1 [] []
      [2014-01-07 11:48:01] app.INFO:         ASSESSMENT_VALUE #GET_ASSESSMENT #GET_ID: 1 [] []
      [2014-01-07 11:48:01] app.INFO:         ASSESSMENT_VALUE #GET_VALUE: 4 [] []
      [2014-01-07 11:48:01] app.INFO:         MANAGED? 1 [] []
      [2014-01-07 11:48:01] app.INFO:   END OUTPUT FOR GRADE POINT AVERAGE Add Val Below - ASSESSMENT VALUE 2 [] []
      [2014-01-07 11:48:01] app.INFO:   BEGIN OUTPUT FOR GRADE POINT AVERAGE Add Val Below - ASSESSMENT VALUE 2 [] []
      [2014-01-07 11:48:01] app.INFO:         ASSESSMENT_VALUE #GET_GRADE_POINT_AVERAGE #GET_ID: 1 [] []
      [2014-01-07 11:48:01] app.INFO:         GRADE_POINT_AVERAGE #GET_ID: 1 [] []
      [2014-01-07 11:48:01] app.INFO:         ASSESSMENT_VALUE #GET_ASSESSMENT #GET_ID: 3 [] []
      [2014-01-07 11:48:01] app.INFO:         ASSESSMENT_VALUE #GET_VALUE: 2 [] []
      [2014-01-07 11:48:01] app.INFO:         MANAGED?  [] []
      [2014-01-07 11:48:01] app.INFO:   END OUTPUT FOR GRADE POINT AVERAGE Add Val Below - ASSESSMENT VALUE 3 [] []
      [2014-01-07 11:48:01] app.INFO: END GRADE_POINT_AVERAGE_REPOSITORY #SAVE [GPA #GET_NAME =ADD VAL BELOW] [] []
      [2014-01-07 11:48:01] doctrine.DEBUG: "START TRANSACTION" [] []
      [2014-01-07 11:48:01] doctrine.DEBUG: INSERT INTO gpa_assessment_value (point_value, grade_point_average_id, assessment_id) VALUES (?, ?, ?) {"1":2,"2":"1","3":"3"} []
      [2014-01-07 11:48:01] doctrine.DEBUG: UPDATE gpa_assessment_value SET point_value = ? WHERE grade_point_average_id = ? AND assessment_id = ? [4,1,1] []
      [2014-01-07 11:48:01] doctrine.DEBUG: "COMMIT" [] []

FAILURE: When FOREIGN KEY 1 is the same across items in a collection, and FOREIGN KEY 2 is less than any existing FOREIGN KEY 2, the unit of work tries to INSERT existing entity and does not operate on new entity. The EntityManager thinks it contains() the new entity, but not the old one

    • Example: GPA "add val above" exists and has assessment value
      {"assessment":3,"value":2}

      We will try to add a new assessment value where assessment_id < that of any existing assessment value for GPA "add val above"

    • Request Payload:
      {"name":"Add Val Above","courses":[],"assessmentValues":[{"assessment":1,"value":4},{"assessment":3,"value":2}]}
    • Debug log:
      [2014-01-07 11:47:09] app.INFO: START GRADE_POINT_AVERAGE_REPOSITORY #SAVE [GPA #GET_NAME =ADD VAL ABOVE] [] []
      [2014-01-07 11:47:09] app.INFO:   BEGIN OUTPUT FOR GRADE POINT AVERAGE Add Val Above - ASSESSMENT VALUE 1 [] []
      [2014-01-07 11:47:09] app.INFO:         ASSESSMENT_VALUE #GET_GRADE_POINT_AVERAGE #GET_ID: 2 [] []
      [2014-01-07 11:47:09] app.INFO:         GRADE_POINT_AVERAGE #GET_ID: 2 [] []
      [2014-01-07 11:47:09] app.INFO:         ASSESSMENT_VALUE #GET_ASSESSMENT #GET_ID: 1 [] []
      [2014-01-07 11:47:09] app.INFO:         ASSESSMENT_VALUE #GET_VALUE: 4 [] []
      [2014-01-07 11:47:09] app.INFO:         MANAGED? 1 [] []
      [2014-01-07 11:47:09] app.INFO:   END OUTPUT FOR GRADE POINT AVERAGE Add Val Above - ASSESSMENT VALUE 2 [] []
      [2014-01-07 11:47:09] app.INFO:   BEGIN OUTPUT FOR GRADE POINT AVERAGE Add Val Above - ASSESSMENT VALUE 2 [] []
      [2014-01-07 11:47:09] app.INFO:         ASSESSMENT_VALUE #GET_GRADE_POINT_AVERAGE #GET_ID: 2 [] []
      [2014-01-07 11:47:09] app.INFO:         GRADE_POINT_AVERAGE #GET_ID: 2 [] []
      [2014-01-07 11:47:09] app.INFO:         ASSESSMENT_VALUE #GET_ASSESSMENT #GET_ID: 3 [] []
      [2014-01-07 11:47:09] app.INFO:         ASSESSMENT_VALUE #GET_VALUE: 2 [] []
      [2014-01-07 11:47:09] app.INFO:         MANAGED?  [] []
      [2014-01-07 11:47:09] app.INFO:   END OUTPUT FOR GRADE POINT AVERAGE Add Val Above - ASSESSMENT VALUE 3 [] []
      [2014-01-07 11:47:09] app.INFO: END GRADE_POINT_AVERAGE_REPOSITORY #SAVE [GPA #GET_NAME =ADD VAL ABOVE] [] []
      [2014-01-07 11:47:09] doctrine.DEBUG: "START TRANSACTION" [] []
      [2014-01-07 11:47:09] doctrine.DEBUG: INSERT INTO gpa_assessment_value (point_value, grade_point_average_id, assessment_id) VALUES (?, ?, ?) {"1":2,"2":"2","3":"3"} []
      [2014-01-07 11:47:09] doctrine.DEBUG: "ROLLBACK" [] []
      [2014-01-07 11:47:09] event.DEBUG: Notified event "kernel.exception" to listener "Symfony\Component\Security\Http\Firewall\ExceptionListener::onKernelException". [] []
      [2014-01-07 11:47:09] event.DEBUG: Notified event "kernel.exception" to listener "Symfony\Component\HttpKernel\EventListener\ProfilerListener::onKernelException". [] []
      [2014-01-07 11:47:09] event.DEBUG: Notified event "kernel.exception" to listener "Symfony\Component\HttpKernel\EventListener\ExceptionListener::onKernelException". [] []
      [2014-01-07 11:47:09] request.CRITICAL: Uncaught PHP Exception Doctrine\DBAL\DBALException: "An exception occurred while executing 'INSERT INTO gpa_assessment_value (point_value, grade_point_average_id, assessment_id) VALUES (?, ?, ?)' with params [2, "2", "3"]:
      
      SQLSTATE[23505]: Unique violation: 7 ERROR:  duplicate key value violates unique constraint "gpa_assessment_value_pkey"
      DETAIL:  Key (grade_point_average_id, assessment_id)=(2, 3) already exists." at /vagrant/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php line 47 {"exception":"[object] (Doctrine\\DBAL\\DBALException: An exception occurred while executing 'INSERT INTO gpa_assessment_value (point_value, grade_point_average_id, assessment_id) VALUES (?, ?, ?)' with params [2, \"2\", \"3\"]:\n\nSQLSTATE[23505]: Unique violation: 7 ERROR:  duplicate key value violates unique constraint \"gpa_assessment_value_pkey\"\nDETAIL:  Key (grade_point_average_id, assessment_id)=(2, 3) already exists. at /vagrant/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php:47, PDOException: SQLSTATE[23505]: Unique violation: 7 ERROR:  duplicate key value violates unique constraint \"gpa_assessment_value_pkey\"\nDETAIL:  Key (grade_point_average_id, assessment_id)=(2, 3) already exists. at /vagrant/vendor/doctrine/dbal/lib/Doctrine/DBAL/Statement.php:138)"} []
         

CODE

migration.sql
CREATE TABLE assessment
(
    id       bigserial NOT NULL,
    scale_id bigint    NOT NULL,
    title    varchar   NOT NULL,
    passing  boolean   NOT NULL,
    rank     int,

    PRIMARY KEY (id)
);

CREATE TABLE assessment_scale
(
    id   bigserial NOT NULL,
    name varchar   NOT NULL,

    PRIMARY KEY (id)
);

-- ...

CREATE TABLE grade_point_average
(
    id                         bigserial       NOT NULL,
    name                       varchar         NOT NULL,
    additional_credit_allowance numeric(4, 2),

    PRIMARY KEY (id)
);

-- ...

CREATE TABLE gpa_assessment_value
(
    grade_point_average_id bigint        NOT NULL,
    assessment_id          bigint        NOT NULL,
    point_value            numeric(4, 2) NOT NULL,

    PRIMARY KEY (assessment_id, grade_point_average_id),
    FOREIGN KEY (assessment_id) REFERENCES assessment,
    FOREIGN KEY (grade_point_average_id) REFERENCES grade_point_average
);
GradePointAverage.php
<?php
namespace LGSConnect\Model;

use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Column;
//...
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
use LGSConnect\Util\ConstructorArgs;
use LGSConnect\Model\GradePointAverage\AssessmentValue;
// ...

/**
 * @Entity("LGSConnect\Repository\GradePointAverageRepository")
 */
class GradePointAverage
{
    // GradePointAverage Model (owning side): a tool for evaluating a student's performance 
    // by dividing the total points earned by total credits attempted.

    use ConstructorArgs;

    /**
     * @Id
     * @GeneratedValue
     * @Column(type="bigint")
     *
     * @var int
     */
    private $id;

    // ...

    /**
     * @OneToMany(targetEntity="LGSConnect\Model\GradePointAverage\AssessmentValue", mappedBy="gradePointAverage", cascade="persist")
     *
     * @var Collection
     */
    private $assessmentValues;
    
    // ...

    /**
     * @param array $args
     */
    public function __construct(array $args = [])
    {
        $this->assessmentValues = new ArrayCollection;
        // ...
        $this->handleArgs($args);
    }
    
    // ...
    
    /**
     * @return Collection
     */
    public function getAssessmentValues()
    {
        return $this->assessmentValues;
    }

    /**
     * @param ArrayCollection $assessmentValues
     */
    public function setAssessmentValues(ArrayCollection $assessmentValues)
    {
        $this->assessmentValues = $assessmentValues;
    }

    /**
     * @param AssessmentValue $assessmentValue
     */
    public function addAssessmentValue(AssessmentValue $assessmentValue)
    {
        $this->assessmentValues->add($assessmentValue);
    }

    /**
     * @param AssessmentValue $assessmentValue
     */
    public function removeAssessmentValue(AssessmentValue $assessmentValue)
    {
        $this->assessmentValues->removeElement($assessmentValue);
    }
    
    // ...
}
AssessmentValue.php
<?php
namespace LGSConnect\Model\GradePointAverage;

use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\Table;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\ORM\Mapping\JoinColumn;
use LGSConnect\Model\GradePointAverage;
use LGSConnect\Model\Assessment;
use LGSConnect\Util\ConstructorArgs;

/**
 * @Entity("LGSConnect\Repository\GradePointAverage\AssessmentValueRepository")
 * @Table("gpa_assessment_value")
 */
class AssessmentValue
{
    // AssessmentValue Model (inverse side): a number of points assigned 
    // to an Assessment by a Grade Point Average

    use ConstructorArgs;

    /**
     * @Id
     * @ManyToOne(targetEntity="LGSConnect\Model\GradePointAverage")
     */
    private $gradePointAverage;

    /**
     * @Id
     * @ManyToOne(targetEntity="LGSConnect\Model\Assessment")
     */
    private $assessment;

    /**
     * @Column("point_value")
     *
     * @var float
     */
    private $value;

    /**
     * @param array $args
     */
    public function __construct(array $args = [])
    {
        $this->handleArgs($args);
    }

    /**
     * @return GradePointAverage
     */
    public function getGradePointAverage()
    {
        return $this->gradePointAverage;
    }

    /**
     * @param GradePointAverage $gradePointAverage
     */
    public function setGradePointAverage(GradePointAverage $gradePointAverage)
    {
        $this->gradePointAverage = $gradePointAverage;
    }

    /**
     * @return Assessment
     */
    public function getAssessment()
    {
        return $this->assessment;
    }

    /**
     * @param Assessment $assessment
     */
    public function setAssessment(Assessment $assessment)
    {
        $this->assessment = $assessment;
    }

    /**
     * @return float
     */
    public function getValue()
    {
        return $this->value;
    }

    /**
     * @param float $value
     */
    public function setValue($value)
    {
        $this->value = $value;
    }

    /**
     * @return AssessmentScale
     */
    public function getAssessmentScale()
    {
        return $this->assessment->getScale();
    }
}
Assessment.php
<?php
namespace LGSConnect\Model;

use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\ManyToOne;
use LGSConnect\Model\Assessment\Scale;
use LGSConnect\Util\ConstructorArgs;

/**
 * @Entity("LGSConnect\Repository\AssessmentRepository")
 */
class Assessment
{
    // Assessment (related, but unmapped): A "grade" assigned to a student 
    // for attending a course section

    use ConstructorArgs;

    /**
     * @Id
     * @GeneratedValue
     * @Column(type="bigint")
     *
     * @var int
     */
    private $id;
    
    // ...

    /**
     * @param array $args
     */
    public function __construct(array $args = [])
    {
        $this->handleArgs($args);
    }

    /**
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }
    
    // ...
}
GradePointAverageRepository.php
<?php
namespace LGSConnect\Repository;

use Doctrine\ORM\EntityRepository;
// ...
use LGSConnect\Model\GradePointAverage;

class GradePointAverageRepository extends BaseRepository implements GradePointAverageRepositoryInterface
{
    // ...

    /**
     * @param GradePointAverage $gradePointAverage
     */
    public function save(GradePointAverage $gradePointAverage)
    {
        $this->getEntityManager()->persist($gradePointAverage);
        $this->getEntityManager()->flush();
    }
}
AssessmentValueRepository.php
<?php
namespace LGSConnect\Repository\GradePointAverage;

use Doctrine\ORM\EntityRepository;
use LGSConnect\Model\GradePointAverage\AssessmentValue;

class AssessmentValueRepository extends EntityRepository
{
    /**
     * @param AssessmentValue $assessmentValue
     */
    public function save(AssessmentValue $assessmentValue)
    {
        $this->getEntityManager()->persist($assessmentValue);
        $this->getEntityManager()->flush();
    }
}
GradePointAverageManager.php
<?php
namespace LGSConnect\Manager;

use InvalidArgumentException;
use Symfony\Component\Validator\ValidatorInterface;
use JMS\DiExtraBundle\Annotation\Service;
use JMS\DiExtraBundle\Annotation\InjectParams;
use JMS\SecurityExtraBundle\Annotation\PreAuthorize;
use Knp\Component\Pager\Pagination\PaginationInterface;
use LGSConnect\Repository\GradePointAverageRepository;
use LGSConnect\PaginationFactory\GradePointAveragePaginationFactoryInterface;
use LGSConnect\Model\GradePointAverage;

/**
 * @Service("grade_point_average_manager")
 */
class GradePointAverageManager
{
    /**
     * @var GradePointAverageRepository
     */
    private $gradePointAverageRepository;

    /**
     * @var GradePointAveragePaginationFactoryInterface
     */
    private $gradePointAveragePaginationFactory;

    /**
     * @var ValidatorInterface
     */
    private $validator;

    /**
     * @InjectParams
     *
     * @param GradePointAverageRepository $gradePointAverageRepository
     * @param GradePointAveragePaginationFactoryInterface $gradePointAveragePaginationFactory
     * @param ValidatorInterface $validator
     */
    public function __construct(
        GradePointAverageRepository $gradePointAverageRepository,
        GradePointAveragePaginationFactoryInterface $gradePointAveragePaginationFactory,
        ValidatorInterface $validator
    )
    {
        $this->gradePointAverageRepository = $gradePointAverageRepository;
        $this->gradePointAveragePaginationFactory = $gradePointAveragePaginationFactory;
        $this->validator = $validator;
    }

    /**
     * @PreAuthorize("isAllowedToManageTheGradePointAverage(#gradePointAverage)")
     * @param GradePointAverage $gradePointAverage
     * @throws InvalidArgumentException
     */
    public function save(GradePointAverage $gradePointAverage)
    {
        $violationList = $this->validator->validate($gradePointAverage);
        if ($violationList->count()) {
            throw new InvalidArgumentException;
        }

        $this->gradePointAverageRepository->save($gradePointAverage);
    }
}
GradePointAverageController.php
<?php
namespace LGSConnect\Controller;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Doctrine\Common\Collections\ArrayCollection;
use FOS\RestBundle\View\View;
use JMS\DiExtraBundle\Annotation\Service;
use JMS\DiExtraBundle\Annotation\InjectParams;
use JMS\SecurityExtraBundle\Annotation\PreAuthorize;
use Knp\Component\Pager\Pagination\PaginationInterface;
use LGSConnect\Manager\GradePointAverageManager;
use LGSConnect\Model\GradePointAverage;
use LGSConnect\Model\GradePointAverage\AssessmentValue;

/**
 * @Service("grade_point_average_controller", parent="lgs.controller.abstract")
 * @Route("/gpa", service="grade_point_average_controller")
 */
class GradePointAverageController extends BaseController
{
    /**
     * @var GradePointAverageManager
     */
    private $gradePointAverageManager;

    private $logger;

    /**
     * @InjectParams
     *
     * @param GradePointAverageManager $gradePointAverageManager
     * @param LoggerInterface $logger
     */
    public function __construct(GradePointAverageManager $gradePointAverageManager, LoggerInterface $logger)
    {
        $this->gradePointAverageManager = $gradePointAverageManager;
        $this->logger = $logger;
    }
    
    // ...

    /**
     * @Route("/{id}", name="gpa.edit", requirements={"id" = "\d+"})
     * @Method("PUT")
     *
     * @param Request $request
     * @param GradePointAverage $gpa
     * @return View
     */
    public function editAction(Request $request, GradePointAverage $gpa)
    {
        $form = $this->formFactory->createNamed(null, 'gpa', $gpa, [
            'method' => 'PUT',
        ]);
        $form->handleRequest($request);

        foreach ($gpa->getAssessmentValues() as $av) {
            $this->logger->info('GPA ID PREVALIDATE IN CONTROLLER:'.$gpa->getId());
            $this->logger->info('PREVALIDATE IN CONTROLLER ASSESSMENT VAL ASSESSMENT ID:'.$av->getAssessment()->getId());
            $this->logger->info('PREVALIDATE IN CONTROLLER ASSESSMENT VAL POINTS:'.$av->getValue());
        }

        /*
        // try reversing the order of the collection to see if that helps
        $assessmentVals = $gpa->getAssessmentValues()->toArray();
        $reversed = array_reverse($assessmentVals);
        $reversedColl = new ArrayCollection($reversed);
        $gpa->setAssessmentValues($reversedColl);
        */

        if ($form->isValid()) {