[DDC-633] fetch="EAGER" is not loading one to one associations Created: 11/Jun/10  Updated: 28/Sep/10  Resolved: 08/Aug/10

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

Type: Bug Priority: Critical
Reporter: Dave Keen Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 1
Labels: None


 Description   
<?php
namespace vo;

/**
 * @Entity
 */

class Appointment {
	
    /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
    public $id;
	
	/**
     * @OneToOne(targetEntity="Patient", inversedBy="appointment", fetch="EAGER")
	 * @JoinColumn(name="patient_id", referencedColumnName="id")
     */
	public $patient;
	
}

When doing a findAll() on appointments, $patient is being created as a proxy even though fetch is EAGER.



 Comments   
Comment by Benjamin Eberlei [ 08/Aug/10 ]

Fixed in master

Comment by Michael Moravec [ 17/Aug/10 ]

What is an advantage of this solution (in master) if it is loaded in the same way as when fetched lazily? Maybe it'd be better to use INNER JOIN instead, at least for OneToOne and save one or more (probably unnecessary) SQL queries?

Comment by Benjamin Eberlei [ 17/Aug/10 ]

There is none (yet), it may be a future enhancement, however we dont know this yet. fetch=EAGER is not so useful at the moment.

Comment by Michael Moravec [ 17/Aug/10 ]

I think that fetch=EAGER should behave like this DQL:
SELECT a, b FROM foo a JOIN a.bar b
This query will use INNER JOIN to load "a.bar" association, but fetch=EAGER won't.

Should I open a new issue for this?

Comment by Eduard Kracmar [ 28/Sep/10 ]

fetch=EAGER still is not working as I think it should.

class Project {

/**

  • @id
  • @column(type="integer")
  • @generatedValue(strategy="SEQUENCE")
    */
    private $id;
    /**
  • @manyToOne(targetEntity="Client", inversedBy="projects", fetch="EAGER")
  • @joinColumn(name="id_client", referencedColumnName="id",nullable=false, onDelete="cascade")
    */
    private $client;

but after

$this->getEntityManager()>find('\Entities\Project', $this>project);

2 doctrine queries are executed:

SELECT t0.id AS id1, t0.name AS name2, t0.paths AS paths3, t0.modified AS modified4, t0.created AS
created5, t0.has_running_tasks AS has_running_tasks6, t0.tasksCount AS taskscount7, t0.productsCount
AS productscount8, t0.id_client AS id_client9
FROM projects t0
WHERE t0.id = ?

SELECT t0.id AS id1, t0.name AS name2, t0.modified AS modified3, t0.created AS created4
FROM clients t0
WHERE t0.id = ?

And it should be one query with inner join to clients.

Comment by Benjamin Eberlei [ 28/Sep/10 ]

Eager doesnt mean it does a Join, it only means the query is executed directly

Comment by Eduard Kracmar [ 28/Sep/10 ]

I see. And how can be achieved that product and client will be queried at once, and not only when I request product->getClient() ?





[DDC-790] Generating entities with cli failed on inheritated entities due missing PK Created: 06/Sep/10  Updated: 16/Sep/10  Resolved: 15/Sep/10

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

Type: Bug Priority: Major
Reporter: Eduard Kracmar Assignee: Jonathan H. Wage
Resolution: Fixed Votes: 0
Labels: None
Environment:

Kubuntu lucid lynx



 Description   

While generating entities with:

./doctrine orm:generate-entities --generate-methods=true ../tmp/entities

getting MappingException: No identifier/primary key specified for Entity 'Entities\Admin'. Every Entity must have an identifier/primary key.

Admin is class inheritated, definition included:

Person: http://pastebin.com/5r9fXrAu
Admin: http://pastebin.com/51BcRZWZ



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

You cannot generate entities in an inheritance hierachy currently

Comment by Benjamin Eberlei [ 15/Sep/10 ]

AFter having looked at the mappings, how do you plan to generate methods from annotated entities? I think the entity generator won't allow that, jwage?

Comment by Jonathan H. Wage [ 15/Sep/10 ]

The problem with everything is that the inheritance hierarchy is not mapped, instead it is read at runtime from the classes themselves. So, when you're generating the initial entities from the mapping information, you don't have that information, so we can't properly generate a class with the "class ClassName extends SomeOtherClass" because we simply don't know it.

To work around it all you have to do is manually create the file with the empty class inside of it, extending the class you want. When you run the orm:generate-entities again, it can properly read the subclasses of every entity and the generation will update the classes existing classes properties and methods instead of trying to generate a new class.

Does that clear things up? I think the only way to fix it would be to allow the user to manually specify the all the inheritance information in the mapping information instead of reading it at run-time. That way we have all the information about some entities even before the actual classes exist and we can generate the right code then.

Thoughts?

Comment by Jonathan H. Wage [ 15/Sep/10 ]

Benjamin, yes it is possible. But like I mentioned above we don't know what class an entity extends until the class is created. You have no way to say in the mapping information that this entity extends this class.

If you have an entity already created with just the annotated properties, and you run the command to generate entities it will update the class adding the methods to the class. If you were to add a new property to the class and annotate and run the command again, it would only add the 2 new methods to the bottom of the class.

Comment by Eduard Kracmar [ 16/Sep/10 ]

This is really what I'm looking for. I create classes, fill them with properties and define annotations for them. Then I run cli tool to generate all methods (getters and setters) for classes to skip the boring part of creating entity. Then if required, I modify getters and setters.

Only problem was that it failed on classes that were inheritated because they were missing primary keys.

As a workaround while generating methods for new entities, I moved away from project inheritated entities and after generating I moved them back.





[DDC-522] Join columns can not be named the same as the association fields. Created: 15/Apr/10  Updated: 15/Sep/10  Resolved: 08/Aug/10

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

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

Issue Links:
Dependency
is required for DDC-419 Problem when I make a INNER JOIN betw... Closed
Reference
is referenced by DDC-774 Getting the primary key of a referenc... Resolved

 Description   

Join columns can currently not be named the same as the association fields in a class. This apparently causes Doctrine to insert the identifier of the associated object instead of the actual object (on hydration of the fetch-joined association at least).

Example:

    /**
     * @OneToOne(...)
     * @JoinColumn(name="item", referencedColumnName="id")
     */
    private $item;


 Comments   
Comment by Roman S. Borschel [ 08/Aug/10 ]

Fixed.





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

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

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

winXP, PHP 5.3.3



 Description   

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

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

{main}

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

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

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

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

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



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

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

Comment by Benjamin Eberlei [ 29/Aug/10 ]

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

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

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

For the next release this week this will be resolved.

Comment by Sherri Flemings [ 30/Aug/10 ]

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

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

I can now work with the sandbox examples.

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

<?php

require_once 'Doctrine/Common/ClassLoader.php';

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

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

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

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

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

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





[DDC-684] Flaw in Build Process? Created: 11/Jul/10  Updated: 30/Aug/10  Resolved: 30/Aug/10

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

Type: Task Priority: Critical
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

As I see it from our build script, each PEAR package of ORM and DBAL includes the Common sources again, although it sets itself as dependent on that package? That would mean the ORM package overwrites the files from the DBAL and Common packages.



 Comments   
Comment by Benjamin Eberlei [ 07/Aug/10 ]

Assigned to jon.

One solution would be to change the package.xml to reference only the ORM code, although DBAL and Common are also shipped.

Comment by Jonathan H. Wage [ 07/Aug/10 ]

Hmm. I don't understand what you mean. The ORM includes the DBAL and Common code and installs it? Should it not do that and require that you install the dependencies via PEAR?

Comment by Benjamin Eberlei [ 07/Aug/10 ]

yes, otherwise if you install DBAL after ORM, the DBAL code will overwrite the DBAL code from the ORM. Or the other way around.

Plus if you deinstall DBAL it will deinstall the DBAL code although ORM might still be installed.

I can come up with about 20 other scenarios where this is problematic

Comment by Roman S. Borschel [ 30/Aug/10 ]

Can we address this for BETA4 or should we push that to RC1 ? After releasing beta4 we still have time to address a lot of things before we go into RC.

Comment by Jonathan H. Wage [ 30/Aug/10 ]

I think the only solution is for the pear packages to only include the specific code for that package and the dependencies installed via pear. But even then, installing the ORM will require a certain version of the DBAL, so if you already have a version of the DBAL installed, it will need you to install the version the ORM requires. So either way you can't mix and match packages. If you use the ORM, you wouldn't ever have your own version of Common and DBAL installed because they would conflict.

Comment by Benjamin Eberlei [ 30/Aug/10 ]

yes, but that is a downside of PEAR that we cannot influence.

Comment by Jonathan H. Wage [ 30/Aug/10 ]

So the same problem exists either way. Do we have anything to fix then?

Comment by Benjamin Eberlei [ 30/Aug/10 ]

Fixed:

http://github.com/doctrine/dbal/commit/8054984a0448c54d5c658f60707b9ac490425c8b
http://github.com/doctrine/doctrine2/commit/803e33836518b7c019db667f482601f55803c29d

2 packages are now generated, one full package and one PEAR package. The PEAR package does not contain its dependencies, instead defines where to fetch them using the <dependencies><package> configuration for d51PearPkg2 task.





[DDC-778] Query Clone Removes DQL Created: 30/Aug/10  Updated: 30/Aug/10  Resolved: 30/Aug/10

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

Type: Bug Priority: Major
Reporter: Tim Oram Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

The fix for DDC-770 made the \Doctrine\ORM\AbstractQuery call the free method when __cloned. This is fine with an abstract query but when you clone from a Doctrine\ORM\Query it calls the free method of that class which nulls out the DQL statement. This breaks the example given in the Doctrine ORM cookbook of writing a custom walker.

This is either a bug in the documentation or a bug in Doctrine ORM.



 Comments   
Comment by Benjamin Eberlei [ 30/Aug/10 ]

Fixed!





[DDC-771] EntityGenerator generates wrong use statement in entity file Created: 27/Aug/10  Updated: 28/Aug/10  Resolved: 28/Aug/10

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

Type: Bug Priority: Major
Reporter: Martin Srom Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

PHP 5.3.2, Windows 7 Professional



 Description   

If I use EntityGenerator with class to extend 'Extension\\Doctrine\\ORM\\ActiveEntity
ActiveEntity' in generated files I have this use statement:

use Extension\Doctrine\ORM\ActiveEntity;

class XXX extends ActiveEntity

and php ends with error. I think the use statement should look like:

use Extension\Doctrine\ORM\ActiveEntity\ActiveEntity;

class XXX extends ActiveEntity

After I repaired this function it works ok:

private function _getClassToExtendNamespace()
{
    $refl = new \ReflectionClass($this->_getClassToExtend());

    return $refl->getNamespaceName() ? $refl->getNamespaceName():$refl->getShortName();
}

to

return $refl->getNamespaceName() ? $refl->getNamespaceName().'\\'.$refl->getShortName():$refl->getShortName();

I'am not sure if it is bug or I am doing something wrong.



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

fixed formating

Comment by Benjamin Eberlei [ 28/Aug/10 ]

Fixed

Comment by Martin Srom [ 28/Aug/10 ]

After your fix, the EntityGenerator generates this:

 
use Extension\Doctrine\ORM\ActiveEntity\ActiveEntity;

class XXX extends Extension\Doctrine\ORM\ActiveEntity\ActiveEntity

and it isn't still right. There are two right posibilities:

 
use Extension\Doctrine\ORM\ActiveEntity\ActiveEntity;

class XXX extends ActiveEntity

or

 
class XXX extends Extension\Doctrine\ORM\ActiveEntity\ActiveEntity
Comment by Benjamin Eberlei [ 28/Aug/10 ]

ok, i dropped the use statement.





[DDC-752] Postpone Metadata Validation Until After Driver and loadClassMetadata Has Executed Created: 17/Aug/10  Updated: 28/Aug/10  Resolved: 27/Aug/10

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

Type: Improvement Priority: Major
Reporter: Michael Ridgway Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

Right now the metadata drivers throw exceptions if certain metadata is not specified. While this is convenient for letting the user know about errors, it limits the extensibility of the ORM, specifically what you can do in the loadClassMetadata event. It also means that there is duplicated code in each of the driver implementations for validation.

All validation of the metadata should be postponed until after the metadata driver has executed and also after the loadClassMetadata event has been fired. This way all metadata has been loaded before attempting to validate and the user is still warned about errors. This validation should still be ignored when loading from cache.

Example use case:

Currently, setting a @DiscriminatorMap is required when using inheritance mapping. The loadClassMetadata event provides a way to dynamically set discriminator maps from a config or a database without having to extend a metadata driver.

The specific regression in functionality that this references is MappingException::missingDiscriminatorMap being thrown in the metadata drivers.



 Comments   
Comment by Michael Ridgway [ 17/Aug/10 ]

Added specific exception that has been causing issues for my use case. (MappingException::missingDiscriminatorMap)

Comment by Roman S. Borschel [ 17/Aug/10 ]

Sounds like a valid issue to me (and a regression).

The metadata drivers should not do this kind of validation. If this validation needs to be done it should happen later either somewhere in ClassMetadata(Info) or the ClassMetadataFactory.

Assigning this issue to Benjamin since I think he added this discriminator map validation in the drivers. I remember we talked about this but I did not properly recognize this issue either.

Comment by Michael Ridgway [ 17/Aug/10 ]

Committed a fix for my use case at http://github.com/mridgway/doctrine2/commit/9acfa8b7c3ea17f4ee75608deb4cb474a799353c

This moves the discriminatorMap validation to ClassMetadataFactory::_loadMetadata

Comment by Benjamin Eberlei [ 27/Aug/10 ]

fixed

Comment by Roman S. Borschel [ 28/Aug/10 ]

I'm not sure but is it right that this validation in the CMF takes place before the loadClassMetadata event is fired? After all, this event is supposed to be used for dynamic completion of the metadata.

Comment by Benjamin Eberlei [ 28/Aug/10 ]

i shouldn't code at late in the night, will fix it

Comment by Benjamin Eberlei [ 28/Aug/10 ]

@Roman, what about the ID stuff? Can i just move the event before every CMF validation?

Comment by Roman S. Borschel [ 28/Aug/10 ]

Maybe, but I would just try to leave the old order intact to not risk any BC issues. Simply moving the inheritance validation below the event should be enough for now.





[DDC-770] Cleanup Query instance when cloneed Created: 26/Aug/10  Updated: 27/Aug/10  Resolved: 27/Aug/10

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

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


 Description   

When calling clone $query the instance should be cleaned from parameters.



 Comments   
Comment by Benjamin Eberlei [ 27/Aug/10 ]

fixed





[DDC-757] Make names for tables and join columns not mandatory Created: 19/Aug/10  Updated: 26/Aug/10  Resolved: 26/Aug/10

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

Type: New Feature Priority: Major
Reporter: Petr Motejlek Assignee: Roman S. Borschel
Resolution: Fixed Votes: 0
Labels: None


 Description   

Why is it necessary to specify a name when using the @Table annotation (I guess it's the same using Yaml or XML) when I just want to add some indexes or unique constraints? When I do not specify the @Table at all, the name is generated from the entity's class, why can't it be also generated when I just want to add indexes or uniqueConstraints? My point is why should I write so many same stuff so many times, when Doctrine can already use it's API to do it for me. Preferably I would like to only specify the name when I need to change it from the default, not every time I need to add some explicit indexes The same applies to the @JoinColumn annotation. When I want a nullable=false column, I have (again) specify a name for it, but the generated name would work just fine. Why do I have to specify it by hand?



 Comments   
Comment by Roman S. Borschel [ 19/Aug/10 ]

Yes, the default/inferred value handling is not very smart yet. We will look into improving this in the future.

Comment by Petr Motejlek [ 19/Aug/10 ]

Thanks. If you'd like, I can try to look into it and make some patchsets, since I'll probably want to correct it for myself as soon as possible.

Comment by Petr Motejlek [ 19/Aug/10 ]

I've successfully created a patch for this issue, it's at http://github.com/petr-motejlek/doctrine2/commit/d8359646fb43b7e1c42c3296ea8d7ebf3d18c51d
I've also issued a pull request for that.

Comment by Petr Motejlek [ 19/Aug/10 ]

So the above-mentioned fix was not that good as I thought it was. This one works perfectly http://github.com/petr-motejlek/doctrine2/commit/e2522a9d4ed74c12356000d03a0aad7c6a34841f#diff-1. Now it should be possible to omit the JoinTable, Table and JoinColumn names, Doctrine will try to generate them automatically.

Comment by Roman S. Borschel [ 26/Aug/10 ]

I committed a modified version of your patch (i.e. it also allows leaving off referencedColumnName as well). I also made inferred default column names lowercase for aesthetics.

Thanks for your help!

Comment by Petr Motejlek [ 26/Aug/10 ]

Thank you





[DDC-737] Update PersistentCollection to upport slice($offset, $length); Created: 08/Aug/10  Updated: 24/Aug/10  Resolved: 24/Aug/10

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

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


 Description   

With DCOM-17 the Collection interface will be updated to contain one new method, this has to be implemented naively for now:

public function slice($offset, $length = null)
{
    $this->initialize();
    return $this->_col->slice($offset, $length);
}


 Comments   
Comment by Benjamin Eberlei [ 24/Aug/10 ]

Implemented.





[DDC-704] Inheritance-type with no discriminator-column results in SQL Error Created: 20/Jul/10  Updated: 16/Aug/10  Resolved: 08/Aug/10

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

Type: Bug Priority: Minor
Reporter: Chris Mealey Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

PHP 5.3 Ubuntu Linux



 Description   

On an entity (XML mapping atleast) if there is an inheritance-type set but no discriminator-column(s) set the resulting query will have an extra comma at the end of the field list or occasionally (based on inheritance-type) a table alias without a fieldname.

The correct solution would be to throw an exception during the parsing of the mapping that would indicate the inheritance-type is set but no discriminator-columns exist.



 Comments   
Comment by Chris Mealey [ 20/Jul/10 ]

Moving this from Major to Minor as a correctly mapped entity works fine, the bug is in the error reporting, not the functionality

Comment by Benjamin Eberlei [ 08/Aug/10 ]

Implemented better validation

Comment by Michael Ridgway [ 16/Aug/10 ]

I can't help but feel that the validation should be implemented outside of the metadata drivers. To me the driver shouldn't require the discriminator map to be present because it limits the ability to add discriminators in other ways.

Example:

I use annotations for my models, but I don't set the discriminator maps using the annotations driver, instead I use the loadClassMetadata event to fill in the discriminatorMap from configs or a database. Perhaps this is a job for a custom metadata driver, but I still can't help but feel that the metadata driver shouldn't be the one making these validations, it should be when you try to use the inheritance-mapped model.

Edit: To clarify the situation: I now get mappingException::missingDiscriminatorMap exception because my model annotations don't have a @DiscriminatorMap, but they would be loaded with the loadClassMetadata function.





[DDC-695] throw error on non-existing relation target column Created: 19/Jul/10  Updated: 12/Aug/10  Resolved: 12/Aug/10

Status: Closed
Project: Doctrine 2 - ORM
Component/s: DQL
Affects Version/s: 2.0-BETA2
Fix Version/s: 2.0-BETA4
Security Level: All

Type: Improvement Priority: Major
Reporter: Martin Ivičič Assignee: Roman S. Borschel
Resolution: Won't Fix Votes: 0
Labels: None
Environment:

any



 Description   

I had a problem with invalid SQL generated from DQL using JOIN the DQL query was as simple as:

SELECT k, kt FROM Kmz k JOIN k.kmzType kt

the final SQL missed the joined column name:

SELECT k0_.ID_KMZ AS ID_KMZ0, k0_.ID_KMZ_TYPE AS ID_KMZ_TYPE1, k0_.IDENTIFICATOR_HW AS IDENTIFICATOR_HW2, k0_.TIME_INSERT AS TIME_INSERT3, k1_.ID_KMZ_TYPE AS ID_KMZ_TYPE4, k1_.SHORTNAME AS SHORTNAME5, k1_.DESCRIPTION AS DESCRIPTION6, k0_.id_KMZ_TYPE AS id_KMZ_TYPE7 FROM KMZ k0_ INNER JOIN KMZ_TYPE k1_ ON k0_.id_KMZ_TYPE = k1_.

After some time of xdebugging I found that the names in JoinColumn clause in Kmz class annotation were not UPPERCASE as in KmzType - I just got a notice in SQL walker (line 728).

if ($relation->isOwningSide)

{ $quotedTargetColumn = $targetClass->getQuotedColumnName($targetClass->fieldNames[$targetColumn], $this->_platform); // <-- PHP Notice: Undefined index: id_KMZ_TYPE in .../libs/Doctrine/ORM/Query/SqlWalker.php:728 $sql .= $sourceTableAlias . '.' . $sourceColumn . ' = ' . $targetTableAlias . '.' . $quotedTargetColumn; }

else

{ $quotedTargetColumn = $sourceClass->getQuotedColumnName($sourceClass->fieldNames[$targetColumn], $this->_platform); $sql .= $sourceTableAlias . '.' . $quotedTargetColumn . ' = ' . $targetTableAlias . '.' . $sourceColumn; }

I think there might be a check and error thrown in case of missing targetColumn.



 Comments   
Comment by Guilherme Blanco [ 12/Aug/10 ]

This is not related to DQL.

We have a validate-mapping CLI command that can verify this for you.
The problem you have is a bug in your mapping definition, nothing related to Doctrine core.

If we add exceptions to all situations, DQL could not perform well. =\

Marking as won't fix.





[DDC-738] Default Allocation Size remains still 10 in Beta 3 Created: 09/Aug/10  Updated: 12/Aug/10  Resolved: 12/Aug/10

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

Type: Bug Priority: Major
Reporter: Jan Tichý Assignee: Roman S. Borschel
Resolution: Fixed Votes: 0
Labels: None


 Description   

It seems like default allocation size for sequences remains still 10 in Beta 3 - see http://github.com/doctrine/doctrine2/blob/2.0.0-BETA3/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php - although it should have been already fixed. See also related older ticket - http://www.doctrine-project.org/jira/browse/DDC-577



 Comments   
Comment by Guilherme Blanco [ 12/Aug/10 ]

Fixed in http://github.com/doctrine/doctrine2/commit/5719f8523bbb3c8a6fd11c749e5317b238d3d2b3





[DDC-581] Unable to use single value association with IN expression Created: 11/May/10  Updated: 11/Aug/10  Resolved: 11/Aug/10

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

Type: Bug Priority: Minor
Reporter: Ivan Voskoboynyk Assignee: Guilherme Blanco
Resolution: Fixed Votes: 0
Labels: None


 Description   

DQL doesn't allow to use Single Value Association with IN expression.

According to documentation:

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

I think it should be like that:

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

Suggested solution:
Edit Parser::inExpression method to accept SingleValuedPathExpressions:

    public function InExpression()
    {
        $inExpression = new AST\InExpression( /* Added this: */ $this->SingleValuedPathExpression() );
        ... 
    }

Test case:

$address1 = new \Entities\Address();
$address1->setStreet("Test Street #1");
$em->persist($address1);

$userA = new \Entities\User();
$userA->setName('user A');
$userA->setTest('test A');
$userA->setAddress( $address1 );
$em->persist($userA);

$userB = new \Entities\User();
$userB->setName('user B');
$userB->setTest('test B');
$userB->setAddress( $address1 );
$em->persist($userB);

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


$dql = "SELECT u FROM Entities\User u WHERE u.address IN (SELECT a FROM Entities\Address a WHERE a.street LIKE 'Test Street%' ) ";
$query = $em->createQuery($dql);


$result = $query->getResult();
foreach ($result as $user) {
    echo "<pre>";
    \Doctrine\Common\Util\Debug::dump($user);
    echo "</pre>";
    $em->remove($user);
}

$em->flush();

Without this change It's impossible to select entities having specified association by a subquery with no additional join.

Now this could be done with this DQL:

SELECT u FROM Entities\User u WHERE u.address.id IN (SELECT a.id FROM Entities\Address a WHERE a.street LIKE 'Test Street%' )

But it requires to join addresses table for u.address.id field, which in fact is redundant and ineffective.

Tried to find similar issues or feature requests but no results. So I posted it here.



 Comments   
Comment by Roman S. Borschel [ 14/May/10 ]

This would only work in one direction though ... in the other direction you need a join anyway and it will also not work with composite keys...

Besides that, you can do this:

SELECT u FROM Entities\User u WHERE u.address.street LIKE 'Test Street%' 

or more explicit

SELECT u FROM Entities\User u JOIN u.address a WHERE a.street LIKE 'Test Street%' 

The performance of join vs subquery should be just as good on most systems, on mysql joins are often even faster than subqueries.

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

Unscheduling as this enhancement is questionable and not really necessary (see my last comment).

Comment by Guilherme Blanco [ 11/Aug/10 ]

Fixed. Implemented this support in:

http://github.com/doctrine/doctrine2/commit/496a34a4d246f7b3e628e37963d8950e43540733





[DDC-680] Complex Mathematical Expressions in DQL Subselects Created: 10/Jul/10  Updated: 11/Aug/10  Resolved: 11/Aug/10

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

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

Attachments: File DDC680patch.diff    

 Description   

It seems complex mathematical expressions are handled differently in DQL Subselects then in normal Selects:

    public function testSelectCorrelatedSubqueryComplexMathematicalExpression()
    {
        $this->assertSqlGeneration(
            'SELECT (SELECT (count(p.phonenumber)+5)*10 FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p JOIN p.user ui WHERE ui.id = u.id) AS c FROM Doctrine\Tests\Models\CMS\CmsUser u',
            'SELECT (SELECT (count(c0_.phonenumber)+5)*10 AS dctrn__1 FROM cms_phonenumbers c0_ INNER JOIN cms_users c1_ ON c0_.user_id = c1_.id WHERE c1_.id = c2_.id) AS sclr0 FROM cms_users c2_'
        );
    }

    public function testSelectComplexMathematicalExpression()
    {
        $this->assertSqlGeneration(
            'SELECT (count(p.phonenumber)+5)*10 FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p JOIN p.user ui WHERE ui.id = ?1',
            'SELECT (count(c0_.phonenumber) + 5) * 10 AS sclr0 FROM cms_phonenumbers c0_ INNER JOIN cms_users c1_ ON c0_.user_id = c1_.id WHERE c1_.id = ?'
        );
    }

Here the first test fails and the second passes. The second has the nested SQL running alone. The failure message is:

1) Doctrine\Tests\ORM\Query\SelectSqlGenerationTest::testSelectCorrelatedSubqueryComplexMathematicalExpression
[Syntax Error] line 0, col 15: Error: Expected One of: MAX, MIN, AVG, SUM, COUNT, got '('

/home/benny/code/php/wsnetbeans/doctrine2/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php:31
/home/benny/code/php/wsnetbeans/doctrine2/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php:709


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

The problem seems to be in SelectExpression(). Functions are only detected in isolation, i.e. everything after the first function is ignored.

Comment by Guilherme Blanco [ 10/Aug/10 ]

Patch that fixes the issue.

However, I am not 100% if the alias (sclr) of subquery select expression should be generated and added to RSM.
Can anyone chat with me tomorrow and agree on this patch?

Comment by Guilherme Blanco [ 11/Aug/10 ]

New patch

Comment by Guilherme Blanco [ 11/Aug/10 ]

In http://github.com/doctrine/doctrine2/commit/84b9eda17c8faead9ea59b39f12d1b78aa5ba823 I have committed a fix to this issue.





[DDC-729] When merging many to many entities back into the repository all associations are deleted on the next flush Created: 31/Jul/10  Updated: 11/Aug/10  Resolved: 09/Aug/10

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

Type: Bug Priority: Critical
Reporter: Dave Keen Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

When merging a DETACHED entity into the repository with a ManyToMany association, the entries in the join table are deleted on the next flush.

Many Movies have many Artists:

class Movie {
	
	/** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
	public $id;
	
	/** @Column(length=50, type="string") */
	public $title;
	
	/** 
	 * @ManyToMany(targetEntity="Artist")
	 */
	public $artists;
	
	public function __construct() {
		$this->artists = new ArrayCollection();
	}
	
}
class Artist {
	
	/** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
	public $id;
	
	/** @Column(length=50, type="string") */
	public $name;
	
	/** @ManyToMany(targetEntity="Movie", mappedBy="artists") */
	public $movies;
	
	public function __construct() {
		$this->movies = new ArrayCollection();
	}
	
}

Assume that the database contains:
Movie: id=1, title="Movie 1"
Artist: id=1, name="Artist 1"

and that there is a entry (1, 1) in movie_artist so that there is a many-many relationship between Movie 1 and Artist 1.

I then run the following code to merge the existing associations into the entity manager:

$m1 = new \vo\Movie();
$m1->id = 1;
$m1->title = "Movie 1";

$a1 = new \vo\Artist();
$a1->id = 1;
$a1->name = "Artist 1";

$m1->artists->add($a1); $a1->movies->add($m1);

$m1 = $em->merge($m1);
$m1->artists->set(0, $em->merge($a1));
$a1->movies->set(0, $em->merge($m1));

At this point $m1 should contains merged entities reflecting the same as what is in the database.

If I now run:

$em->flush()

the association is deleted from movie_artist and the SQL log shows DELETE FROM Movie_Artist WHERE Movie_id = '1' as having been run.

Debugging $m1 both before and after the flush shows the expected values, and $em->getUnitOfWork()->computeChangeSets() is empty before the flush.



 Comments   
Comment by Benjamin Eberlei [ 08/Aug/10 ]

Can you explain why you merge $m1 twice?

Comment by Dave Keen [ 08/Aug/10 ]

Its a representation of how the algorithm I am using works - it assumes that once an entity is managed merge() will just return the already managed entity.

Anyway, to be sure I just ran another test that only calls merge() once, and it has the same behaviour.

Comment by Benjamin Eberlei [ 08/Aug/10 ]

Fixed

Comment by Dave Keen [ 09/Aug/10 ]

A slightly different many to many merge bug is occurring - I am re-opening this ticket for it because a) I expect it is somewhat related and b) the example to recreate follows on from the example in this bug.

Now assume the database has one more artist:

Movie: id=1, title="Movie 1"
Artist: id=1, name="Artist 1"
Artist: id=2, name="Artist 2"

and that there is still only an entry (1, 1) in movie_artist so that there is a many-many relationship between Movie 1 and Artist 1.

I then run the following code to merge the existing entity AND add a new association between artist 2 and movie 1:

$m1 = new \vo\Movie();
$m1->id = 1;
$m1->title = "Movie 1";

$a1 = new \vo\Artist();
$a1->id = 1;
$a1->name = "Artist 1";

$a2 = new \vo\Artist();
$a2->id = 2;
$a2->name = "Artist 2";

$m1->artists->add($a1); $a1->movies->add($m1);
$m1->artists->add($a2); $a2->movies->add($m1);

$m1 = $em->merge($m1);

$m1->artists->set(0, $em->merge($a1));
$a1->movies->set(0, $em->merge($m1));

$m1->artists->set(1, $em->merge($a2));
$a2->movies->set(1, $em->merge($m1));

If I now run:

$em->flush();

Instead of getting a (1, 2) entry added to movie_artist as expected, the change sets are empty and I get the following error:

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1-2' for key 'PRIMARY'' in D:\Projects\ORM\doctrine2\lib\vendor\doctrine-dbal\lib\Doctrine\DBAL\Connection.php on line 646
( ! ) PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1-2' for key 'PRIMARY' in D:\Projects\ORM\doctrine2\lib\vendor\doctrine-dbal\lib\Doctrine\DBAL\Connection.php on line 646
Call Stack

  1. Time Memory Function Location
    1 0.0006 400744 {main}

    ( ) ..\index.php:0
    2 0.0933 4375416 Doctrine\ORM\EntityManager->flush( ) ..\index.php:62
    3 0.0934 4375416 Doctrine\ORM\UnitOfWork->commit( ) ..\EntityManager.php:320

Comment by Benjamin Eberlei [ 09/Aug/10 ]

There is no CASCADE=MERGE on this relation or?

Comment by Dave Keen [ 09/Aug/10 ]

No - I think I am simulating what cascade merge would do though.

Comment by Benjamin Eberlei [ 09/Aug/10 ]

I cannot reproduce this with any case.

Additionally your algorithm is REALLY slow compared to doing this natively in the UnitOfWork. The merge operation does lots of stuff even if the entity is already merged before.

Comment by Benjamin Eberlei [ 09/Aug/10 ]

Added 3 more tests that verify the correct behavior. Please add a failing test-case for this and open up a new ticket.

Comment by Dave Keen [ 11/Aug/10 ]

Thanks for pointing out the inefficiency in the algorithm - you are completely right and as recommended I have changed the Flextrine codebase to use UnitOfWork merge (by internally changing the metadata to enable cascade). However, there still seems to be a bug mergng many to many - I will open it up in a new ticket. Cheers





[DDC-562] @OneToOne is not generating a unique constraint on the owning table Created: 30/Apr/10  Updated: 10/Aug/10  Resolved: 10/Aug/10

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

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

Win 7 x64, PHP 5.3.1


Issue Links:
Dependency
depends on DDC-626 Remove Association Classes Closed

 Description   

Annotations:

<?php

/** @Entity */
class Customer
{
    /**
     * @Id @Column(name="id", type="integer")
     */
    private $customerId;

    /**
     * @OneToOne(targetEntity="Cart", mappedBy="customer")
     */
    private $cart;
}

/** @Entity */
class Cart
{
    /**
     * @Id @Column(name="id", type="integer", nullable=false)
     */
    private $cartId;

    /**
     * Shouldn't unique=true be setting a UNIQUE index on customer_id ??
     *
     * @OneToOne(targetEntity="Customer", inversedBy="cart")
     * @JoinColumn(name="customer_id", referencedColumnName="id", nullable=false, unique=true)
     */
    private $customer;
}

Resulting schema (MySQL), generated with orm:schema-tool:create in CLI:

CREATE TABLE `customer` (
  `id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `cart` (
  `id` int(11) NOT NULL,
  `customer_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `customer_id` (`customer_id`),  /* this should be UNIQUE KEY  */
  CONSTRAINT `cart_ibfk_1` FOREIGN KEY (`customer_id`) REFERENCES `customer` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

I think the key on customer_id in the cart should be generating a UNIQUE KEY by definition on a @OneToOne, with or without the unique= param in the annotation, right?

I've tested this with and without the unique=true param and in both cases it does not generate a UNIQUE key constraint.



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

Verified, however i cannot fix this know, we need another internal refactoring before this can be done.

Comment by Roman S. Borschel [ 07/Jul/10 ]

Pushing back to beta4.

Comment by Roman S. Borschel [ 10/Aug/10 ]

I think this can be easily fixed now.

Comment by Benjamin Eberlei [ 10/Aug/10 ]

Fixed!





[DDC-741] Support SingleValuedAssociationPathExpression owning side Association in InExpression Created: 10/Aug/10  Updated: 10/Aug/10  Resolved: 10/Aug/10

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

Type: Improvement Priority: Major
Reporter: Guilherme Blanco Assignee: Guilherme Blanco
Resolution: Duplicate Votes: 0
Labels: None


 Description   

Title explains everything:

DQL: SELECT v FROM Videos v WHERE v.Venue IN (....)
SQL: SELECT .. FROM ... WHERE v.venue_id IN (...)


 Comments   
Comment by Guilherme Blanco [ 10/Aug/10 ]

http://www.doctrine-project.org/jira/browse/DDC-581





[DDC-626] Remove Association Classes Created: 06/Jun/10  Updated: 10/Aug/10  Resolved: 10/Aug/10

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

Type: Improvement Priority: Major
Reporter: Benjamin Eberlei Assignee: Roman S. Borschel
Resolution: Fixed Votes: 0
Labels: None

Issue Links:
Dependency
is required for DDC-562 @OneToOne is not generating a unique ... Resolved

 Description   

The AssociationMapping classes are not needed anymore now that all of the logic has moved to the persisters.

Additionally we get caching benefits doing this and its a dependency for DDC-562 (allowing to differ between ManyToOne and OneToOne)



 Comments   
Comment by Roman S. Borschel [ 07/Jul/10 ]

Pushing back to beta4.





[DDC-728] Inherited (JOINED) associations referred on DQL on owning side doesn't refer to correct table column Created: 30/Jul/10  Updated: 09/Aug/10  Resolved: 09/Aug/10

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

Type: Bug Priority: Major
Reporter: Guilherme Blanco Assignee: Guilherme Blanco
Resolution: Fixed Votes: 0
Labels: None


 Description   

Based on code instrospection, it seems that SQL generated is wrong when you attempt to do something like this:

SELECT m FROM CompanyManager m WHERE m.InheritedSingleValuedAssociation = ?1

It seems the column that refers to the association points to wrong table (apparently it points to CompanyManager table).
If everything works, we still need to have coverage to it (we have none).



 Comments   
Comment by Roman S. Borschel [ 07/Aug/10 ]

The first thing we need is tests to verify the issue.

Comment by Benjamin Eberlei [ 08/Aug/10 ]

I added a test to show that it works and no issue occours:

    /**
     * @group DDC-728
     */
    public function testQueryForInheritedSingleValuedAssociation()
    {
        $manager = new CompanyManager();
        $manager->setName('gblanco');
        $manager->setSalary(1234);
        $manager->setTitle('Awesome!');
        $manager->setDepartment('IT');

        $person = new CompanyPerson();
        $person->setName('spouse');

        $manager->setSpouse($person);

        $this->_em->persist($manager);
        $this->_em->persist($person);
        $this->_em->flush();
        $this->_em->clear();

        $dql = "SELECT m FROM Doctrine\Tests\Models\Company\CompanyManager m WHERE m.spouse = ?1";
        $dqlManager = $this->_em->createQuery($dql)->setParameter(1, $person->getId())->getSingleResult();

        $this->assertEquals($manager->getId(), $dqlManager->getId());
        $this->assertEquals($person->getId(), $dqlManager->getSpouse()->getId());
    }

Its in Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest.php, see commit:

http://github.com/doctrine/doctrine2/commit/dcebc241b4e36f20f364699105aff258f5840962

Comment by Guilherme Blanco [ 09/Aug/10 ]

I think I fixed it sometime... it was missing a condition that is now present.

Fixed. =)





[DDC-735] PersistentCollection#remove() and PersistentCollection#removeElement() behave differently Created: 07/Aug/10  Updated: 09/Aug/10  Resolved: 09/Aug/10

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

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

Attachments: File DDC735Test.php    

 Description   

It all started when I noticed that removing elements from an a collection using removeElement() didn't actually remove them from the database. While debugging that issue, I found that using remove() worked as expected, so I took a look at ArrayCollection#removeElement() and remove(). I remained thorougly confused for a good 5 minutes because the two methods are virtually identical, yet they were behaving differently. That's when I realized that loading a collection from the database gives you a PersistentCollection, not an ArrayCollection.

So here's the bug: PersistentCollection#remove() and PersistentCollection#removeElement() behave differently. remove() marks the collection as changed only if an element is actually removed, then schedules an OrphanRemoval if applicable. removeElement() unconditionally marks the collection as changed and forgets to check for orphanRemoval.

Since both methods are virtually identical, I suggest that they are refactored to use a common code path instead of duplicating their code. The same should be done with ArrayCollection.



 Comments   
Comment by s9e [ 07/Aug/10 ]

Testcase and proposed fix at http://github.com/s9e/doctrine2/commit/5a01b50bdbffbfd59c3af6cfc94ddb5793dac329

Comment by Benjamin Eberlei [ 08/Aug/10 ]

Slighty changed the patch because removeElement() on the wrapped collection has to be called.

Merged your testcase also, fixed in master.

Comment by s9e [ 08/Aug/10 ]

How about merging the code path differently then? You keep calling the right method on the wrapped collection but you move all the common code from PersistentCollection to its own method instead of duplicating it. Plus, it doesn't prevent you from implementing method-specific routines such as the ones mentionned in the TODOs.


class PersistentCollection
{
    public function remove($key)
    {
        return $this->removeFromCollection('remove', $key);
    }

    public function removeElement($element)
    {
        /*if ( ! $this->initialized) {
            $this->em->getUnitOfWork()->getCollectionPersister($this->association)
                ->deleteRows($this, $element);
        }*/

        return $this->removeFromCollection('removeElement', $element);
    }

    private function removeFromCollection($method, $arg)
    {
        $this->initialize();
        $removed = $this->coll->$method($arg);
        if ($removed) {
            $this->changed();
            if ($this->association !== null && $this->association->isOneToMany() &&
                    $this->association->orphanRemoval) {
                $this->em->getUnitOfWork()->scheduleOrphanRemoval($removed);
            }
        }

        return $removed;
    }
}
Comment by Benjamin Eberlei [ 09/Aug/10 ]

dynamic method calls are to slow and this gives no additional benefit.

i just realize that there might be another bug in the removeElement() just that i read the docblock changes yesterday. it returns true and not the element if the operation was successful. I have to reevaluate this...

Comment by s9e [ 09/Aug/10 ]

It's been a long time since I've last heard that dynamic method calls were slow. That may have been true in older versions of PHP (4?) but nowadays the difference is negligible; I've just run a quick informal test showing a ~20ms difference over one million calls on PHP 5.3.3 in CLI .

I think that code deduplication is a strong benefit. In fact, that's because code was duplicated instead of reused that this ticket exists. The next time any code is added to or removed from one of these methods, it will have to be mirrored to the other one or you will run into the same issue.

Wrt the return value, I had noticed earlier that ArrayCollection#removeElement's docblock mentionned returning a boolean, but the Collection interface declares returning the object and that's what the implementation does too, so I assumed its docblock simply needed to be updated. Shouldn't it use

{@inheritdoc}

just like PersistentCollection does? Interestingly, it's another case of deduplication.

Comment by Benjamin Eberlei [ 09/Aug/10 ]

fixed, again!

Comment by s9e [ 09/Aug/10 ]

I see that PersistentCollection#removeElement has been modified to accomodate the underlying collection's removeElement() potentionally returning a boolean. Is the Collection interface's definition going to be changed so that removeElement() returns a boolean? I think that would be confusing for the end user because we'd then have:

  • add() takes an element as argument, returns a boolean
  • remove() takes a key as argument, returns an element
  • removeElement() takes an element as argument, returns a boolean




[DDC-584] Document DBAL ArrayType and ObjectType in "Doctrine Mapping Types" instructions Created: 12/May/10  Updated: 08/Aug/10  Resolved: 08/Aug/10

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

Type: Improvement Priority: Minor
Reporter: Marc Hodgins Assignee: Jonathan H. Wage
Resolution: Fixed Votes: 0
Labels: None


 Description   

http://www.doctrine-project.org/documentation/manual/2_0/en/basic-mapping#doctrine-mapping-types

Does not mention Doctrine\DBAL\Types\ArrayType or Doctrine\DBAL\Types\ObjectType

Should these be included as documented mapping types?



 Comments   
Comment by Jonathan H. Wage [ 08/Aug/10 ]

It seems to show it now

http://www.doctrine-project.org/projects/orm/2.0/docs/reference/basic-mapping/en#doctrine-mapping-types





[DDC-663] Update PEAR install command Created: 01/Jul/10  Updated: 08/Aug/10  Resolved: 08/Aug/10

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

Type: Task Priority: Minor
Reporter: Michael Stelly Assignee: Jonathan H. Wage
Resolution: Fixed Votes: 0
Labels: None
Environment:

Mac OS X 10.6.



 Description   

Documentation gives incorrect command for downloading ORM from PEAR which causes the installation to fail with the message:

Failed to download doctrine/DoctrineORM, version "2.0.0", latest release is version 2.0.0BETA2, stability "beta", use "channel://pear.doctrine-project.org/DoctrineORM-2.0.0BETA2" to install
install failed

Currently:
sudo pear install pear.doctrine-project.org/DoctrineORM-2.0.0

Change to:
sudo pear install pear.doctrine-project.org/DoctrineORM-2.0.0BETA2



 Comments   
Comment by Jonathan H. Wage [ 08/Aug/10 ]

http://github.com/doctrine/orm-documentation/commit/70d12fc57aa3ea3b94b1b8ff8efdf8b7e0543988





[DDC-651] Bad class (without used namespace) is provided in extends section of entity class declaration in generator. Created: 23/Jun/10  Updated: 08/Aug/10  Resolved: 08/Aug/10

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

Type: Bug Priority: Major
Reporter: stepan svoboda Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

n\a



 Description   

Bad class (without used namespace) is provided in extends section of entity class declaration in generator.

For example with option --extend="Nette\Object" the class looks like this:

// ...

namespace Entities;

use Nette;

class Foo extends Object <= this is bad. Here should by Nette\Object

// ...



 Comments   
Comment by Benjamin Eberlei [ 08/Aug/10 ]

Fixed





[DDC-703] Explicit change tracking not inherited by inheriting classes Created: 20/Jul/10  Updated: 08/Aug/10  Resolved: 08/Aug/10

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

Type: Bug Priority: Major
Reporter: Dennis Verspuij Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

I have a class B that inherits from A using single table inheritance strategy with discriminator column.
On class A I have defined @ChangeTrackingPolicy ("DEFERRED_EXPLICIT"), which should be inherited by B, but it is not currenlty.

This means that when I have a managed instance $b of B $em->getClassMetadata(get_class($b))->isChangeTrackingDeferredExplicit()
does not return TRUE and calling $em->persist($b) and $em->flush() does not save any changes to $b.

If I set @ChangeTrackingPolicy ("DEFERRED_EXPLICIT") on class B it does work. So either way I think B should inherit the change tracking policy of A, or it should have IMPLICT as default like A but not none.



 Comments   
Comment by Benjamin Eberlei [ 08/Aug/10 ]

fixed





[DDC-542] ManyToMany with Properties sharing Join columns with PRimary Key Created: 26/Apr/10  Updated: 08/Aug/10  Resolved: 08/Aug/10

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

Type: Bug Priority: Minor
Reporter: Benjamin Eberlei Assignee: Roman S. Borschel
Resolution: Fixed Votes: 2
Labels: None

Attachments: File Recipes.php    
Issue Links:
Reference
is referenced by DDC-436 Foreign keys on primary keys and vice... Resolved

 Description   
Spagetthi with Tomatoes

Notice: Undefined index: recipe_id in /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/UnitOfWork.php on line 1820

Call Stack:
    0.0005     354964   1. {main}() /home/benny/code/php/wsnetbeans/DoctrineTests/ManyToMany/Recipes.php:0
    0.2063    4308460   2. Doctrine\ORM\PersistentCollection->getIterator() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/PersistentCollection.php:0
    0.2063    4308460   3. Doctrine\ORM\PersistentCollection->_initialize() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/PersistentCollection.php:512
    0.2064    4308460   4. Doctrine\ORM\Mapping\OneToManyMapping->load() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/PersistentCollection.php:210
    0.2064    4308820   5. Doctrine\ORM\Persisters\StandardEntityPersister->loadOneToManyCollection() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/Mapping/OneToManyMapping.php:137
    0.2371    4312216   6. Doctrine\ORM\Persisters\StandardEntityPersister->_createEntity() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/Persisters/StandardEntityPersister.php:559
    0.2372    4312720   7. Doctrine\ORM\UnitOfWork->createEntity() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/Persisters/StandardEntityPersister.php:611


Notice: Undefined index: product_id in /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/UnitOfWork.php on line 1820

Call Stack:
    0.0005     354964   1. {main}() /home/benny/code/php/wsnetbeans/DoctrineTests/ManyToMany/Recipes.php:0
    0.2063    4308460   2. Doctrine\ORM\PersistentCollection->getIterator() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/PersistentCollection.php:0
    0.2063    4308460   3. Doctrine\ORM\PersistentCollection->_initialize() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/PersistentCollection.php:512
    0.2064    4308460   4. Doctrine\ORM\Mapping\OneToManyMapping->load() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/PersistentCollection.php:210
    0.2064    4308820   5. Doctrine\ORM\Persisters\StandardEntityPersister->loadOneToManyCollection() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/Mapping/OneToManyMapping.php:137
    0.2371    4312216   6. Doctrine\ORM\Persisters\StandardEntityPersister->_createEntity() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/Persisters/StandardEntityPersister.php:559
    0.2372    4312720   7. Doctrine\ORM\UnitOfWork->createEntity() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/Persisters/StandardEntityPersister.php:611


Notice: Undefined index: recipe_id in /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/UnitOfWork.php on line 1820

Call Stack:
    0.0005     354964   1. {main}() /home/benny/code/php/wsnetbeans/DoctrineTests/ManyToMany/Recipes.php:0
    0.2063    4308460   2. Doctrine\ORM\PersistentCollection->getIterator() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/PersistentCollection.php:0
    0.2063    4308460   3. Doctrine\ORM\PersistentCollection->_initialize() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/PersistentCollection.php:512
    0.2064    4308460   4. Doctrine\ORM\Mapping\OneToManyMapping->load() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/PersistentCollection.php:210
    0.2064    4308820   5. Doctrine\ORM\Persisters\StandardEntityPersister->loadOneToManyCollection() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/Mapping/OneToManyMapping.php:137
    0.2382    4314316   6. Doctrine\ORM\Persisters\StandardEntityPersister->_createEntity() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/Persisters/StandardEntityPersister.php:559
    0.2383    4314820   7. Doctrine\ORM\UnitOfWork->createEntity() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/Persisters/StandardEntityPersister.php:611


Notice: Undefined index: product_id in /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/UnitOfWork.php on line 1820

Call Stack:
    0.0005     354964   1. {main}() /home/benny/code/php/wsnetbeans/DoctrineTests/ManyToMany/Recipes.php:0
    0.2063    4308460   2. Doctrine\ORM\PersistentCollection->getIterator() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/PersistentCollection.php:0
    0.2063    4308460   3. Doctrine\ORM\PersistentCollection->_initialize() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/PersistentCollection.php:512
    0.2064    4308460   4. Doctrine\ORM\Mapping\OneToManyMapping->load() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/PersistentCollection.php:210
    0.2064    4308820   5. Doctrine\ORM\Persisters\StandardEntityPersister->loadOneToManyCollection() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/Mapping/OneToManyMapping.php:137
    0.2382    4314316   6. Doctrine\ORM\Persisters\StandardEntityPersister->_createEntity() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/Persisters/StandardEntityPersister.php:559
    0.2383    4314820   7. Doctrine\ORM\UnitOfWork->createEntity() /home/benny/code/php/wsnetbeans/doctrine2/lib/Doctrine/ORM/Persisters/StandardEntityPersister.php:611


Notice: Trying to get property of non-object in /home/benny/code/php/wsnetbeans/DoctrineTests/ManyToMany/Recipes.php on line 176

Call Stack:
    0.0005     354964   1. {main}() /home/benny/code/php/wsnetbeans/DoctrineTests/ManyToMany/Recipes.php:0

   100

Notice: Trying to get property of non-object in /home/benny/code/php/wsnetbeans/DoctrineTests/ManyToMany/Recipes.php on line 176

Call Stack:
    0.0005     354964   1. {main}() /home/benny/code/php/wsnetbeans/DoctrineTests/ManyToMany/Recipes.php:0

   5


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

With DQL the second ingredient in the loop has an product of NULL:

Spagetthi with Tomatoes
  Tomatoes 100

Notice: Trying to get property of non-object in /home/benny/code/php/wsnetbeans/DoctrineTests/ManyToMany/Recipes.php on line 168

Call Stack:
    0.0004     356008   1. {main}() /home/benny/code/php/wsnetbeans/DoctrineTests/ManyToMany/Recipes.php:0

   5
Comment by Roman S. Borschel [ 26/Apr/10 ]

Scheduled for beta2 for now. May be pushed back later if we don't find the time.

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

Pushing back.

Comment by Roman S. Borschel [ 08/Aug/10 ]

This works now after the latest patches.





[DDC-133] Complete implementation for schema support. Created: 09/Nov/09  Updated: 08/Aug/10  Resolved: 08/Aug/10

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

Type: Bug Priority: Major
Reporter: Roman S. Borschel Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 2
Labels: None


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

This mainly affects SqlWalker but probably many other parts also.

Comment by Roman S. Borschel [ 16/Feb/10 ]

This shoudl wait for ddc-335 to finish.

Comment by Roman S. Borschel [ 27/Feb/10 ]

How (if) his should be supported is still open to discussion. Maybe just @Table(name="schema.table") can work fine mostly and we dont need to bloat our implementation.

Comment by Roman S. Borschel [ 07/Mar/10 ]

I tested this a bit with PostgreSQL and @Table(name="schema.table") and it seems to work fine. Even DDL generation/export works fine as long as the schema is created beforehand, just like databases. I think this is acceptable but still need to test further.

Comment by Andy Aja deh [ 12/May/10 ]

Hello, I use postgresql, with PHP mapping driver like this:

<?php

use Doctrine\ORM\Mapping\ClassMetadataInfo;

$metadata->setInheritanceType(ClassMetadataInfo::INHERITANCE_TYPE_NONE);
$metadata->setPrimaryTable(array(
    'name' => 'sales.mdp',
    'schema' => 'sales',
));

$metadata->setChangeTrackingPolicy(ClassMetadataInfo::CHANGETRACKING_DEFERRED_IMPLICIT);
$metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE);
$metadata->setSequenceGeneratorDefinition(array(
        'sequenceName'   => 'mdp_id_seq',
        'allocationSize' => 10,
        'initialValue'   => 1,
    ));
    
$metadata->mapField(array(
   'id'         => true,
   'fieldName'  => 'id',
   'columnName' => 'id',
   'type'       => 'integer',
  ));
$metadata->mapField(array(
   'fieldName'  => 'rrn',
   'columnName' => 'rrn',
   'type'       => 'string',
   'length'     => 50,
   'unique'     => true,
  ));

When I create database schema from CLI, it raises exception:

[Doctrine\DBAL\Schema\SchemaException]
Invalid index-name sales.mdp_rrn_uniq given, has to be [a-zA-Z0-9_]
Comment by Andy Aja deh [ 12/May/10 ]

I try to remove unique => true, then it works. The mdp table is generated in sales schema.
Now when I I try to drop the database from CLI, I get an exception:

[PDOException]
SQLSTAT[42P01] Undefined table: 7 Error: table "mdp" does not exist.

it seems like dropping improper sequence or table name.

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

Ben, do you have an opinion on this? I think we can try to address this on the DBAL level by inspecting the table names whether they are of the form "foo.bar". The alternative would require full extra schema support on the ORM + DBAL level, so I'd rather try to do this the "hacky" way if possible (i.e. no explicit schema support, just "schema.table" as table name implicitly works) since most of the stuff works already with this.

The DBAL does not need to support creating schemas or stuff like that. Just ensuring that "schema.table" as a table name does not mess up DDL statements like constraint or index names in this example.

Comment by Benjamin Eberlei [ 06/Jun/10 ]

Fixed the auto-naming of indexes and constraints on the latest DBAL trunk, so this should continue to work @Andy can you verify?

Comment by Benjamin Eberlei [ 06/Jun/10 ]

Move to Beta3 to gather more feedback on the implicit definition

Comment by Andy Aja deh [ 08/Jun/10 ]

Thanks Benjamin, Now it works. When I run orm:schema-tool:create, it creates the tables & indexes & constraints in the proper schema.
But, I still have problems when update / dropping the tables.

when I run orm:schema-tool:drop, I get an exception:

[PDOException]

  SQLSTATE[42P01]: Undefined table: 7 ERROR:  relation "mdp_id_seq" does not exist
  LINE 1: SELECT min_value, increment_by FROM mdp_id_seq

                                              ^

I use this in my map:

<?php

use Doctrine\ORM\Mapping\ClassMetadataInfo;

$metadata->setInheritanceType(ClassMetadataInfo::INHERITANCE_TYPE_NONE);
$metadata->setPrimaryTable(array(
    'name' => 'sales.mdp',
    'schema' => 'sales',
));

$metadata->setChangeTrackingPolicy(ClassMetadataInfo::CHANGETRACKING_DEFERRED_IMPLICIT);
$metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE);
$metadata->setSequenceGeneratorDefinition(array(
        'sequenceName'   => 'sales.mdp_id_seq',
        'allocationSize' => 10,
        'initialValue'   => 1,
    ));

I want my sequence name to be also in sales schema. But when I drop it, I get that exception.

Comment by Scott Morken [ 16/Jun/10 ]

Since I was trying to break the schemaname.tablename by overcomplicating it and not doing a very good search here first (DDC-639, sorry Roman!), I happened to notice that the quoteIdentifier method in AbstractPlatform doesn't appear to be correctly quoting the schema and table name if quotes are needed. I'm not using any quoting but just glancing at the code, shouldn't $str be exploded on '.' in case of a schema.tablename string passed in? The current method looks like it will return (quote)schemaname.tablename(quote) instead of (quote)schemaname(quote).(quote)tablename(quote).
Maybe something along the lines of:

$expStr = explode('.', $str);
return $c . join("$c.$c", $expStr) . $c;

Awesome piece of work! It rocks!!

Comment by Jonathan H. Wage [ 17/Jun/10 ]

The only problem I can think of is the identifier quoting like Scott mentions above. I had to "hack" this same thing in Doctrine 1. I don't like it

Comment by Roman S. Borschel [ 17/Jun/10 ]

I think the limitation of not supporting identifier quoting in cases like this is not problematic so this hack is not needed. Identifier quoting is not supported everywhere anyway (i.e. not for join columns and discriminator columns).

Comment by Roman S. Borschel [ 07/Jul/10 ]

Pushing back to beta4 to wait for more potential feedback. If anyone has issues with the current support for schemas via the table name, please speak up.

Comment by Roman S. Borschel [ 08/Aug/10 ]

Closing this case for now as no further negative feedback was submitted. If new major issues arise that can not be addressed easily this issue needs to be reconsidered in a post 2.0 release.





[DDC-385] Change behaviour if fully qualified classname is passed in as string Created: 01/Mar/10  Updated: 08/Aug/10  Resolved: 08/Aug/10

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

Type: Improvement Priority: Minor
Reporter: Christian Heinrich Assignee: Roman S. Borschel
Resolution: Fixed Votes: 0
Labels: None


 Description   

If one calls $em->getRepository('\Entity') (leading \ !) then Doctrine's behaviour is quite undefined, as it would result e.g. in a "mapping file '.entity.dcm.yml' not found" error. (leading dot!)

PHP, however, seems to allow the leading \, but Doctrine does not. In fact, the leading \ is not necessary as classnames in strings are always fully qualified.

So Doctrine should either:

1.) Throw an exception stating that using a leading backslash is prohibited
2.) Simply strip it.



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

I vote for 1. Stripping the char just leads to major overhead given that getMetadataFor is one of the most called functions in Doctrine 2.

Comment by Roman S. Borschel [ 08/Aug/10 ]

Fixed.





[DDC-675] EntityManager->find() returns detached (or otherwise unmanaged) object. Created: 09/Jul/10  Updated: 08/Aug/10  Resolved: 08/Aug/10

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

Type: Bug Priority: Major
Reporter: Michael Nielsen Assignee: Roman S. Borschel
Resolution: Fixed Votes: 1
Labels: None


 Description   

The find method seems to be broken. Returned objects are not managed according to the EntityManager. Fetching the same object via findAll() works.

$e = $em->find('\net\jay\products\doctrine\ProductEntityType', 1);
print "Class: " . get_class($e) . "<br>";
print "Contained: " . ($em->contains($e) === true ? 'Yes' : 'No');

This gives me:

Class: net\jay\products\doctrine\ProductEntityType
Contained: No



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

can you try to build a reproducible test-case? This would be a serious issue, however we cannot reproduce it this way.

Comment by Michael Nielsen [ 09/Jul/10 ]

Ah it turns out to be the leading namespace \ in the find parameter that killed me. Without it, the object turns out managed.

Slightly troublesome that the object is returned in both cases perhaps.

I tested with this added to tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php, in case the behaviour needs to be changed:

public function testFind()
    {
    	// Create
        $user = new CmsUser;
        $user->name = 'Roman';
        $user->username = 'romanb';
        $user->status = 'developer';
        $this->_em->persist($user);
       
        $this->_em->flush();
        
        // Find1
        $this->_em->clear();
        $user2 = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $user->id);
        $this->assertTrue($this->_em->contains($user2));

        // Find2
        $this->_em->clear();
        $user3 = $this->_em->find('\Doctrine\Tests\Models\CMS\CmsUser', $user->id);
        $this->assertTrue($this->_em->contains($user3));
    }

Find1 passes, while Find2 fails. The user is found in both cases though.

Have a nice weekend.

Comment by Roman S. Borschel [ 09/Jul/10 ]

That is because the objects are stored in the identity map based on their class name. We could strip off leading backslashes but once we start doing that we will always miss some places. Class names in strings are always fully-qualified, thus there is never a need to use a leading backslash in a string that contains a class name. The leading backslash is only useful in actual code, not in strings.

Comment by Michael Nielsen [ 09/Jul/10 ]

Maybe just mentioning it in a "common use errors" section of the manual could be a good solution to avoid too much despair when the \ is added by mistake. If it's not already mentioned in there somewhere.

Comment by Jan Obrátil [ 20/Jul/10 ]

The solution is just add a warning when leading \ is found.

The same bug happends to me. It took lots of hours to find that it was by \.

Thanks
obrys

Comment by Roman S. Borschel [ 08/Aug/10 ]

Fixed.





[DDC-650] $data using wrong index in UnitOfWork::createEntity() in one to one assoc Created: 22/Jun/10  Updated: 08/Aug/10  Resolved: 08/Aug/10

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

Type: Bug Priority: Major
Reporter: Scott Morken Assignee: Roman S. Borschel
Resolution: Fixed Votes: 0
Labels: None


 Description   

It looks like $data is using the wrong index ($srcColumn) in UnitOfWork::createEntity() line 1834 (1854 in github repo, it seems my IDE can't count ) to get the $joinColumnValue. Since $data contains the camelized field names and $srcColumn is the actual field name, should it be:

+ $joinColumnValue = $data[$class->fieldNames[$srcColumn]];
- $joinColumnValue = $data[$srcColumn];

?



 Comments   
Comment by Roman S. Borschel [ 23/Jun/10 ]

Not really, join columns have no field name but you may have encountered one of DDC-522 DDC-383

Join columns should really never be mapped to fields, they have no place whatsoever in the objects.

Comment by Scott Morken [ 23/Jun/10 ]

It looks like it is DDC-383 for me. I think this occurred in my case because the tables use compound keys and I was using partials and part of the compound key was also the foreign key for a joined table. Since the partial required all the compound keys be added to the field list, the foreign key was also added and probably caused this.

Thanks for the explanation.

Comment by Roman S. Borschel [ 08/Aug/10 ]

Should be fixed now.





[DDC-419] Problem when I make a INNER JOIN between 2 classes Created: 12/Mar/10  Updated: 08/Aug/10  Resolved: 08/Aug/10

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

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

Ubuntu 9.10
PHP 5.3.1-0.dotdeb.1 with Suhosin-Patch (cli) (built: Dec 5 2009 20:08:29)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2009 Zend Technologies
with Xdebug v2.0.5, Copyright (c) 2002-2008, by Derick Rethans
with Suhosin v0.9.29, Copyright (c) 2007, by SektionEins GmbH
PHPUnit 3.4.6 by Sebastian Bergmann


Attachments: File DDC419Test.php     File TestCase.tar.bz2    
Issue Links:
Dependency
depends on DDC-522 Join columns can not be named the sam... Closed

 Description   

I hae some problems when I make a inner join between 2 classes, one of these classes makes join to others 2 classes in the same time and when I try to make a inner to this class, it's not coming like a object, but object Id...

I don't know why its happening..

I make a test case..there're all the classes and yml that show my problem..it's on ItemPregaoTest.php.. just need to run phpunit in this file..



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

This is what returns for me:

object(stdClass)[82]
  public '__CLASS__' => string 'ItemPregao' (length=10)
  public 'id' => int 1
  public 'item' => string '1' (length=1)

The expected result I guess. What happens for you?

Comment by Henrique Girardi dos Santos [ 14/Mar/10 ]

Ok...this is what happen for me...
but I think the expected result would be

object(stdClass)[82]
  public '__CLASS__' => string 'ItemPregao' (length=10)
  public 'id' => int 1
  public 'item' => string 'Item' (length=4)

because 'public item' makes refereces to Item class, so I think it should give me a Item class, not its Id...

Comment by Henrique Girardi dos Santos [ 16/Mar/10 ]

When I try to make a inner join between Item and ItemPregao, happens what I've said before, but if I make a inner join between Item and its refereces tables, it's working fine

$qb = $this->em->createQueryBuilder();
        $qb->select('i, cc, ca, cl')
           ->from('Item', 'i')
           ->innerJoin('i.classificacaoCatalogo', 'cc')
           ->innerJoin('cc.catalogo', 'ca')
           ->innerJoin('cc.classificacao', 'cl')
        ;

object(stdClass)[141]
  public '__CLASS__' => string 'Item' (length=4)
  public 'id' => int 1
  public 'descricao' => string 'ITEM 1' (length=6)
  public 'classificacaoCatalogo' => 
    object(stdClass)[99]
      public '__CLASS__' => string 'ClassificacaoCatalogo' (length=21)
      public 'id' => int 1
      public 'classificacao' => string 'Classificacao' (length=13)
      public 'catalogo' => string 'Catalogo' (length=8)

It brings a class on 'classificacaoCatalogo' and inside classificacaoCatalogo you can see that 'classificacao' and 'catalogo' are objects too..so it worked! But If I make this:

$qb = $this->em->createQueryBuilder();
        $qb->select('ip, i')
           ->from('ItemPregao', 'ip')
           ->innerJoin('ip.item', 'i');

do not work like before..

object(stdClass)[152]
  public '__CLASS__' => string 'ItemPregao' (length=10)
  public 'id' => int 1
  public 'item' => int 1

'item' should be a object, not a integer..

Comment by Benjamin Eberlei [ 16/Mar/10 ]

Ah now I see it. Yes, this seems to be a problem.

Comment by Benjamin Eberlei [ 18/Mar/10 ]

I have taken some time now trying to re-produce it, there is definately a bug i have identified, however i havent found the reason yet.

Comment by Henrique Girardi dos Santos [ 18/Mar/10 ]

ok man!
I've try to find the reason too but I havent found yet too...
I dont know if there's something about the item are conected to a table that there're 2 table...
i dont know :S

Comment by Benjamin Eberlei [ 20/Mar/10 ]

I found the issue. A quick fix is to rename the join column to "item_id" instead of "item". This is causing the bug, we will look how to fix it.

@Roman:

This is particularly nasty, in UnitOfWork::createEntity the join column is set to the field name in $data, which makes the following code write the primitive FK value to the entity:

            if ($this->_useCExtension) {
                doctrine_populate_data($entity, $data);
            } else {
                foreach ($data as $field => $value) {
                    if (isset($class->reflFields[$field])) {
                        $class->reflFields[$field]->setValue($entity, $value);
                    }
                }
            }

This then leads in the ObjectHydrator to:

                    // PATH B: Single-valued association
                    $reflFieldValue = $reflField->getValue($parentObject);
                    if ( ! $reflFieldValue || isset($this->_hints[Query::HINT_REFRESH])) {

not evaluating to null, but to the primitive value. the If condition does not match here and the relation is never set.

A simple solution would be to replace !$reflFieldValue with !is_object().

Comment by Benjamin Eberlei [ 20/Mar/10 ]

Attached a reproduce test-case.

Comment by Roman S. Borschel [ 20/Mar/10 ]

I see. As their is an easy workaround, this is not a blocker, however.

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

DDC-522 needs to be fixed, then this issue is solved, too (its the same after all, the other issue is just more specific).

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

Scheduled for beta2

Comment by Roman S. Borschel [ 08/Aug/10 ]

Should be fixed now in master.





[DDC-383] Setting Column name doesn't work predictably in associations Created: 27/Feb/10  Updated: 08/Aug/10  Resolved: 09/Jul/10

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

Type: Improvement Priority: Minor
Reporter: akeem philbert Assignee: Roman S. Borschel
Resolution: Invalid Votes: 0
Labels: None

Attachments: File YamlExportDriver.php    

 Description   

Setting a column name that is different from the property name yields errors in associations (e.g. in a one to one association I get "Undefined index: shipping_id in /var/www/wetawa/library/Doctrine/ORM/UnitOfWork.php on line 1782 Call ")

...
    /**
     * @Column(type="bigint", name="shipping_id")
     *
     * @var integer
     */
    protected $shippingId=0;
    /**
     * @OneToOne(targetEntity="Shipping")
     * @JoinColumn(name="shipping_id", referencedColumnName="id")
     * 
     * @var Shipping
     */
    protected $shipping;

The only way I've been able to get associations to work is by using the default naming so $shipping_id instead of $shippingId



 Comments   
Comment by Roman S. Borschel [ 27/Feb/10 ]

Foreign keys (or discriminator columns) are not intended to be mapped to properties. What do you need $shippingId for?

Comment by akeem philbert [ 27/Feb/10 ]

I see your point though there might be some use cases for wanting to access $shippingId (maybe storing in some kind of log that doesn't need the full set of shipping info) and not incur the expense of getting the shipping object.

Comment by Benjamin Eberlei [ 28/Feb/10 ]

@akeem: This is possible without mapping the shipping-id, although its not recommended for the reason that you are depending on internal Doctrien 2 APIs. This should only be done as a very last resort (performance reasons).

You can retrieve the identifier of the shipping proxy object by calling:

$shippingId = $em->getUnitOfWork()->getEntityIdentifier($entity->shipping);

As another solution you could, if required for a specific use-case, retrieve only the shipping ids and initialize shipping as partial objects:

SELECT o, PARTIAL s.{id} FROM Order o JOIN o.shipping s
Comment by Roman S. Borschel [ 03/Mar/10 ]

Let my try to clarify, because I saw you tweeting that you dislike this "limitation".

A foreign key has no meaning in an object model. Foreign keys are how relational databases establish associations/relations between rows. In object-oriented programming objects establish associations through object references. In a sense, when you map a foreign key to an object property you leak detail of your relational schema into your object model. Detail that is only ever relevant to a relational database. If you would ever persist this object in another type of persistent storage, the foreign key has no meaning. This level of abstraction that D2 provides is rare among PHP ORMs. Most require you to have foreign keys as properties which is a major flaw of the abstraction.

It should be possible to map foreign keys to properties but this has very low priority because even if you want to do it, it can only be a workaround and there are other ways that Benjamin pointed out.

That said, Doctrine does of course not "take away" access to the foreign keys. With array or scalar hydration or even plain SQL, of course, you can still get the foreign keys in a result but foreign keys have no place in an object model.

Just trying to communicate this better.

Comment by akeem philbert [ 03/Mar/10 ]

I appreciate the time spent on explaining this an do appreciate what you guys have said. I guess one of the things I really liked about the doctrine 2.0 direction was the use of plain php objects (so tempted to so pojos). While this is true there seem to be a number of caveats that get in the way of using those objects exactly how I want to (or in a way that isn't doctrine specific), so these caveats seem to make it a bit more intrusive than I initially thought (though less intrusive than having to extend classes). I'll chalk this one up to keep an eye on and I commend you guys on the work you've done so far.

Comment by Roman S. Borschel [ 03/Mar/10 ]

Whenever you have questions on how to do something properly without dedicated foreign key properties just drop a mail to the user mailing list. For most cases there is a good solution and if not, we will create one.

Comment by Benjamin Eberlei [ 09/Jul/10 ]

This is not an issue. Closed

Comment by Aigars Gedroics [ 27/Jul/10 ]

Still there is another issue related to this one.

When I create yaml files from existing database using the command line command "orm:convert-mapping --from-database yaml" the relational field "target_id" is created in both places - as a field and in the relation definition (under oneToOne in my case). Here I get the same problem as described above and the target object cannot be retrieved.

Sample generated yaml for city—country relation:

City:
  type: entity
  table: city
  fields:
    id:
      id: true
      type: integer
      unsigned: false
      nullable: false
      generator:
        strategy: IDENTITY
    countryId:
      type: string(2)
      fixed: true
      nullable: false
      column: country_id
    name:
      type: string(255)
      fixed: false
      nullable: true
  oneToOne:
    country:
      targetEntity: Country
      cascade: {  }
      mappedBy: null
      joinColumns:
        country_id:
          referencedColumnName: id
      orphanRemoval: false
  lifecycleCallbacks: {  }

This yaml causes problems when city is loaded.

Is it a bug or is it just me?

Comment by Aigars Gedroics [ 27/Jul/10 ]

The file attached is modified YAML export driver which workarounds the problem with the problem described in the previous comment.

Also it can append namespace to classes in the YAML files generated from the database schema.

Hope it helps someone.

Comment by Roman S. Borschel [ 08/Aug/10 ]

This should be fixed now.





[DDC-700] Proxy class is created for MappedSuperclass class Created: 20/Jul/10  Updated: 08/Aug/10  Resolved: 08/Aug/10

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

Type: Bug Priority: Minor
Reporter: Aigars Gedroics Assignee: Roman S. Borschel
Resolution: Fixed Votes: 0
Labels: None
Environment:

Windows, PHP 5.3.2


Attachments: Text File vcs-diff2497454792683211266.patch    

 Description   

When having abstract class as Mapped Superclass the proxy class is created without the "abstract" keyword which raises fatal PHP error "Class %proxyClassName% contains 1 abstract method and must therefore be declared abstract or implement the remaining methods" when read.

I think there is no need to generate the proxy classes for classes marked as @MappedSuperclass at all.



 Comments   
Comment by Aigars Gedroics [ 20/Jul/10 ]

Patch which adds the "abstract" keyword for problematic proxies

Comment by Benjamin Eberlei [ 08/Aug/10 ]

Fixed, skip generation of proxies for mapped superclasses.





[DDC-654] Unused lines of code in Doctrine\ORM\Query\AST\Functions Created: 24/Jun/10  Updated: 08/Aug/10  Resolved: 08/Aug/10

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

Type: Improvement Priority: Major
Reporter: Antoine Hedgecock Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

The majority of the classes contains a line that does notthing

$lexer = $parser->getLexer();


 Comments   
Comment by Benjamin Eberlei [ 08/Aug/10 ]

Fixed





[DDC-709] Doctrine-cli should check @OrderBy() taget existency Created: 21/Jul/10  Updated: 08/Aug/10  Resolved: 08/Aug/10

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

Type: Bug Priority: Major
Reporter: Jan Obrátil Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

Doctrine-cli orm:validate-schema should check schema for common typo mistakes as much as possible. Unknown target attribute passes ok. It's not expected behaviour.



 Comments   
Comment by Benjamin Eberlei [ 08/Aug/10 ]

Fixed.





[DDC-645] XML schema missing change-tracking-policy Created: 18/Jun/10  Updated: 08/Aug/10  Resolved: 08/Aug/10

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

Type: Bug Priority: Major
Reporter: Frantisek Troster Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

Hi,

XML schema is missing change-tracking-policy element:

<entity name="Doctrine\Tests\Models\ECommerce\ECommerceCart" table="ecommerce_carts">
        <change-tracking-policy>DEFERRED_IMPLICIT</change-tracking-policy>
        <field name="payment" type="string" column="payment" length="50" precision="0" scale="0"/>

Thank you



 Comments   
Comment by Benjamin Eberlei [ 08/Aug/10 ]

We changed how the XML Driver allows to define the change-tracking-policy for better validation. The working case is now:

    <entity change-tracking-policy="DEFERRED_IMPLICT" />

Its included in the XSD Schema now.





Generated at Tue Oct 21 20:10:12 UTC 2014 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.