[DC-952] Non-Equal Nest Relations Not Working - from "Children" side Created: 03/Jan/11  Updated: 24/Mar/11

Status: Open
Project: Doctrine 1
Component/s: Record, Relations
Affects Version/s: 1.2.3
Fix Version/s: None

Type: Bug Priority: Blocker
Reporter: Paweł Barański Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 4
Labels: None
Environment:

Ubuntu 10.04 + PHP 5.3.3 + Symfony 1.4.8


Attachments: File DC952TestCase.php    
Sub-Tasks:
Key
Summary
Type
Status
Assignee
DC-958 updating Models with Intra-Table Rela... Sub-task Open Jonathan H. Wage  

 Description   

I've copy & pasted example from http://www.doctrine-project.org/projects/orm/1.2/docs/manual/defining-models/1_0#relationships:join-table-associations:self-referencing-nest-relations:non-equal-nest-relations .
I've created User backend module using doctrine:generate-admin backend User task. On how to reproduce the error:

1. Add 3 User objects (A,B,C)
2. Open generated edit form for User A.
3. Set User B as Children from Children list and Save
4. Set User B and C as Chidren from Children list and Save

As a result you will see only C set as Children, and strange situation in database :

UserReference Table:

parent_id | child_id
pk_B | pk_B (!!!)
pk_A | pk_C



 Comments   
Comment by Paweł Barański [ 06/Jan/11 ]

Same ticket on symfony trac because I'm not sure whose fault is it

http://trac.symfony-project.org/ticket/9398

Also some new error path there

Comment by Daniel Reiche [ 24/Mar/11 ]

Test Case of Non-Equal Self-Referencing Relations, based on #DC-329.

Failure occures in line 75 of the test case file. This should not happen!
Only the parent object is modified in line 73 and saving should not interfere with the relations.





[DC-860]  0 down vote favorite In some circumstances Doctrine_Core::getTable('%Name%') returns Doctrine_Table instance instead of %Name%Table one. Created: 06/Sep/10  Updated: 06/Sep/10

Status: Open
Project: Doctrine 1
Component/s: Relations
Affects Version/s: 1.2.3
Fix Version/s: None

Type: Bug Priority: Blocker
Reporter: Hong Kil Dong Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None
Environment:

WinXP, Apache, PHP 5.2.14



 Description   

In some circumstances Doctrine_Core::getTable('%Name%') returns Doctrine_Table instance instead of %Name%Table one.
So custom %Name%Table's methods become unavailable.

In order to give a demonstration of this improper behavior : here is a schema of small issue tracking system

User:
actAs: [Timestampable]
tableName: issue_user
columns:
user_id:

{ type: integer, primary: true, autoincrement: true }

user_name:

{ type: string(255) }

user_role:

{ type: enum, values: [worker, dispatcher, manager] }

managed_by:

{ type: integer }

password:

{ type: string(32) }

salt:

{ type: string(32) }

relations:
Manager:
foreignAlias: Workers
class: User
local: managed_by
foreign: user_id
type: one
foreignType: many

Issue:
actAs: [Timestampable]
columns:
issue_id:

{ type: integer, primary: true, autoincrement: true }

from_ceh:

{ type: string(255) }

from_name:

{ type: string(255) }

from_phone:

{ type: string(255) }

from_location:

{ type: string(255) }

comp_name:

{ type: string(255) }

comp_serial:

{ type: string(255) }

comp_os:

{ type: enum, values: [Win95, Win98, WinNT, WinME, Win2000, WinXP, Vista, Win7] }

issue_title:

{ type: string(255) }

comment:

{ type: string(255) }

owner_id:

{ type: integer }

is_executed:

{ type: bool }

relations:
Owner:
onDelete: CASCADE
foreignAlias: Issues
class: User
local: owner_id
foreign: user_id
type: one
foreignType: many

When I just call Doctrine_Core::getTable('User') it returns UserTable instance, but if I call it after such a query:

Doctrine_Query::create()
->select('u.user_id, ws.user_id, i.*')
->from('User u, u.Workers ws, ws.Issues i')
->where('u.user_id=', $manager_id)
->fetchArray();

calling Doctrine_Core::getTable('User') returns Doctrine_Table instance






[DC-313] Ordering m2m relationship with column from related table (with orderBy option) Created: 02/Dec/09  Updated: 18/Feb/11

Status: Open
Project: Doctrine 1
Component/s: Record, Relations
Affects Version/s: 1.2.0
Fix Version/s: None

Type: Bug Priority: Blocker
Reporter: Maciej Hołyszko Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 3
Labels: None
Environment:

php 5.3/win, doctrine 1.2 svn, ATTR_QUOTE_IDENTIFIER = true, ATTR_USE_DQL_CALLBACKS = true


Attachments: File DC313TestCase.php    

 Description   

I find no way to define automatic orderBy in m2m relations with column not from reference table, but actual related table.

E.g. BlogPost <= m2m through BlogPostCategory => BlogCategory
I need BlogPost->Categories ordered by BlogCategory.name

class BlogPost extends Doctrine_Record
{
    public function setTableDefinition()
    {
        $this->hasColumn('title', 'string', 128);
        $this->hasColumn('content', 'string');
    }
    
    public function setUp()
    {
        $this->hasMany('BlogCategory as BlogCategories', array('local' => 'id_blog_post', 'foreign' => 'id_blog_category', 'refClass' => 'BlogPostCategory', 'orderBy' => 'name'));        
    }
}

class BlogCategory extends Doctrine_Record
{
    public function setTableDefinition()
    {
        $this->hasColumn('name', 'string', 128);
    }
    
    public function setUp()
    {
        $this->hasMany('BlogPost as BlogPosts', array('local' => 'id_blog_category', 'foreign' => 'id_blog_post', 'refClass' => 'BlogPostCategory'));
    }
}

class BlogPostCategory extends Doctrine_Record
{
    public function setTableDefinition()
    {
        $this->hasColumn('id_blog_post', 'integer', null, array('primary' => true));
        $this->hasColumn('id_blog_category', 'integer', null, array('primary' => true));
    }
    
    public function setUp()
    {
        $this->hasOne('BlogPost', array('local' => 'id_blog_post', 'foreign' => 'id', 'onDelete' => 'CASCADE'));
        $this->hasOne('BlogCategory', array('local' => 'id_blog_category', 'foreign' => 'id', 'onDelete' => 'CASCADE'));
    }
}

The resulting query contains doubled 'name' column in ORDER BY clause, both from reference table and related table, e.g. ORDER BY t2.name, t3.name

I tried putting the following code in BlogCategory::setTableDefinition() instead of attribute in relation definition in BlogPost record:

$this->option('orderBy', 'name');

but the result was the same.

Maybe I'm doing something wrong? Is there a possibility to define an alias, where to get column name from - in orderBy attribute?

Thanks in advance.



 Comments   
Comment by Maciej Hołyszko [ 02/Dec/09 ]

Attached test case.

Comment by Maciej Hołyszko [ 08/Dec/09 ]

I find this issue as critical one now, because when I use e.g.

$this->option('orderBy', 'name');

in a model's definition (not ref class), then when other model is related m2m with it, a query loading both of them with relations will fail because of name column duplicated in ref table.

Comment by suhock [ 23/Apr/10 ]

I am having the same issue with an equivalent test case. For some reason, the 'orderBy' option on the target of the join (set by calling the option() function inside the setUp() method of the model class, not the ref class) is being applied to the relation table. After digging through the 1.2.2 tag a bit, I found altering line 1319 of Query.php as follows seems to fix the problem (at least against my test cases):

if (isset($map['relation'])) {
if (isset($map['relation']) && $map['relation']->getTable() === $map['table']) {

I'll do some more thorough testing and submit a patch if I find time.

Comment by Bart W [ 17/Feb/11 ]

I had this issue as well. suhock's solution fixed it for me. It would be nice if this was merged in to a bug fix release of Doctrine 1.x.

Comment by suhock [ 18/Feb/11 ]

I ended up creating a new ticket, DC-651, which addresses a more general problem with the orderBy feature. You should use the attached Ticket_DC651.patch instead, as I found the solution I provided here is not completely correct and does not pass all test cases.





[DC-1050] Doctrine_Relation_ForeignKey ignores ATTR_COLL_KEY attribute Created: 06/Mar/12  Updated: 03/May/14

Status: Open
Project: Doctrine 1
Component/s: Attributes, Relations
Affects Version/s: 1.2.3
Fix Version/s: None

Type: Bug Priority: Critical
Reporter: Uli Hecht Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Windows 7 64Bit
PHP 5.3
Symfony 1.4


Attachments: Text File ForeignKey.php.patch     Microsoft Word Form01 - Diagnóstico-12012011.doc     File Proposta do sistema de Gestão de ligas.odt     File Proposta do sistema de meio ambiente.odt    

 Description   

Doctrine_Relation_ForeignKey::fetchRelatedFor() executes the following code at line 70:

$coll = $this->getTable()>getConnection()>query($dql, $id);
$related = $coll[0];

As you can see it accesses the first element by using index "0" in $coll and hence ignores a modified ATTR_COLL_KEY-setting, for instance:

$this->setAttribute(Doctrine_Core::ATTR_COLL_KEY, 'id');

Fortunately I had two models (ForeignA and ForeignB) in my project which both have an one-to-one relation to a third model (Main). That helped me finding this bug which causes the following strange behavior:

// program 1:

$m = new Main();
$m->name = 'M1';
$m->setForeignA(new ForeignA()); // has ATTR_COLL_KEY changed to 'id'
$m->setForeignB(new ForeignB());
$m->save();

// program 2:

$m = Doctrine_Core::getTable('M1')->findOneBy('name', 'M1');
$m->getForeignA()->exists(); // false
$m->getForeignB()->exists(); // true

-------------------------

The big problem about this issue is that behavior is inconsistent. If you don't split the example above into two separate programs/processes you won't have problems, since Doctrine accesses the reference which was stored when calling save().

You will get into trouble using functional tests in Symfony. Since there is only a single process for all requests I wasn't able to reproduce a problem caused by this bug which appeared in the production environment.

-------------------------

Edit:

Doctrine_Connection::queryOne() is affected as well!

A solution is to replace

$coll = $this->getTable()>getConnection()>query($dql, $id);
$related = $coll[0];

by

$related = $this->getTable()>getConnection()>query($dql, $id)->getFirst();



 Comments   
Comment by Uli Hecht [ 07/Mar/12 ]

Suggested patch

Comment by joao guermandi [ 03/May/14 ]

Implementação





[DC-1057] Inserts instead of updates for related objects Created: 20/Jul/12  Updated: 17/Apr/14

Status: Open
Project: Doctrine 1
Component/s: Relations
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Grzegorz Godlewski Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 0
Labels: None
Environment:

linux, apache2, php 5.3



 Description   

Ok, so the object relations go like this:

  • Comparison
    • [1:N] Product (FK:comparison_id)
      • [1:N] Rules (FK:product_id, FK:option_id)
      • [1:N] Parameters (FK:product_id)
        • [1:N] Options (FK:parameter_id)

The testing code looks like following:

== CODE START ==

Unable to find source-code formatter for language: php. Available languages are: actionscript, html, java, javascript, none, sql, xhtml, xml
$comp = new Application_Model_Comparison();

/* Filling $comp with data */

for ($i = 0; $i < 10; $i++) {

    $product = new Application_Model_Product();

    // Options referenced in Rules
    $options = array();

    for ($j = 0; $j < 10; $j++) {

        $param = new Application_Model_Parameter();

        for ($k = 0; $k < 10; $k++) {

            $option = new Application_Model_Option();

            $param->Options->add($option);

            // Register a single option for this parameter
            if (!isset($options[$j])) {
                $options[$j] = $option;
            }
        }

        $product->Parameters->add($param);
    }

    for ($j = 0; $j < 10; $j++) {
        $rule = new Application_Model_Rule();

        $rule->Option = $options[$j];
        $product->Rules->add($rule);
    }

    $comp->Products->add($product);
}

/**
 * The first save() goes nicely, all objects
 * are created (INSERTed)
 */ 

$comp->save();

// Remove every second product
$pCount = $comp->Products->count();

for ($i = 0; $i < $pCount; $i += 2) {
    $comp->Products->remove($i);
}

/**
 * Fails while trying to save
 *
 * Comparison->Product->Parameter->Option
 * INSERT ... `parameter_id` cannot be NULL
 *
 * Comparison->Product->Rule
 * INSERT ... `product_id` cannot be NULL
 */

$comp->save();

== CODE END ==

The first save() cleans up the relation information in the graph. All child objects are INSERTED instead of UPDATE.






[DC-1056] Doctrine is not compatible with PHP 5.4 due to change in serialize() behaviour. Created: 04/Jun/12  Updated: 06/Oct/13

Status: Open
Project: Doctrine 1
Component/s: Record, Relations
Affects Version/s: 1.2.3
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Marcin Gil Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 2
Labels: None
Environment:

PHP 5.4+


Attachments: Text File Record.php.patch    

 Description   

In PHP 5.4 there is a change in the way the object references are serialized:

Quote:
"Support for object references in recursive serialize() calls
Prior to PHP 5.4, object references where not saved in recursive serialize calls."

This minor change, breaks down serialization of collections when column of type "array" is present - double serialization occurs.
I'm attaching a patch fixing the issue.



 Comments   
Comment by Colin Darie [ 15/Oct/12 ]

I confirm for possible future readers: this patch works perfectly well. (cf github for several forks of doctrine with other bugfixes).

Comment by steven [ 27/Jan/13 ]

Hi all, does somebody knows where can I get a copy of the Doctrine 1.2.4 version but running on php 5.4?
Thise version you're talking about

Thanks

Comment by Marcin Gil [ 28/Jan/13 ]

I sent you URL to our private svn repo.

Comment by steven [ 28/Jan/13 ]

Thanks, you've saved mi life

Comment by Marcin Gil [ 06/Oct/13 ]

New, better patch.

Comment by Marcin Gil [ 06/Oct/13 ]

Hi, I have uploaded a better patch which resolved one more issue.

Comment by Christophe Coevoet [ 06/Oct/13 ]

Please use a pull request on github to submit a patch





Non-Equal Nest Relations Not Working - from "Children" side (DC-952)

[DC-958] updating Models with Intra-Table Relations cascades strangely Created: 24/Jan/11  Updated: 27/Jan/11

Status: Open
Project: Doctrine 1
Component/s: Behaviors, Documentation, Nested Set, Relations
Affects Version/s: 1.2.3
Fix Version/s: None

Type: Sub-task Priority: Major
Reporter: Daniel Reiche Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None
Environment:

PHP 5.3 / symfony 1.4.9



 Description   

Sorry for the lengthy explanation, couldn't make it more straight forward:

I have a model which is similiar to a nestet set but the tree structure needs to overlap:

For Model A, every Object A1 can have multiple descendant objects A2 and in turn can be a descendant of multiple objects A0.

Since I saw no way to do this with Nested-Set Relations (or Equal-Nested-Sets) I have set up my Model like this:

modules:
columns: ..<do not matter>
relations:
Children:
class: modules
refClass: modules_required
Parents:
class: modules
refClass: modules_required

modules_required:
columns: <do not matter here, just 2 foreign key columns>
relations:
Children:
Parents:

I needed to specify the Relations on both tables, to use onDelete/onUpdate CASCADE rules. Generated Models look fine, just as intended.
(Every Class has many Children and has many Parents...)

Now the strange part:
When I update an object of modules (say id=18), Doctrine issues the following queries:
DELETE FROM modules_required WHERE (required_id = ? AND module_id IN (?, ?, ?, ?, ?)) - (18, 25, 26, 32, 34, 35)
// where 25 to 35 are CHILDREN of 18
UPDATE modules_required SET required_id = ? WHERE module_id = ? AND required_id = ? - (25, 25, 10)
UPDATE modules_required SET required_id = ? WHERE module_id = ? AND required_id = ? - (26, 26, 10)
UPDATE modules_required SET required_id = ? WHERE module_id = ? AND required_id = ? - (32, 32, 10)
UPDATE modules_required SET required_id = ? WHERE module_id = ? AND required_id = ? - (34, 34, 10)
UPDATE modules_required SET required_id = ? WHERE module_id = ? AND required_id = ? - (35, 35, 10)
UPDATE modules_required SET required_id = ? WHERE module_id = ? AND required_id = ? - (25, 25, 12)
//where 10 and 12 are PARENTS of 18
and somewhen, Doctrine encounters an MySQL ERROR because of the previous update marathon:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '25-25' for key 'PRIMARY'

The point is:
1. why is Doctrine trying to create self-referencing relations, and
2. why is it touching the relation at all, when i only did change some text fields in the object?

Is there a better way to solve my problem?



 Comments   
Comment by Daniel Reiche [ 25/Jan/11 ]

forgot to add something: I have done a debug run, to see why these queries are created, when there was no data modified that related to these tables:

Doctrine seems to handle my structure internally as a Nested-Set, although I have not specified an actAs: NestedSet or relations: equal: true statement in the model definition.
Is there a way to prevent symfony from misinterpreting this?

This is not a nested set, as each object can have virtually any other object either as parent or as a child, and additionaly, parent relations can span multiple tree-levels:
Object 2 is parent of Object 3 and 6
Object 3 is parent of Object 4 and 5
Object 4 is parent of Object 6

results in: Object 6 has parents 2 and 4 (where 4 has parent 3 and 3 has parent 2 in turn)

This spanning relations seems to cause the guessed nested set to fail.

I simply wanted to create an m:n Relation using a Reference table and the fact that both m and n are of the same class should not consider doctrine.

Comment by Daniel Reiche [ 26/Jan/11 ]

related to #DC-329:
seems to be the same general problem as described there. Only in DC 1.2.3, doctrine tries to delete every child-relation for some unknown reason.

also the h2aEqualable mentioned there does not work, because it does not prevent symfony from issueing the delete queries. It prevents only the UPDATE-Queries, and thus circumvents the MySQL-Error.

Nevertheless, data is still corrupted after object save, thus not useable in production.





[DC-925] missing hasOne() method-call in many-to-many relation Created: 11/Nov/10  Updated: 11/Nov/10

Status: Open
Project: Doctrine 1
Component/s: Relations
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Simon Schick Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Debian Lenny
Apache 2.0
PHP 5.3.3-0.dotdeb.1
Symfony 1.4.8 - using Doctrine 1.2.x



 Description   

Here's my YAML-file for the model: http://pastie.org/1290649

I'm using the following command to build the whole model: symfony doctrine:build --all --and-load
By this command symfony will create the model using Doctrine.

Please have a closer look at the class BaseTicketHasHardware: http://pastie.org/1290737
If I compare it to the class BaseTicketHasNote I expect a class like this: http://pastie.org/1290765
But Doctrine has created this class: http://pastie.org/1290766






[DC-888] Foreign key id columns do not respect ATTR_DEFAULT_IDENTIFIER_OPTIONS Created: 13/Oct/10  Updated: 13/Oct/10

Status: Open
Project: Doctrine 1
Component/s: Migrations, Relations, Schema Files
Affects Version/s: 1.2.3
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Tom Boutell Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Any



 Description   

Some time ago Jon Wage suggested that one can override the 8-byte default integer type for IDs by setting Doctrine_Core::ATTR_DEFAULT_IDENTIFIER_OPTIONS in configureDoctrine (in a Symfony project), like this:

public function configureDoctrine(Doctrine_Manager $manager)

{ // Use 4-byte IDs for backwards compatibility with databases built on // Apostrophe 1.4, sfDoctrineGuard pre-5.0, etc. You don't need this for // a brand new site $options = $manager->getAttribute(Doctrine_Core::ATTR_DEFAULT_IDENTIFIER_OPTIONS); $options['length'] = 4; $manager->setAttribute(Doctrine_Core::ATTR_DEFAULT_IDENTIFIER_OPTIONS, $options); }

This works for primary key id columns. However it is not respected by foreign key id columns, which do not consult ATTR_DEFAULT_IDENTIFIER_OPTIONS.

I looked at working around this using ATTR_DEFAULT_COLUMN_OPTIONS, however it is not type-specific. So if you set a length of 4 with that option, it applies not just to all integers but also to dates, datetimes, booleans and many other things that definitely should not be 4 bytes.

The correct fix seems to be for foreign key id columns to respect ATTR_DEFAULT_IDENTIFIER_OPTIONS.

Also, ATTR_DEFAULT_COLUMN_OPTIONS should probably let you specify different defaults for each column type as the length option is basically not usable in its current form. But that would not be a particularly clean solution to the foreign key id problem since limiting non-ID integers to 4 bytes should not be necessary.

  • * *

The motivation for this bug report:

The new stable release of sfDoctrineGuardPlugin (for Symfony) does not specify an integer size as it formerly did, so the size of integers now defaults to 8 bytes. This breaks backwards compatibility with existing code that adds foreign key relationships to sfGuard objects like sfGuardUser, etc. Creating migrations to deal with changing this across all tables involved is quite difficult (all foreign key indexes must be dropped and recreated - doctrine:migrations-diff is unable to figure it out, understandably).






[DC-880] Versionable + I18n creates additional migration with irrelevant data Created: 06/Oct/10  Updated: 17/Apr/14

Status: Open
Project: Doctrine 1
Component/s: Behaviors, I18n, Migrations, Relations
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Thomas Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 1
Labels: None
Environment:

PHP 5.2, Symfony 1.4, Diem 5.1, Doctrine 1.2.2



 Description   

First run of generate-migrations-diff and migrate creates 2 migration diff files. First one for new tables, second one for new indexes and foreign keys. Than if I run generate-migrations-diff again another version is created although nothing was changed and following is inside:

  • 1st entry tries to drop a foreign key never been created and not existing in file
  • next entry tries to create a foreign key already existing
  • 3rd entry tries to create an existing index

After a long try and errorI found out that it's only happening with I18n plus Versionable behavior.

As I already have spent much time for a report please have also a look at: http://forum.diem-project.org/viewtopic.php?f=2&t=173&sid=5e0e3349c0e15a169bc9990a3104b3f6#p465

As I'm quite new to Doctrine and Symfony systems I cannot get further, but willing for more investigation if just one could give me a hint where to start.



 Comments   
Comment by Andrew Coulton [ 10/Oct/10 ]

I think this is because the versionable behaviour doesn't define a table name in the Doctrine_Template_Versionable class. As a result, if using model prefixes, the prefixes are not discarded from the table names when the behaviour model classes are built. This means that the tables have different names to what is expected, so they have different index keys, so the indexes are dropped and recreated as part of the migration.

I have committed unit tests and patch for this issue (which applies to Searchable also) to http://github.com/acoulton/doctrine1/tree/DC-880

Comment by Daniele Dore [ 19/Sep/11 ]

I experienced the same problem in the latest version 1.2.4, and the patch proposed by Andrew Coulton solves the problem.
Why the fix is not included in official release?





[DC-845] One of our Foreign Keys is not being inserted/passed Created: 27/Aug/10  Updated: 27/Aug/10

Status: Open
Project: Doctrine 1
Component/s: Record, Relations, Transactions
Affects Version/s: 1.2.0, 1.2.1, 1.2.2, 1.2.3
Fix Version/s: None

Type: Bug Priority: Major
Reporter: charles wisniewski Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Linux ubuntu 2.6.31-22-generic #63-Ubuntu SMP Thu Aug 19 00:23:50 UTC 2010 x86_64 GNU/Linux
PHP 5.2.10-2ubuntu6.4 with Suhosin-Patch 0.9.7 (cli) (built: Jan 6 2010 22:56:44)
mysql Ver 14.14 Distrib 5.1.37, for debian-linux-gnu (x86_64) using EditLine wrapper



 Description   

We are working on a symfony/doctrine project and have come to a near halt on development.

We feel that now, it may be a bug/feature in doctrine, regarding foreign keys

Part of our model includes a join table that references three different table. Below is a diagram of what the model looks like, and the relevant portion of our schema.yml is at the bottom.

Image of our schema: http://imgur.com/dfFYI.png

We have a form that contains a set of embedded forms that attempt to create a new Person entry and add rows to the join table, adding items to the PersonName table as needed.

The form attempts to do this by creating and saving PersonName objects with NameType parameters, but are running into the problem of Doctrine not including that column when trying to do an insert into the join table.

Part of the problem seems to be caused by the Doctrine_Connection_UnitOfWork::saveAssociations method:

foreach ($v->getInsertDiff() as $r)

{ $assocRecord = $assocTable->create(); $assocRecord->set($assocTable->getFieldName($rel->getForeign()), $r); $assocRecord->set($assocTable->getFieldName($rel->getLocal()), $record); $this->saveGraph($assocRecord); }

Are we correct in understanding that this means that Doctrine 1.2 does not support tables with multiple foreign keys in this scenario?

Here is the relevant portion of schema.yml:

agPerson:
columns:
id:
primary: true
type: integer(5)
autoincrement: true
relations:
agPersonName:
class: agPersonName
refClass: agPersonMjAgPersonName
local: person_id
foreign: person_name_id
agPersonNameType:
class: agPersonNameType
refClass: agPersonMjAgPersonName
local: person_id
foreign: person_name_type_id
agPersonNameType:
columns:
id:
primary: true
type: integer(2)
autoincrement: true
person_name_type:
unique: true
type: string(30)
notnull: true
app_display:
default: 1
type: boolean
notnull: true
relations:
agPerson:
class: agPerson
refClass: agPersonMjAgPersonName
local: person_name_type_id
foreign: person_id
agPersonName:
class: agPersonName
refClass: agPersonMjAgPersonName
local: person_name_type_id
foreign: person_name_id
agPersonName:
columns:
id:
primary: true
type: integer(5)
autoincrement: true
person_name:
unique: true
type: string(64)
notnull: true
relations:
agPerson:
class: agPerson
refClass: agPersonMjAgPersonName
local: person_name_id
foreign: person_id
agPersonNameType:
class: agPersonNameType
refClass: agPersonMjAgPersonName
local: person_name_id
foreign: person_name_type_id
agPersonMjAgPersonName:
columns:
id:
primary: true
type: integer(5)
autoincrement: true
person_id:
type: integer(5)
notnull: true
person_name_id:
type: integer(5)
notnull: true
person_name_type_id:
type: integer(2)
notnull: true
is_primary:
type: boolean
notnull: true
indexes:
UX_ag_person_mj_ag_person_name:
fields: [person_name_id, person_name_type_id, person_id]
type: unique
relations:
agPerson:
local: person_id
foreign: id
agPersonName:
local: person_name_id
foreign: id
agPersonNameType:
local: person_name_type_id
foreign: id
actAs:
Timestampable:

As a caveat: we've noticed that sfdoctrineguard group table, has such a relationship:

mysql> describe sf_guard_user_group;
---------------------------------------+

Field Type Null Key Default Extra

---------------------------------------+

user_id int(11) NO PRI 0  
group_id int(11) NO PRI 0  
created_at datetime NO   NULL  
updated_at datetime NO   NULL  

---------------------------------------+

i.e. IT has two foreign keys taken into account






[DC-835] Inconsistent record validation on a notnull foreign key when the local relation is set Created: 19/Aug/10  Updated: 24/Aug/10

Status: Open
Project: Doctrine 1
Component/s: Record, Relations, Validators
Affects Version/s: 1.2.1
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Adam Huttler Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File dc-835-patch.txt     File ForeignKeysTestCase.php    

 Description   

Doctrine_Validator_ForeignKeys_TestCase#testForeignKeyIsValidIfLocalRelationIsSet()

This test passes fine as is. But it fails if I make the following change:

public function testForeignKeyIsValidIfLocalRelationIsSet()
{
    //$person = new TestPerson();
    $address = new TestAddress();
        
    //$address->Person = $person;    
    $address->Person->first_name = "John";
        
    $table = $address->getTable();
    $errors = $table->validateField('person_id', $address->person_id, $address);
        
    $this->assertEqual(0, $errors->count());
}

The only difference is that instead of explicitly assigning $address->Person, I'm letting it happen automatically when assigning the first name. What is it about the property chaining when creating the related record that screws up doctrine's internal reference tracking?



 Comments   
Comment by Adam Huttler [ 19/Aug/10 ]

This is an existing test case for which I've added two tests. The first one fails, while the second passes. The first one captures the issue I'm experiencing.

Comment by Adam Huttler [ 24/Aug/10 ]

This patch augments the test file with the new test and also makes a change to Doctrine_Related_LocalKey that causes the test to pass.

Unfortunately, it causes another test to fail: 1072.

I don't fully understand test 1072, but it appears to be testing closely related behavior (i.e. relation chaining).

What do you think?





[DC-797] Records containing a one-to-one relation are hydrated as dirty/modified Created: 26/Jul/10  Updated: 06/Jul/11

Status: Open
Project: Doctrine 1
Component/s: Record, Relations
Affects Version/s: 1.2.2
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Dominic Scheirlinck Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None

Attachments: File Record.php.diff     File test.php    

 Description   

Attached is a self-contained 80 line test. In the test, Foo has an one to one relation to Bar. There is a null value in the foreign key column (at least one Foo without a Bar). And the relation is being used via this DQL:

Doctrine_Query::create()->from('Foo f')->leftJoin('f.Bar b')->execute();

At around line 254 of Doctrine_Hydrator_Graph/Graph.php, the hydrator sets the value of the relation column to Doctrine_Null if there is no related record:

$prev[$parent][$relationAlias] = $this->getNullPointer();

This causes Doctrine_Record to check if the value of the foreign key field was updated, which it does by calling Doctrine_Record::_isValueModified(). However, that method considers an update from null to Doctrine_Null as a modification. So, the record (and eventually the entire Collection returned) is marked as Doctrine_Record::STATE_DIRTY, even though it contains no modifications. This occurs during hydration, so the caller never sees the record as being clean.

The workaround I'm using is to subclass Doctrine_Record, and return false from _isValueModified() when moving from null to Doctrine_Null. But I think this could also be fixed in the hydrator.



 Comments   
Comment by Dominic Scheirlinck [ 15/Sep/10 ]

Patch is here: http://github.com/doctrine/doctrine1/pull/7

Comment by Dominic Scheirlinck [ 17/Oct/10 ]

New pull request, done on a topic branch this time (and rebased to be much nicer)

http://github.com/doctrine/doctrine1/pull/8

Comment by Derek Price [ 06/Jul/11 ]

Record.php.diff contains basically the patch Dominic attached but also makes sure that the internal property value is set regardless of whether the record is marked as dirty or not. Some code will break when the internal property value is left <unset> instead of Doctrine_Null.





[DC-774] Cannot fromArray a toArray with many to many records Created: 01/Jul/10  Updated: 01/Jul/10

Status: Open
Project: Doctrine 1
Component/s: Record, Relations
Affects Version/s: 1.2.2
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Jeff Chu Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File doctrine-link.patch    

 Description   

When working with a many to many record, if you toArray then synchronizeWithArray/fromArray the result - you get an exception.

This appears to be due to the fact that toArray returns collections of array(0 => false) (because a record is in a locked state) and fromArray will attempt to link() the refClass (which has multiple identifiers).

Here's a test that should show this behavior:

class Doctrine_Ticket_DC774_TestCase extends Doctrine_UnitTestCase
{
    public function prepareTables()
    {
        $this->tables[] = 'EntityAddress';
        $this->tables[] = 'Book';
        parent::prepareTables();
    }

    public function prepareData()
    {
        $user = new User();
        $user->name = 'TestUser';

        $address = new Address();
        $address->address = 'TestAddress';

        $user->Addresses[] = $address;
        
        $user->save();
    }

    public function testToArraySynchronizeWithManyToMany() {
        $user = Doctrine_Core::getTable('User')->findOneByName('TestUser');
        $user->refreshRelated();
        $user->synchronizeWithArray($user->toArray());
    }

    public function testToArrayFromManyToMany() {
        $user = Doctrine_Core::getTable('User')->findOneByName('TestUser');
        $user->refreshRelated();
        $user->fromArray($user->toArray());
    }
}



 Comments   
Comment by Jeff Chu [ 01/Jul/10 ]

I doubt this is the right way to fix this, but we wrote in a patch that has the link() function ignore relations that with multiple identifiers. I figured this would be alright since linking those in directly don't make too much sense anyways.

It seems to pass the doctrine test suite. I've attached the patch in case anyone is curious.





[DC-742] Add support for relations consist on two or more fileds Created: 16/Jun/10  Updated: 07/Aug/10

Status: Open
Project: Doctrine 1
Component/s: Relations
Affects Version/s: None
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: Tomasz Kuter Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None
Environment:

n/a



 Description   

Let's say I have following tables:

article

  • art_id

article_version

  • art_id
  • art_version

category

  • cat_id

category2article

  • cat_id
  • art_id

category2article_version

  • cat_id
  • art_id
  • art_version

As I know I can describe relation between tables `article` and `category`, but I cannot describe relation between `artcile_version` and `category`.
The problem is Doctrine supports only following relation mapping:
$this->hasMany('Category as categories', array(
'local' => 'art_id',
'foreign' => 'cat_id',
'refClass' => 'Category2Article'
));

It would be nice to have also something like that:
$this->hasMany('Category as categories', array(
'local' => array('art_id', 'art_version')
'foreign' => 'cat_id',
'refClass' => 'Category2ArticleVc'
));

In the first (supported) example Doctrine produce something like that, when I add LEFT JOIN STATEMENT:
SELECT *
FROM article a
LEFT OUTER JOIN category2article c2a ON c2a.art_id = a.art_id
LEFT OUTER JOIN category c ON c.cat_id = c2a.cat_id

But I would like to have also support for following example:
SELECT *
FROM article_version a_vc
LEFT OUTER JOIN category2article_version c2a_vc ON c2a_vc.art_id = a_vc.art_id AND c2a_vc.art_version = a_vc.art_version
LEFT OUTER JOIN category c ON c.cat_id = c2a_vc.cat_id


Very best,
Tomasz Kuter

PS. I will check Doctrine code.. maybe I will solve it by myself..






[DC-684] After adding a Reference, the ForeignKeys in the DB are not updatet Created: 14/May/10  Updated: 26/Oct/10

Status: Open
Project: Doctrine 1
Component/s: Record, Relations
Affects Version/s: 1.2.2
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Lars Kosubek Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 1
Labels: None
Environment:

Ubuntu 9.04, PHP 5.2.6, MySQL 5.1, Zend Framework


Attachments: Text File DC_684_dirty_fix.patch    

 Description   

After query a record from the DB, where a foreign key is null, and changing only the reference belonging to this foreign key, and only these reference no other value of the record, a save of the record doesn't lead to a change in the foreign key field.

For example: I'll save a user record with some data of a regestration and give him the possibillity to add a city where he cames from later in his account settings, if no other user attribute is changed, the state of the user record is still CLEAN. The result is that I can access the user->City property correctly only as long as no refresh from the db is done. So the changing of the foreign key belonging to the city isn't persistent in the DB.

Example Code:
$user = new Model_User();
$user->firstName = md5(rand());
$user->save();

$id = $user->id;
unset($user);
assert(! $user);

$user = Model_UserTable::getInstance()->find($id);
assert(!$user->relatedExists('City'));

$user->City->name = 'Mainz';
$user->save();
unset($user);

$user = Model_UserTable::getInstance()->find($id);
$user->refresh(true);
assert($user->City->name == 'Mainz');

The last assert failse. I realized the problem while updating just a referenz using the fromArray() method like $user->City->fromArray(). The city would be saved correctly in DB but the foreign key in the user table would not be updated. After debugging I recognized that the $user is not replaced in UnitOfWork::saveGraph() because the $user is still in CLEAN state.

Using " $user->coreSetRelated('Country', $user->Country);" or "$user->state(Doctrine_Record::STATE_DIRTY);" after "$user->City->name = 'Mainz'" would fix the prob in this case. As well as creating a new City instance an set $user->City with this instance like:

$city = new Model_City();
$city->name = 'Mainz';
$user->City = $city;

Also $user->isModified(true) is true. So I fixed the issues in my case by changing the state of my records to DIRTY if the "$this->state() == CLEAN && $user->isModified(true) == true" in the preSave() method of an abstract class that my Base classes are extending....



 Comments   
Comment by Alexandre Ravey [ 15/Sep/10 ]

Spend the last hour trying to get a workaround on this one.

It apear to me that the solution is not easy. The object is modified while in STATE_LOCKED state, meaning that any state change in Record::_set() is not passed back to UnitOfWork::saveGraph() and therfor not saved in the database.

Finaly I've managed to make a realy dirty fix, I'll attach it if it come handy to somebody.
Keep in mind this is only a workaround and has NOT been tested. Use at your own risk...

Comment by Alexandre Ravey [ 15/Sep/10 ]

Dirty fix, see comments.
! NOT tested thoroughly !





[DC-628] Two queries on the same table seems to share set of fields Created: 14/Apr/10  Updated: 14/Jun/10

Status: Open
Project: Doctrine 1
Component/s: Relations
Affects Version/s: 1.2.2
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Vlatko Basic Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None
Environment:

OS: Vista 64
Zend Framework 1.10.1
MySQL: 5.1.39



 Description   

Two queries:

1. $ab1 = Doctrine_Query::create()
->from('Model_UserAddressbook ab')
->leftJoin('ab.UserPersons up')
->leftJoin('ab.AdminUsers au'); // second one doesn't have this join

2. $ab2 = Doctrine_Query::create()
->from('Model_UserAddressbook ab')
->leftJoin('ab.UserPersons up');

When executing the following fetchOne:

A.) $x1 = $ab2->fetchOne()->toArray(); // has fields from addressbook, and subarray UserPersons, OK
B.) $x2 = $ab1->fetchOne()->toArray(); // has fields from addressbook, and subarray UserPersons and AdminUsers, OK
C.) $x3 = $ab2->fetchOne()->toArray(); // has fields from addressbook, and subarray UserPersons and AdminUsers, NOT OK

$x1 and $x3 should have the same set of fields, but $x3 has somehow received set of fields from $x2.

I haven't turned on any caching, but even if the caching is on, the result sets shouldn't mix, right?

I'm talking just about field names (set of fields), not fields data.






[DC-666] Unable to create relations with several fields Created: 05/May/10  Updated: 07/Aug/10

Status: Open
Project: Doctrine 1
Component/s: Relations
Affects Version/s: 1.2.0-ALPHA1, 1.2.0-ALPHA2, 1.2.0-ALPHA3, 1.2.0-BETA1, 1.2.0-BETA2, 1.2.0-BETA3, 1.2.0-RC1, 1.2.0, 1.2.1, 1.2.2, 1.2.3
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Pavel Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Windows Server 2003 SP2
Apache 2.2.14
PHP 5.3.1
Doctrine 1.2.2



 Description   

I have 2 tables.

t1 :


id [Primary Key]
field1
field2
...
fieldn
t2_id [related to t2.id]

primary key: id

t2:

id [related to t1.t2_id]
fixed_set [predefined set of values (for example "a", "b", "c")]
field1
field2
...
fieldn

primary key: id + fixed_set

I need to use relation like follows:
SELECT *
FROM t1
LEFT JOIN t2 ON (t1.t2_id = t2.id AND t2.fixed_set = "a")

There is followed text in phpdoc from Relation.php:

  • local the local field(s)
    *
  • foreign the foreign reference field(s)

But it is unable to use several fields in "local" and "foreign", only one "local" and "foreign" field.






[DC-652] unidirectionnal hasMany definition Created: 27/Apr/10  Updated: 14/Jun/10

Status: Open
Project: Doctrine 1
Component/s: Relations
Affects Version/s: 1.2.2
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Thomas Tourlourat - Armetiz Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Here the definition of the Domain Model : http://pastebin.com/i80d73s8

To resume, Show is a mother class. Video, is a direct extend from Show.
ShowContainer is an abstract class that expend Show. It define an hasMany relation to Video, through CompoShowShow.
Program and Playlist are extends ShowContainer.

the following DQL Query work fine.

$query = Doctrine_Query::create ()
->from ("Model_Program program")
->leftJoin ("program.children children");
$oShow = $query->fetchOne ();
var_dump (get_class ($oShow->children[0])); //Output Model_Video

But, the following code isn't working :

$oProgram = Doctrine_Core::getTable ("Model_Program")->find (2);
$oProgram->children;

//Throw Exception
//Message: Unknown record property / related component "children" on "Model_Program"
//Doctrine\Record.php(1381)

The Program#2 is in the database.

Here we are.



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

We'll need some more information. I don't see the Model_Program model anywhere. Can you create a failing test case?





[DC-651] [PATCH] Doctrine_Record::option('orderBy', ...) of join's right side being applied to refTable in m2m relationship Created: 26/Apr/10  Updated: 17/Apr/14

Status: Open
Project: Doctrine 1
Component/s: Query, Relations
Affects Version/s: 1.2.2, 1.2.3
Fix Version/s: 1.2.2, 1.2.3

Type: Bug Priority: Major
Reporter: suhock Assignee: Guilherme Blanco
Resolution: Unresolved Votes: 2
Labels: None
Environment:

CentOS 5.4
PHP 5.3.2
MySQL 5.1.44, for unknown-linux-gnu (x86_64)


Attachments: File DC651TestCase.php     File Query_orderBy_relation.diff     Text File Ticket_DC651.patch    

 Description   

When using the Doctrine_Record::option('orderBy', ...) feature on a table definition, where that table is the target of a many-to-many join, the specified orderBy columns are applied to the relation table's alias. So for example, given the following definitions:

class User extends Doctrine_Record {
  public function setTableDefinition() {
    $this->hasColumn('uid', 'integer', null, array('primary' => true));
    $this->option('orderBy', 'uid');
  }

  public function setUp() {
    $this->hasMany('Group as groups', array('refClass' => 'UserGroup', 'local' => 'user_uid', 'foreign' => 'group_id'));
  }
}

class Group extends Doctrine_Record {
  public function setTableDefinition() {
    $this->hasColumn('gid', 'integer', null, array('primary' => true));
  }

  public function setUp() {
    $this->hasMany('User as users', array('refClass' => 'UserGroup', 'local' => 'group_gid', 'foreign' => 'user_id'));
  }
}

class UserGroup extends Doctrine_Record {
  public function setTableDefinition() {
    $this->hasColumn('user_uid', 'integer', null, array('primary' => true));
    $this->hasColumn('group_gid', 'integer', null, array('primary' => true));
  }

  public function setUp() {
    $this->hasOne('User as user', array('local' => 'user_uid', 'foreign' => 'uid'));
    $this->hasOne('Group as group', array('local' => 'group_gid', 'foreign' => 'gid'));
  }
}

the following queries:

$query = Doctrine_Query::create()
  ->select('u.*')
  ->from('User u')
  ->leftJoin('u.groups g WITH g.gid=?', 1);
echo $query->getSqlQuery() . "\n";

$query = Doctrine_Query::create()
  ->select('g.*')
  ->from('Group g')
  ->leftJoin('g.users u WITH u.uid=?', 1);
echo $query->getSqlQuery() . "\n";

will output the following:

SELECT u.uid AS u__uid FROM user u LEFT JOIN user_group u2 ON (u.uid = u2.user_uid) LEFT JOIN group g ON g.gid = u2.group_id AND (g.gid = ?) ORDER BY u.uid
SELECT g.gid AS g__gid FROM group g LEFT JOIN user_group u2 ON (g.gid = u2.group_gid) LEFT JOIN user u ON u.uid = u2.user_id AND (u.uid = ?) ORDER BY u.uid, u2.uid

The orderBy option() call is applied to the User definition. The SQL for the first query is correct (where User is on the left side of the join). The SQL for the second query (where User is on the right-most side of the join), however, is obviously incorrect (UserGroup doesn't even have a uid column). Basically, User's orderBy option is being applied to both the User table and its respective reference table, UserGroup, when it is the target of a join.

After digging through the source for a while, I believe I've come up with a patch for this issue (which should be checked by someone more knowledgeable of Doctrine's internals). Basically, in the Doctrine_Query::buildSqlQuery() function, a call is made to Doctrine_Relation::getOrderByStatement() with the reference table (UserGroup)'s alias (u2), which in turn makes a call to Doctrine_Table::getOrderByStatement() on the referenced table (User), filling in the ORDER BY clause with User columns using UserGroup's alias. My solution was to reorder the logic so that the test for a reference class is made before the initial call to getOrderByStatement() is made. It seems to work against my test case and the test cases in the repository. I'll post my patch momentarily.

This bug was first mentioned in the comments in DC-313, but the original ticket comes across as more of a feature request for the hasMany() orderBy feature.



 Comments   
Comment by suhock [ 26/Apr/10 ]

attached a test case for this bug

Comment by suhock [ 26/Apr/10 ]

patch against /branches/1.2 HEAD (should also work apply to 1.2.2 tag)

Comment by Dan Ordille [ 30/Aug/10 ]

I can confirm this as an issue. However I don't think the above patch adequately fixes the problem it seems like with it an order by is still added for the ref column however the relation alias is lost.

My query with the patch became
SELECT g.gid AS g__gid FROM group g LEFT JOIN user_group u2 ON (g.gid = u2.group_gid) LEFT JOIN user u ON u.uid = u2.user_id AND (u.uid = ?) ORDER BY u.uid, uid

I made an another patch that prevents this extra order by clause from being added and have attached it.

Comment by suhock [ 21/Sep/10 ]

I tried out the new patch (Query_orderby_relation.diff), but it provides a reversed diff (patching goes from a patched version to the original). After applying it manually, it fails the provided test case and several additional test cases from the repository.

The original patch DOES pass the provided test case, when applied against 1.2.2, 1.2.3, or the 1.2 branch from the repository. It does not pass, however, Doctrine_Query_Orderby_TestCase. As the previous poster mentioned, it fails to resolve aliases in instances where the 'orderBy' option is specified in a relation definition.

I deleted the original patch and am providing a revised patch (Ticket_DC651.patch) against branch 1.2 HEAD (also works with 1.2.3), which fixes this issue. It passes all working test cases, including Doctrine_Query_Orderby_TestCase and DC651TestCase.

Comment by José De Araujo [ 31/Aug/11 ]

I had this issue recently on a application I'm working on as described the oderBy option was applied on the joined table on a column that even doesn't exist in it. I used the DC651 patch provided and it solved the issue, so far I haven't seen any side effect to it.





[DC-637] Many-to-many: Using Association Class (refclass) property in query adds leftJoin Created: 20/Apr/10  Updated: 20/Apr/10

Status: Open
Project: Doctrine 1
Component/s: Query, Relations
Affects Version/s: 1.2.2
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Pablo Grass Assignee: Guilherme Blanco
Resolution: Unresolved Votes: 0
Labels: None
Environment:

PHP 5.3.2 (cli) (built: Mar 4 2010 22:12:20)
mysql 5.1.45
centOS


Attachments: File example.php    

 Description   

When trying to use a refclass property - i.e. normalization table column - in a query, an unnecessary join is added to the query created, which is then used to "access" the property.

This issue has already been discussed back in May 2008 but still seems to persist.
Please see the google group discussion http://groups.google.com/group/doctrine-user/browse_thread/thread/c655832a450ccd1a/9cb6eca6ae1c3dee for example + comments.

Unfortunately it is hardly possible to write a test case for this, as working SQL is generated, but the query is just not right (test case basically would have to assert the query string, wich does not make much sense).
Another way to test if it does "what it should", could be to assert contents of $q->getTableAliasMap() - but does not seem ideal either.

John Wage commented on this issue
"Can you create a ticket for this with a failing test case? I believe this
should be possible and we should investigate a fix for it.
Thanks, Jon "
http://groups.google.com/group/doctrine-user/browse_thread/thread/c655832a450ccd1a/9cb6eca6ae1c3dee#msg_c73934a38515cadb






[DC-601] When using a join and giving an alias to each select column the hyrdrator only returns one row. Created: 25/Mar/10  Updated: 02/Aug/10

Status: Open
Project: Doctrine 1
Component/s: Query, Relations
Affects Version/s: 1.2.2
Fix Version/s: None

Type: Bug Priority: Major
Reporter: will ferrer Assignee: Guilherme Blanco
Resolution: Unresolved Votes: 2
Labels: None
Environment:

XP Xamp



 Description   

Hi All
I am running into a strange problem using Doctrine-1.2.2-- I have a multi row result set but only the first row of it is returned in the hyrdated array that is generated.
I have tracked this down in the code to get a basic idea of whats going on – it seems that the $id variable in the hydrateResultSet function in Doctrine_Hydrator_Graph isn't being populated properly with data about the fields that are returning from my query. The _gatherRowData function seems to never detect that one of my columns is an identifier ("if ($cache[$key]['isIdentifier'])

{" doesn't return true ever so the next line of code: "$id[$dqlAlias] .= '|' . $value;" doesn't run). I think this is the problem but I don't totally understand how the mapping process is taking place in this function so can't be absolutely sure. This hydration problem goes away if I don't use left joins in my query, or if I use a query where not every field I am requesting is assigned an alias (at least one of the fields doesn't use the 'as' syntax). For instance this php: {code}

$q = Doctrine_Query::create();
$q->from('Customer Customer');
$q->leftJoin('Customer.Zip Zip');
$q->addSelect('Customer.firstname as first_name');
$q->addSelect('Customer.postalcode as postalcode');
$q->setHydrationMode(Doctrine::HYDRATE_ARRAY);

Generates this DQL: 

SELECT Customer.firstname as first_name, Customer.postalcode as postalcode FROM Customer Customer LEFT JOIN Customer.Zip Zip

And this SQL:

SELECT c.firstname AS c_0, c.postalcode AS c_1 FROM customers c LEFT JOIN zips z ON c.postalcode = z.postalcode

Which results in this return after hyrdration: 

array('0'=>array('first_name'=>'Armando', 'postalcode'=>'00659'))

However the following code hydrates just fine: 

$q = Doctrine_Query::create();
$q->from('Customer Customer');
$q->addSelect('Customer.firstname as first_name');
$q->setHydrationMode(Doctrine::HYDRATE_ARRAY);

As does this code: 

$q = Doctrine_Query::create();
$q->from('Customer Customer');
$q->leftJoin('Customer.Zip Zip');
$q->addSelect('Customer.firstname');
$q->addSelect('Customer.postalcode as postalcode');
$q->setHydrationMode(Doctrine::HYDRATE_ARRAY);

Here is the yaml for the sample data I am testing on: 

detect_relations: false
package: Example
options:
type: INNODB
charset: utf8
Customer:
tableName: customers
columns:
customer_id:
type: integer(4)
primary: true
notnull: true
autoincrement: true
firstname:
type: string(45)
lastname:
type: string(45)
streetaddress:
type: string(45)
city:
type: string(45)
state:
type: string(45)
postalcode:
type: string(45)
relations:
Order:
type: many
local: customer_id
foreign: customer_id
Zip:
type: one
local: postalcode
foreign: postalcode
options:
type: InnoDB
Zip:
connection: default_schema
tableName: zips
columns:
postalcode:
type: varchar(30)
primary: true
latitude: 'float(10,6)'
longitude: 'float(10,6)'
city: string(50)
state: string(50)
country: string(50)
type: string(50)
relations:
Customer:
type: many
local: postalcode
foreign: postalcode


Perhaps there is something simple I am overlooking. To get around this I am just always selecting the primary key from my main table in every query.

Thanks in advance for any advice.
Will Ferrer



 Comments   
Comment by will ferrer [ 03/Apr/10 ]

This problem also exists in 1.2.2 so I have updated the post to reflect this.

Comment by Peter Bücker [ 06/Apr/10 ]

I experienced the same problem with Doctrine 1.2 (r7329). I also fixed this by adding the primary key of the table I select from to the select list.

Comment by will ferrer [ 07/Apr/10 ]

Hi Peter

Thats how I am currently working around the bug as well but hopefully it will get rectified in a later version of doctrine.

Thanks for the comment.

Will

Comment by Sam Doun [ 08/Jun/10 ]

Hi all,

I'm new to doctrine and since yesterday, I'm experiencing exactly the same behavior.
Any news about this subject ? Is there a doctrine version where the pb is solved ?
Help !

Regards,
Doun

Comment by will ferrer [ 08/Jun/10 ]

Hi Sam

Currently I am working around this bug by always adding the primary key of the table to the select (like peter also mentions above).

It is a work around for the problem but so far it has been reliable for me.

I hope that helps until there is a patch for it.

Will Ferrer

Comment by Sam Doun [ 09/Jun/10 ]

Hi Will

I'll do so.
Thank you VM.

Sam Doun

Comment by Shuchi Sethi [ 02/Aug/10 ]

Hi,

Has there been any patch release for the same?
We just upgraded from Doctrine 1.1 to 1.2 and our project now crashes.

For DQL -

function getServiceDetails($merchantId,$merchantServiceId) {
    $q = Doctrine_Query::create()
        ->select('b.*, m.name as merchant_service_name,payment_mode.name as payment_mode_name,payment_mode.id as paymentMode,p.id as paymentModeOption ')
        ->from('ServicePaymentModeOption b')
        ->leftJoin("b.MerchantService m")
        ->leftJoin("m.Merchant merchant")
        ->leftJoin("b.PaymentModeOption p")
        ->leftJoin("p.PaymentMode payment_mode")
        ->where("merchant.id=?",$merchantId)
        ->andWhere("b.merchant_service_id=?",$merchantServiceId)
        ->groupBy('p.name');

    return $res = $q->execute(array(),Doctrine::HYDRATE_ARRAY);
  }  

Result with Doctrine 1.1 is

Array
(
    [0] => Array
        (
            [id] => 1
            [merchant_service_id] => 1
            [payment_mode_option_id] => 1
            [created_at] =>
            [updated_at] =>
            [deleted] =>
            [created_by] =>
            [updated_by] =>
            [merchant_service_name] => NIS Passport
            [merchant_name] => NIS
            [payment_mode_option_name] => Bank
            [payment_mode_name] => Bank
            [paymentMode] => 1
            [paymentModeOption] => 1
            [MerchantService] => Array
                (
                    [merchant_service_name] => NIS Passport
                    [Merchant] => Array
                        (
                            [merchant_name] => NIS
                        )

                )

            [PaymentModeOption] => Array
                (
                    [payment_mode_option_name] => Bank
                    [paymentModeOption] => 1
                    [PaymentMode] => Array
                        (
                            [payment_mode_name] => Bank
                            [paymentMode] => 1
                        )

                )

        )
)

Result with Doctrine 1.2 is

Array
(
    [0] => Array
        (
            [id] => 1
            [merchant_service_id] => 1
            [payment_mode_option_id] => 1
            [created_at] =>
            [updated_at] =>
            [deleted_at] =>
            [created_by] =>
            [updated_by] =>
            [merchant_service_name] => NIS Passport
            [merchant_name] => NIS
            [payment_mode_option_name] => Bank
            [payment_mode_name] => Bank
            [paymentMode] => 1
            [paymentModeOption] => 1
        )
)

We have used Hydration for the result set at lot of places. Please suggest if there could be a fix without going about revising everything that has been coded.

Looking forward to a quick response.





[DC-587] Problem with non equal self referencing many to many relations Created: 18/Mar/10  Updated: 08/Jun/10

Status: Open
Project: Doctrine 1
Component/s: Relations
Affects Version/s: 1.2.1
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Nil Null Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Windows 7600 / Linux / PHP 5.2.13 / PHP 5.3.0


Attachments: File person.php     File relation.php     File test.php    

 Description   

I think that this bug has been reported already here:
http://www.doctrine-project.org/jira/browse/DC-329?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
But I thought that it might be useful to submit a very simple test case, with the bug completely isolated.
When you create a self referenced non equal many-to-many relation like: person has many parents AND has many children (taken from the documentation).

In the attached test case, after both collections of related records are altered within the foreach statement, Doctrine somehow messes up the Ids in the reference class. Now, it's important to note, that if you loop through just one of the collections, it won't fail.

Thanks in advance!






[DC-502] sometimes not all the constraints are created for a many to many relation Created: 15/Feb/10  Updated: 14/Jun/10

Status: Open
Project: Doctrine 1
Component/s: Import/Export, Relations
Affects Version/s: 1.2.0-ALPHA1, 1.2.0-ALPHA2, 1.2.0-ALPHA3, 1.2.0-BETA1, 1.2.0-BETA2, 1.2.0-BETA3, 1.2.0-RC1, 1.2.0, 1.2.1, 1.2.2
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Papp Richard Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 1
Labels: None
Environment:

i tried both under linux / win; with doctrine 1.1 / 1.2.1
tried with sandbox / direct creating "bootstrap" => same results...



 Description   

it seems that the naming is important:

in a User, Group, UserGroup relation (where the UserGroup defines the many to many relation for User & Group) the constraints are defined well

but if the tables are Order, Service, OrderService it doesn't work => just one constraint is created... please find my example:

schema.yml
Order:
  tableName:          orders
  columns:
    name:             string(50)
  relations:
    Services:
      class:          Service
      local:          order_id
      foreign:        service_id
      refClass:       OrderService

Service:
  actAs:
    Versionable:      ~
  columns:
    name:             string(50)
  relations:
    Orders:
      class:          Order
      local:          service_id
      foreign:        order_id
      refClass:       OrderService

# WTF: it takes alphbetically the constraints building  !?
# if I used ZorderService instead of OrderService, Z is after S (O is before S) the constraints are defined fine!
OrderService:
  columns:
    order_id:         { type: integer, primary: true }
    service_id:       { type: integer, primary: true }

==> the generated SQL

sql
CREATE TABLE orders (id BIGINT AUTO_INCREMENT, name VARCHAR(50), PRIMARY KEY(id)) ENGINE = INNODB;
CREATE TABLE order_service (order_id BIGINT, service_id BIGINT, version BIGINT, PRIMARY KEY(order_id, service_id, 
        version)) ENGINE = INNODB;
CREATE TABLE service_version (id BIGINT, name VARCHAR(50), version BIGINT, PRIMARY KEY(id, version)) ENGINE = 
        INNODB;
CREATE TABLE service (id BIGINT AUTO_INCREMENT, name VARCHAR(50), version BIGINT, PRIMARY KEY(id)) ENGINE = 
        INNODB;
ALTER TABLE order_service ADD CONSTRAINT order_service_order_id_orders_id FOREIGN KEY (order_id) REFERENCES 
        orders(id);
ALTER TABLE service_version ADD CONSTRAINT service_version_id_service_id FOREIGN KEY (id) REFERENCES service(id) 
        ON UPDATE CASCADE ON DELETE CASCADE;

=> as you can see for TABLE order_service just one constraint is defined (order_service_order_id_orders_id) the other one (order_service_service_id_service_id) is missing !!!

However if i change the names for tables (actually i think alphabetically order) and use ZorderService instead of OrderService (lik UserGroup for User & Group) the two constraints are created!

This also affects the "getRelations()" when i tried to write a behavior (it gives back just one relation):

  foreach ($event->getInvoker()->getTable()->getRelations() as $relation)

ps:
also the same bug reported on the list: http://groups.google.com/group/doctrine-user/browse_thread/thread/ad48db71b71e043b

(edit G.X: split too long lines in SQL code)



 Comments   
Comment by Piotr Karaś [ 20/Apr/10 ]

I seem to have a very similar issue. It is really annoying because no error feedback is given at any point...
In my case, one out of three many-to-many relations actually has its constraints created, the other two not.
However, if I take the file date/sql/schema.sql (I am working with Symfony 1.4.4) and run as an SQL query directly with my database, the constraints are created properly!

So, with symfony, if I go:
$ symfony14 doctrine:build-model
$ symfony14 doctrine:build-sql
$ symfony14 doctrine:insert-sql
The model gets generated, the database gets generated, but several many-to-many constrains are missing.

Then if I go:
$ symfony14 doctrine:build-model
$ symfony14 doctrine:build-sql
$ mysql -u user -p database < date/sql/schema.sql
The model gets generated, the database gets generated, and the constraints are in place.

Hope this helps to have the problem fixed.

Cheers,
Piotrek

Comment by Guilliam X [ 11/Jun/10 ]

I do confirm this "alphabetical-order exporting" problem! (in 1.2 svn revision 7676)
(see also #DC-655)

*Edit:* I have gone closer through the functions calls and used a debugger, and the problem is actually logical;
it happens whenever a refClass of a many-to-many relation is parsed (and exported) before one or both of the linked classes.

Let's take this schema (YAML is shorter, anyways the generated PHP models are not bugged):

schema.yml
---
LinkTable:
  columns:
    table1_id:
      primary: true
      type:    integer
    table2_id:
      primary: true
      type:    integer
Table1:
  relations:
    Table2:
      refClass: LinkTable
      local:    table1_id
      foreign:  table2_id
Table2:
  relations:
    Table1:
      refClass: LinkTable
      local:    table2_id
      foreign:  table1_id

Now if you call Doctrine_Core::createTablesFromModels() or Doctrine_Core::generateSqlFromModels(), consequent call to Doctrine_Export::exportSortedClassesSql() does a loop and calls exportClassesSql() for each model in alphabetical order; once a table has been exported, subsequent bindings of pending relations won't be "retro-parsed" for the export.

I tried to compact the calls chain:

php
/* IN CLASS Doctrine_Export (or child (connection export)) */

$this->exportSortedClassesSql($classes)
{
    FOREACH ($classes as $class) {
        $connection = Doctrine_Manager::getInstance()->getConnectionForComponent($class);
        //...
        $sql =
        $connection->export->exportClassesSql($models = array($class))
        {
            FOREACH ($models as $name) {
                $record = new $name();
                $table = $record->getTable();
                //...
                $data = $table->getExportableFormat()
                {
                    /* IN CLASS Doctrine_Table (or child) */
                    
                    //...
                    $this->_parser->getRelations()
                    {
                        /* IN CLASS Doctrine_Relation_Parser (or child) */
                        
                        FOREACH ($this->_pending as $alias => $v) {
                            $this->getRelation($alias)
                            {
                                //...
                                /*
                                 * In the case of an "association relation" through a refTable:
                                 *   binds a *pending* (simple foreign key) relation to the refTable parser,
                                 *   binds a *pending* (simple foreign key) relation to itself,
                                 *   and "finalizes" (adds to $this->_relations) its association relation
                                 */
                            }
                        }
                    }
                    //...
                }
            }
        }
    }
}

So, with our example schema,

  1. LinkTable is exported with no constraints (because has no relations at this time);
  2. Table1 gets parsed, which finalizes the pending relation with Table2 (binded when loaded), binds to itself a pending relation with LinkTable, and binds to LinkTable parser the first pending relation (with Table1); Table1 is then exported whilst it still has a pending relation;
  3. Table2 gets parsed and exported the same way.

So now we have 2 problems:

  • each table has been exported immediately after its parsing, i.e. in an incomplete state (this is the present issue)
  • even after the whole relations parsing loop, LinkTable has still 2 pending relations, and each of both other tables has one "final" and one pending (but maybe it is supposed to be so...)

Note that a second call to Doctrine_Core::generateSqlFromModels() just after the first one, will parse all models one more time and thus finalize those pending relations, generating all constraints (also will subsequent calls).

For now I don't have a fix but I think we could consider:

  • loop twice in Doctrine_Export::exportSortedClassesSql() and exportClassesSql(), and construct SQL queries only the 2nd time (but... hum...)
  • improve Doctrine_Relation_Parser? maybe explicitly call getRelations() after each bind() (in the getRelation() function)...

Anyway it seems clear that export shouldn't be done before all tables have been parsed.

G.X

Comment by Guilliam X [ 12/Jun/10 ]

I still have no fix but in the waiting we can still discuss some "user-side" work-arounds (that don't need modifying Doctrine source code)...
Here is what crosses my mind first:

  • (in the PHP working code) do a first "dummy" call to
    $conn->export->exportClassesSql(Doctrine_Core::loadModels('models'))

    just to ensure all relations are bound, then a "real" call to Doctrine_Core::createTablesFromModels('models') which will export all constraints well

  • (in the schema) rename LinkTable to something like ZzLinkTable so that it is exported last
  • "explicitize" the two (one-to-many) foreign key relations in LinkTable by completing the schema as follows:
    schema.yml
    ---
    LinkTable:
      columns:
        table1_id:
          primary: true
          type:    integer
        table2_id:
          primary: true
          type:    integer
    #(added)
      relations:
        Table1:
          local:   table1_id
          foreign: id
        Table2:
          local:   table2_id
          foreign: id
    #(/added)
    Table1:
      relations:
        Table2:
          refClass: LinkTable
          local:    table1_id
          foreign:  table2_id
    Table2:
      relations:
        Table1:
          refClass: LinkTable
          local:    table2_id
          foreign:  table1_id
    

    (I think this one would also "solve" the behavior problem of Papp Richard)

But I'm not that happy with the idea of choosing one of these "hacks" if I had to, I would use this last one but (unless you use some "onDelete: CASCADE" or so) it looks like unnecessary duplication...
Someone, any other idea? ^^

G.X

(edit: typo fix)

Comment by Guilliam X [ 13/Jun/10 ]

We can try another approach too: let's say that our generated PHP models classes are incomplete.

Indeed, for a simple foreign key relation (i.e. o2o and o2m / m2o), we can define it only once on the owning side in the YAML file, and the schema importer will generate complete PHP classes, with the "hasOne" on the owning side and the auto-completed "hasMany" on the opposite side. E.g:

YAML schema
Phonenumber:
  columns:
    user_id: integer
  relations:
    User: {local: user_id, foreign: id}
User:
# we don't precise the opposite relation here

will generate the following classes (simplified a bit):

PHP models (1)
// models/Phonenumber.php
class Phonenumber extends Doctrine_Record
{
    public function setTableDefinition() {
        $this->hasColumn('user_id', 'integer');
    }

    public function setUp() {
        $this->hasOne('User', array('local'   => 'user_id',
                                    'foreign' => 'id'));
    }
}

// models/User.php
class User extends Doctrine_Record
{
    public function setTableDefinition() {
    }

    public function setUp() {
        // this was auto-added during the schema import:
        $this->hasMany('Phonenumber', array('local'   => 'id',
                                            'foreign' => 'user_id'));
    }
}

and this will work well.
BUT, now if we remove the auto-added hasMany() in User.php, then run the following (which worked well before our manual modification):

test.php
require_once 'bootstrap.php';

$user = new User();
Doctrine_Core::dump($user->Phonenumber);

we get some Fatal error: Uncaught exception 'Doctrine_Record_UnknownPropertyException' with message 'Unknown record property / related component "Phonenumber" on "User"', which is supposed to occur. Indeed, how could Doctrine know that a User has a "link" with Phonenumber? It would be only possible by parsing the relations of all the (loaded) models first...

So we can say that YAML schema files can be incomplete whereas PHP models classes MUST be COMPLETE.

Now, considering it is not to change, why not apply this "principle" to (m2m) association relations?
i.e., Doctrine documentation could warn that, if you want to have all constraints properly exported (like in the present issue) and/or use relations from an association class (having $link instance of LinkTable, you want to use $link->Table1, not just $link->table1_id), then you MUST complete your PHP models with the FK relations, like this:

PHP models (2)
// models/LinkTable.php
class LinkTable extends Doctrine_Record
{
    public function setTableDefinition() {
        $this->hasColumn('table1_id', 'integer', null, array(
                'primary' => true));
        $this->hasColumn('table2_id', 'integer', null, array(
                'primary' => true));
    }

    public function setUp() {
        // ADD:
        $this->hasOne('Table1', array('local'   => 'table1_id',
                                      'foreign' => 'id'));
        $this->hasOne('Table2', array('local'   => 'table2_id',
                                      'foreign' => 'id'));
    }
}

// models/Table1.php
class Table1 extends Doctrine_Record
{
    public function setTableDefinition() {
    }

    public function setUp() {
        $this->hasMany('Table2', array('refClass' => 'LinkTable',
                                       'local'    => 'table1_id',
                                       'foreign'  => 'table2_id'));
        // add too?:
        $this->hasMany('LinkTable', array('local'    => 'id',
                                          'foreign'  => 'table1_id'));
    }
}

// models/Table2.php
class Table2 extends Doctrine_Record
{
    public function setTableDefinition() {
    }

    public function setUp() {
        $this->hasMany('Table1', array('refClass' => 'LinkTable',
                                       'local'    => 'table2_id',
                                       'foreign'  => 'table1_id'));
        // add too?:
        $this->hasMany('LinkTable', array('local'    => 'id',
                                          'foreign'  => 'table2_id'));
    }
}

After all, these additional relations are bound internally (if not already defined) when exporting tables to DB...

We also said that the YAML can be incomplete, but for now the short schema.yml I took as an example in my first comment results in PHP classes without those (2+1+1) adds.

So to allow YAML to be incomplete even for m2m relations, Doctrine_Import_Schema#_buildRelationships() would need some "improvement" so that it creates the many-to-one relation for each many-to-many relation (and the opposite one-to-many relation, on the association class side i.e. the owning side, would be auto-completed afterwards). However, a m2m relation is allowed to be defined on one single end, thus may be created one the other end only when _autoCompleteOppositeRelations() is called, i.e. after _buildRelationships() has looped over all the existing relations. So Doctrine_Import_Schema#_autoCompleteOppositeRelations() would need the same kind of improvement...

In fact I'm not sure of what is a "well defined" model as soon as it uses refClass, the documentation sometimes uses contradictory examples...

Sorry I was so verbose!
Thank you for developing Doctrine





[DC-447] Problem linking many-to-many relationships Created: 25/Jan/10  Updated: 25/Jan/10

Status: Open
Project: Doctrine 1
Component/s: Relations
Affects Version/s: 1.2.1
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Rytis Daugirdas Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Windows Vista x86 SP2, PHP 5.2.x



 Description   

Hello,

Here's a small usage example of linking many-to-many relationships. The group is not linked with the user after calling link() as can be seen by comparing the group ids before and after the call.

schema.yml
User:
  tableName: users
  columns:
    username:      { type: string(255), notnull: true }
    email:         { type: string(255), notnull: true }
  indexes:
    username_idx:
      fields: [username]
      type:   unique
    email_idx:
      fields: [email]
      type:   unique
  actAs: [Timestampable]
  relations:
    groups:
      class:    Group
      alias:    Groups
      refClass: UserGroupRelation

Group:
  tableName: groups
  columns:
    name: { type: string(255), notnull: true }
  actAs: [Timestampable, NestedSet]
  relations:
    users:
      class:    User
      alias:    Users
      refClass: UserGroupRelation

UserGroupRelation:
  tableName: user_group_relations
  columns:
    user_id:  { type: integer, notnull: true, primary: true }
    group_id: { type: integer, notnull: true, primary: true }
  relations:
    Group:
      class:        Group
      foreignAlias: UserGroupRelations
      onDelete:     CASCADE
    User:
      class:        User
      foreignAlias: UserGroupRelations
      onDelete:     CASCADE
test.php
$u = Doctrine_Core::getTable('User')->findOneByUsername('james');
$g = Doctrine_Core::getTable('Group')->findOneByName('group');
var_dump($g['id']);
$current = array();
foreach ($u['UserGroupRelations'] as $r) {
    $current[] = $r['group_id'];
}
var_dump($current);
$u->link('Groups', array($g['id']), true);
$u = Doctrine_Core::getTable('User')->findOneByUsername('james');
$current = array();
foreach ($u['UserGroupRelations'] as $r) {
    $current[] = $r['group_id'];
}
var_dump($current);
Output
string(1) "2"
array(3) {
  [0]=>
  string(1) "1"
  [1]=>
  string(1) "5"
  [2]=>
  string(1) "6"
}
array(3) {
  [0]=>
  string(1) "1"
  [1]=>
  string(1) "5"
  [2]=>
  string(1) "6"
}





[DC-443] Incorrect insert order in i18n entities Created: 22/Jan/10  Updated: 22/Jan/10

Status: Open
Project: Doctrine 1
Component/s: I18n, Relations
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Rodrigo Borrego Bernabé Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Linux (2.6.21 kernel)
Apache/2.2.6
PHP 5.2.6
symfony version 1.4.1
doctrine 1.2


Attachments: File i18nrelation_problem.tgz    

 Description   

If the schema has an entity MyMain with all its fields i18n and an entity MySecondary related to MyMain and you try to create a new MySecondary item using Symfony forms you get an error.

I think the error is doctrine and in i18n because if you remove a field from the i18n behavior (fields: [a,b,c,d], for example) all works ok.
I've included a symfony project to help developpers replicate the error.

My Schema

 
MyMain:
  actAs:
    I18n:
      fields: [a,b,c,d, e]
  columns:
    a:  { type: string(255), notnull: true }
    b:  { type: string(255), notnull: true }
    c:  string
    d:  string
    e:  string

MySecondary:
  columns:
    my_main_id:  integer
    a:        string(255)
    b:        string(255)
  relations:
    MyMain:
      local: my_main_id
      foreign: id
      foreignType: one
      cascade: [delete]

And the form code

class MyMainForm extends BaseMyMainForm
{
  public function configure()
  {
    $this->embedI18n(array('en', 'es'));
  }
}

class MySecondaryForm extends BaseMySecondaryForm
{
  public function configure()
  {
    $this->widgetSchema['my_main_id'] = new sfWidgetFormInputHidden();
    $this->embedRelation('MyMain as main_subform');
  }
}

And last the queries (and its order when you get the error)

INSERT INTO my_secondary (my_main_id, a, b) VALUES (?, ?, ?) - (, my_secondary[a], my_secondary[b])
INSERT INTO my_main_translation (id, lang, a, b, c, d, e) VALUES (?, ?, ?, ?, ?, ?, ?) - 
  (, en, my_secondary[main_subform][en][a], my_secondary[main_subform][en][b], my_secondary[main_subform][en][c], 
   my_secondary[main_subform][en][d], my_secondary[main_subform][en][e])
Error Doctrine_Connection_Mysql_Exception	SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'id' cannot be null 





[DC-442] Refined definition of relations regarding "copy()" cloning behaviour Created: 21/Jan/10  Updated: 10/Feb/10

Status: Open
Project: Doctrine 1
Component/s: Relations
Affects Version/s: 1.2.0
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: Raphael Schumacher Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Doctrine's cloning feature is based on the Doctrine_Record::copy($deep = false) method, while the $deep param says whether to clone the related objects as well, or not.

However, considering the perspective of the application logic, the functional need can also be stated as: "I wish you to clone yourself, expecting you to know yourself which related objects you need to clone as well, or even to de-reference, or whatever is needed (e.g. to remove the relation)."
For this, the $deep argument is somehow inaccurate, as it does not take into consideration the different meanings of the relations:

  • some relations (namely aggregations in UML terminology) need that the cloned object shall still refer to the same object (like referenced by the cloned object)
  • some relations (namely compositions) need to clone the related objects as well, as the latter are owned by the main object.

Practical example: when cloning an invoice (Doctrine_Record), application logic expects that its invoice line items be cloned as well (compositions), but not the reference to the customer (cloning my customers this way will not increase my business .

Thus it would be great if there were a means to specify the needed behaviour in the schema.yml etc.
Thinkable approach: extend the "application-level cascade" feature of Doctrine by adding a "clone" or "copy" parameters. Then the copy() method in Doctrine_Record will know which related objects to clone as well, or not, or to clear (null). I guess it's quite analogous to the "delete" cascade stuff.

So far my proposal. In case it will find support, I will then be happy to provide an implementation proposal.






[DC-436]  Change in 1.2 to Doctrine_Event::skipOperation() functionality Created: 18/Jan/10  Updated: 10/Feb/10

Status: Open
Project: Doctrine 1
Component/s: Relations
Affects Version/s: 1.2.1
Fix Version/s: 1.1.6

Type: Bug Priority: Major
Reporter: Cameron Ross Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Debian



 Description   

I have been using Doctrine 1.1.6.

I have two related models, which are always saved together. In my application, save is called on class A and that save cascades to class B. I have a save listener which in some cases can intercept class A's save operation and call Doctrine_Event::skipOperation() to prevent class A from being persistently saved. However, in such cases, class B is still saved - the skipOperation() does not skip the entire operation, just class A's save operation, allowing subsequent operations to occur as normal.

This is the desired functionality and has been working fine. However, I have just upgraded to 1.2.1. only to find that something has changed, causing the skipOperation() to skip the entire operation, therefore not saving class B when class A's listener interferes.

I presume this is a bug. If not, what precisely has changed with skipOperation(), and how can I keep the traditional functionality?






[DC-362] Doctrine fails to create correct table structure if model is named "User" Created: 16/Dec/09  Updated: 08/Jan/10

Status: Open
Project: Doctrine 1
Component/s: Behaviors, Query, Relations
Affects Version/s: 1.2.0-RC1
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Michael Henriksen Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 1
Labels: None
Environment:

Mac OS X 10.6.2 (10C540) (Snow Leopard) with MAMP 1.8 bundle:
PHP Version: 5.2.10,
MySQL Version: 5.1.37



 Description   

When building models and database structure from YAML schema, Doctrine ignores the behaviors and relations on models if it is named "User":

...

User:  
  actAs:
    Timestampable:
    Sluggable:
      unique: true
      fields: username
      canUpdate: true
  columns:
    id:
      type: integer(4)
      primary: true
      autoincrement: true
    company_id
      type: integer(4)
    timezone_id:
      type: integer(1)
    role_id:
      type: integer(1)
    email:
      type: string(255)
    username:
      type: string(255)
      unique: true
    password:
      type: string(40)
    firstname:
      type: string(255)
    lastname:
      type: string(255)
    last_login:
      type: datetime
  relations:
    Company:
      local: company_id
      foreign: id
    Timezone:
      local: timezone_id
      foreign: id
    Role:
      local: role_id
      foreign: id

...

This creates the following table structure:

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `company_id` int(11) DEFAULT NULL,
  `timezone_id` tinyint(4) DEFAULT NULL,
  `role_id` tinyint(4) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  `username` varchar(255) DEFAULT NULL,
  `password` varchar(40) DEFAULT NULL,
  `firstname` varchar(255) DEFAULT NULL,
  `lastname` varchar(255) DEFAULT NULL,
  `last_login` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

The table structure is both missing foreign key constraints to Company, Timezone and Role. It is also missing columns updated_at and created_at for Timestampable behavior. The slug column for Sluggable behavior is missing, as well.

When looking at the BaseUser::setUp() method it looks as it is supposed to:

class BaseUser extends Doctrine_Record
{

    ....

    public function setUp()
    {
        parent::setUp();
        $this->hasOne('Company', array(
             'local' => 'company_id',
             'foreign' => 'id'));

        $this->hasOne('Timezone', array(
             'local' => 'timezone_id',
             'foreign' => 'id'));

        $this->hasOne('Role', array(
             'local' => 'role_id',
             'foreign' => 'id'));

        $timestampable0 = new Doctrine_Template_Timestampable();
        $sluggable0 = new Doctrine_Template_Sluggable(array(
             'unique' => true,
             'fields' => 'username',
             'canUpdate' => true,
        ));
        $this->actAs($timestampable0);
        $this->actAs($sluggable0);
    }

    ....

}

So the only area where it goes wrong, is when generating the queries for creating the model tables. I don't know if the same problem appears with other model names, but it doesn't like models named "User".

If I rename the model to "Person" and rebuild, it all works perfectly as it should.



 Comments   
Comment by Michael Henriksen [ 16/Dec/09 ]

Forgot to mention, that it works perfectly when renaming model to something else than "User"

Comment by Sander [ 08/Jan/10 ]

Have the same problem in 1.2.1 at PostgreSQL 8.4





[DC-329] Problem saving Self Referencing (Nest Relations) Created: 05/Dec/09  Updated: 03/Jun/11

Status: Open
Project: Doctrine 1
Component/s: Relations
Affects Version/s: 1.2.0
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Jaime Suez Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 14
Labels: None
Environment:

Mac OSX 10.5, Symfony 1.4 and MAMP


Attachments: Zip Archive h2aEqualable.zip     PNG File saving process.png     File schema.yml     File testEqualNestRelationsTest.php     File testNestedEqualRelationWithObjectsTest.php    

 Description   

There is a problem when you save Many to Many Self Referencing (Nest Relations).

I used the same example that it's used on Doctrine 1.2 Self Referencing (Nest Relations) Documentation:

My Schema:

User:
columns:
name:

Unknown macro: { type}

relations:
Parents:
class: User
local: child_id
foreign: parent_id
refClass: UserReference
foreignAlias: Children

UserReference:
columns:
parent_id:
type: integer
primary: true
child_id:
type: integer
primary: true

Fixtures:

User:
james:
name: James
alexander:
name: Alexander
david:
name: David

The problem happens with the Children. The first time I assigned children and saved the User, there is no problem; but when I saved the User again (without any change on him) the values in the UserReference? table changes: the "parent_id" takes the value of the "child_id".

I test it with Sf 1.4 and with Sf 1.3 stable versions, and I've got the same error.

If it not clear to understand what I'm saying, I put a "very ilustrative" image about the form and how change the values of the UserReference? table. Please see it, because it would be very usefull for understanding (explains better than my terrible English)

Thanks for all your work!

P. D.

I forgot to to say that watching the stack trace I think that the problem is in:

symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/UnitOfWork.php

In the line 429:

public function saveAssociations(Doctrine_Record $record)

I would like to help more, but I couldn't figure out how this function works.



 Comments   
Comment by Jaime Suez [ 07/Dec/09 ]

This picture explains the error that it's done when you do an insert and then you save it again.

Comment by Jonathan H. Wage [ 07/Dec/09 ]

Can you provide a failing Doctrine test case? This may be a problem with Symfony and not Doctrine.

Comment by Jaime Suez [ 08/Dec/09 ]

First I published this bug on Symfony, because I thought that was a problem with Symfony, but you set it as invalid because it's belong to Doctrine.

This is the ticket on symfony:
http://trac.symfony-project.org/ticket/7690

I could do the Doctrine test case, but in one more mounth, because tomorrow I go out for vacations.
When I come back I'll do them.

Comment by psylosss [ 20/Dec/09 ]

Yes, I have got the same problem. During hours of debugging and exploring Doctrine's code, I found that problem localized in Hydrator component. I cannot digg deeper, so I ask you to fix it very much

Comment by Filippo De Santis [ 26/Dec/09 ]

Hi,
I had this problem in the 1.0 version of doctrine as well.
Using symfony, I upgraded to symfony 1.3 and doctrine 1.2 and I've found the same problem.

Attached to this comment you can find the files containing the schema I used (it is the same as that describe on this ticket but with a different class naming), and 2 unit tests. One using the symfony form and one using directly the doctrine objects. They report the bug discussed on this ticket and show another bug saving objects that already have one ore more relations.

As fixtures I used a fixtures.yml file containing:

Issue:
<?php for ($i = 1; $i <= 30; $i++): ?>
Issue_<?php echo $i; ?>:
title: "new issue <?php echo $i ?>"
<?php endfor; ?>

The following are the tests results:

– testEqualNestRelationsTest.php (using the forms) –

> First form for first issue: creation of the relation "issue 1 -> issue 2"
ok 1 - the edit form for issue 1 is valid
ok 2 - form1 saved
ok 3 - issue 1 is related with another issue
ok 4 - issue 1 is really related with issue 2

> Second form for first issue: saving the relation between "issue 1" and "issue 2" from "issue 2"'s form
ok 5 - the edit form for issue 2 is valid
ok 6 - form2 saved
not ok 7 - issue 2 is related with another issue ******** this is the problem reported on this ticket ********

  1. Failed test (./test/unit/testEqualNestRelationsTest.php at line 57)
  2. got: 0
  3. expected: 1
    not ok 8 - issue 2 is really related with issue 1
  4. Failed test (./test/unit/testEqualNestRelationsTest.php at line 58)
  5. got: NULL
  6. expected: 1

ok 9 - issue 1 is related with another issue
not ok 10 - issue 1 is really related with issue 2 ******** this is the problem reported on this ticket ********

  1. Failed test (./test/unit/testEqualNestRelationsTest.php at line 63)
  2. got: '1'
  3. expected: 2
    > Checking the relation table IssueReference ...
    ok 11 - There is only one relation saved on IssueReference
    ok 12 - 1 is the issue1 field of the relation
    not ok 13 - 2 is the issue2 field of the relation ******** this is the problem reported on this ticket ********
  4. Failed test (./test/unit/testEqualNestRelationsTest.php at line 71)
  5. got: '1'
  6. expected: '2'

> multi selection proof
ok 14 - the edit form for issue 1 is valid
ok 15 - form1 saved
ok 16 - the edit form for issue 2 is valid

                • this is the other bug I've found ********
                  not ok 17 - form2 exception catched : SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1-1' for key 1
  1. Failed test (./test/unit/testEqualNestRelationsTest.php at line 114)

– testNestedEqualRelationWithObjectsTest.php (test using the "doctrine" objects ) –

> Saving relation directly from the objects and not using the forms...
ok 1 - issue1 saved
> checking issue1 relations
ok 2 - issue 1 is related with another issue
ok 3 - issue 1 is really related with issue 2

> checking "reverse" relation on issue2
ok 4 - issue 2 is related with another issue
ok 5 - issue 2 is really related with issue 1

> adding a relation issue2->issue1 directly
ok 6 - issue2 saved

> checking issue2 relations
not ok 7 - issue 2 is related with another issue ******** this is the problem reported on this ticket ********

  1. Failed test (./test/unit/testNestedEqualRelationWithObjectsTest.php at line 56)
  2. got: 0
  3. expected: 1
    not ok 8 - issue 2 is really related with issue 1
  4. Failed test (./test/unit/testNestedEqualRelationWithObjectsTest.php at line 57)
  5. got: NULL
  6. expected: 1

> checking issue1 relations
ok 9 - issue 1 is related with another issue
not ok 10 - issue 1 is really related with issue 2 ******** this is the problem reported on this ticket ********

  1. Failed test (./test/unit/testNestedEqualRelationWithObjectsTest.php at line 63)
  2. got: '1'
  3. expected: 2

> Checking the relation table IssueReference ...
ok 11 - There is only one relation saved on IssueReference
ok 12 - 1 is the issue1 field of the relation
not ok 13 - 2 is the issue2 field of the relation

  1. Failed test (./test/unit/testNestedEqualRelationWithObjectsTest.php at line 71)
  2. got: '1'
  3. expected: '2'

> object multi adding relation proof
ok 14 - issue1 saved

                • this is the other bug I've found ********
                  not ok 15 - issue2 exception catched : SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1-1' for key 1
  1. Failed test (./test/unit/testNestedEqualRelationWithObjectsTest.php at line 112)
Comment by Jaime Suez [ 13/Jan/10 ]

With the test provided by Filippo De Santis is any other thing needed??

I still on vacations untill 3 of febrary, so then I could do any other thing needed.

Comment by Jaime Suez [ 01/Feb/10 ]

The necessary test have to be how are illustrated in this link???

http://www.doctrine-project.org/documentation/manual/1_2/en/unit-testing

Comment by Alexander Sweis [ 09/Feb/10 ]

What has happen with this bug?? I also have the same problem...

Comment by Jonathan H. Wage [ 02/Mar/10 ]

Hi, yes. We still need a unit test case like described here: http://www.doctrine-project.org/documentation/manual/1_2/en/unit-testing

So we can run it with all the other tests and reproduce the issue in Doctrine by itself. Not in Symfony.

Thanks, Jon

Comment by psylosss [ 02/Mar/10 ]

Jon, here is the test for this bug: http://gist.github.com/319856

Please, fix it.. my work has been stopped cause of it

Comment by Jaime Suez [ 15/Mar/10 ]

Yes... please fix it... I'm also stuck in my work since a lot of time that the bug it's open.

Thanks

Comment by Nil Null [ 15/Mar/10 ]

I'm affected with this bug as well, fortunately, I found a way to get over it, it's ugly and innefficient, but at least my work isn't stopped due to this bug. I'll try to explain what I did commenting here later. Anyway, I really need this bug fixed too before I can start betatesting my app.
Thanks!

P.D: I'm using Doctrine 1.2.1.

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

I am trying to understand the issue but it just doesn't make much sense to me yet. The test case is wrong because you are dealing with instances of objects that have previously loaded references, then you try and re-fetch the same object instance. If you do $user1->free(true); then re-fetch the object the test passes as expected. So, I don't really have a proper failing test case still that actually exposes the problem. I'll keep playing around see if I can understand. let me know if anyone else has more information or a patch to test.

Thanks, Jon

Comment by Filippo De Santis [ 16/Mar/10 ]

Hi Jonathan,
This is the "translated" version of my unit test for symfony in "doctrine unit test"

http://github.com/ideato/phpcollab3/blob/phpcollabsf13/test/doctrine_unit_test/DC329TestCase.php

The first test is to show the error "SQLSTATE[23000]: Integrity constraint violation: 19 columns issue1, issue2 are not unique".
The second one is to show the fact that the relation are saved with wrong data.

Sorry for the late translation.

Filippo

Comment by Hendri Kurniawan [ 16/Mar/10 ]

Hi Jonathan,

It seems that the problem is caused by Doctrine_Collection::add() method line 456 (I could be totally wrong).

if (isset($this->referenceField)) {
    $value = $this->reference->get($this->relation->getLocalFieldName());
    if ($value !== null) {
        $record->set($this->referenceField, $value, false);
    } else {
        $record->set($this->referenceField, $this->reference, false);
    }
...

What is trying to do is to set the reference field value to the reference value that it's linked to.

This only happens when you try to fetch record from the "children".

Consider the following:

Employees:
  tableName: employees
  columns:
    id:
      type: integer(4)
      primary: true
      autoincrement: true
    name:
      type: string(100)
  relations:
    managing:
      class: Employees
      type: many
      local: manager_id
      foreign: employee_id
      foreignAlias: managedBy
      refClass: EmployeeManager

EmployeeManager:
...

Code:

// ----- The following will not give you any issues
  $manager = Doctrine::getTable('Issue')->findOneBy('id', '1'); // This is a manager
  foreach ($manager->managing as $employee) {
    ....
  }

  // This will not save anything
  $manager->save();
// -----

// ----- The following will
  $employee = Doctrine::getTable('Issue')->findOneBy('id', '2'); // This is an employee
  foreach ($employee->managedBy as $manager) {
    ...
  }

  // This will save the wrong data to the "EmployeeManager" table
  // because the code from Doctrine_Collection is overwriting "EmployeeManager" records
  // When they were being added to the collection by the Hydrator.
  $employee->save();
// -----

Debug backtrace when this happens:

string(100) "File: /Data/app/onlinevw-drupalvividwireless/libs/external-doctrine1/Doctrine/Record.php @ line 1432"
string(103) "File: /Data/app/onlinevw-drupalvividwireless/libs/external-doctrine1/Doctrine/Collection.php @ line 461"
string(99) "File: /Data/app/onlinevw-drupalvividwireless/libs/external-doctrine1/Doctrine/Access.php @ line 131"
string(107) "File: /Data/app/onlinevw-drupalvividwireless/libs/external-doctrine1/Doctrine/Hydrator/Graph.php @ line 229"
string(101) "File: /Data/app/onlinevw-drupalvividwireless/libs/external-doctrine1/Doctrine/Hydrator.php @ line 137"
string(108) "File: /Data/app/onlinevw-drupalvividwireless/libs/external-doctrine1/Doctrine/Query/Abstract.php @ line 1036"
string(105) "File: /Data/app/onlinevw-drupalvividwireless/libs/external-doctrine1/Doctrine/Relation/Nest.php @ line 84"
string(100) "File: /Data/app/onlinevw-drupalvividwireless/libs/external-doctrine1/Doctrine/Record.php @ line 1362"
string(100) "File: /Data/app/onlinevw-drupalvividwireless/libs/external-doctrine1/Doctrine/Record.php @ line 1333"

Comment by Pierrot Evrard [ 19/Mar/10 ]

Hi all,

For people who are looking for a workaround, I've found one that work for me.

Get the doctrine extension h2aEqualable (h2aEqualable.zip), register it as a doctrine extension (see http://www.doctrine-project.org/documentation/manual/1_2/0_11/extensions) and make your refClass of every equal nest relation acting as h2aEqualable.

In your PHP script :
{{
Doctrine::setExtensionsPath( 'path/to/unzip/place' );
Doctrine_Manager::getInstance()->registerExtension( 'h2aEqualable' );
}}

In your YAML schema :
{{
MyEqualNestRelationRefClassModel:
actAs:
h2aEqualable:
fields: [id_1,id_2]
}}

As I've said before, it works for me, so let me know if it solve your issues too...

Comment by Pierre Guéguin [ 18/Jun/10 ]

I have the very same issue with non equal nest relations.
It is stopping my project

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '87-87' for key 'PRIMARY'

execute : UPDATE cop_job_stream_successor SET job_stream_destination_id = ?, updated_at = ? WHERE job_stream_source_id = ? AND job_stream_destination_id = ? - (87, 2010-06-18 18:55:32, 87, 94)

CopJobStream:
columns:
name:
type: string(255)
notnull: false
....
relations:
SuccessorJobStreams:
class: CopJobStream
local: job_stream_source_id
foreign: job_stream_destination_id
refClass: CopJobStreamSuccessor
foreignAlias: PredecessorJobStreams
onDelete: CASCADE
onUpdate: CASCADE

CopJobStreamSuccessor:
columns:
job_stream_source_id:
type: integer
primary: true
job_stream_destination_id:
type: integer
primary: true
relations:
CopJobStream:
local: job_stream_source_id
foreignAlias: CopJobStreamSuccessors
onDelete: CASCADE
onUpdate: CASCADE

Comment by Pierre Guéguin [ 18/Jun/10 ]

It works anyway with above h2aEqualable extension

Comment by Daniel Reiche [ 26/Jan/11 ]

after stumbling into the same pit as everyone, i created a fresh report as DC-958. Later I found out that it has been reported before, so please mark DC-958 as duplicate of this. (or at least related, as I was using a Non-Equal Nested Set) also DC-952 refers to the same problem, but also with Non-Equal nestet sets.

My Case: Non-Equal-Nested-Set. Problems occur on saving Objects for 2nd or more time. Doctrine deletes all Child-Relations of the Object to be saved and updates Relations of the Childs to other Objects (other parents of the children objects) with references to the child itself!

the proposed h2aEqualable extension does prevent the wrong update statements but not the initial delete of the child-relations.

What exactly is missing on this bug to be fixed? It is now a year old, and clearly preventing people from using Self-Referencing relations with doctrine.

How can we help? More sample data, schema definitions, test cases?

Comment by Francesco Levorato [ 15/Feb/11 ]

Here is a better and simpler test case for the equal relation: https://gist.github.com/827414

There is clearly a memory problem here. I'll leave it up to Jonathan to decide whether it's a scenario which can be avoided in Doctrine itself or must be handled by Symfony (http://trac.symfony-project.org/ticket/9398).

In the Symfony context calls to refresh() might not be an option when modifying an object (aka saving a form).

Comment by Yitzchak Schaffer [ 17/Feb/11 ]

h2aEqualable seems to work for me.

Comment by Pavel Campr [ 02/Jun/11 ]

h2aEqualable works only partly for me (same as Daniel Reiche wrote).

I tried to identify the problem.

My usecase was:
1) I have an Article record in $article
2) I called $article->RelatedArticles->getPrimaryKeys() , where RelatedArticles is a name of my self reference
3) $article->save();

The problem originates from step 2), during hydratation process for related articles, which are added to a collection of related articles, in Collection->add() method (line 465) here:

if ($value !== null)

{ $record->set($this->referenceField, $value, false); }

else {

but, $this->referenceField contains wrong name of reference field. Self referenced model (Article) has two relations to the same class (one from "owning" side, second from "referencing" side). $this->referenceField in the collection is somewhere filled with the wrong relation name (not the"referencing" one, but the "owning" one).

When I save the $article, all referenced records are saved too and this is the problem, why the Doctrine tries to save corrupted data:

In my example, I have this data:

in Doctrine_Collection->add on line 457: $record) is a RelatedArticle (
article1 = string(1) "4"
article2 = string(1) "9"
)
in Doctrine_Collection->add on line 458: $this->referenceField) = string(19) "article1"
in Doctrine_Collection->add on line 459: $value) = string(1) "9"

BUT expected data is:

in Doctrine_Collection->add on line 458: $this->referenceField) = string(19) "article2"

This wrong behavior modified my RelatedArticle into this: RelatedArticle (
article1 = string(1) "9"
article2 = string(1) "9"
)

I have no idea how to fix it, but maybe someone can, I hope

(
my schema is:

Article
relations:
RelatedArticles:
class: Article
local: article1
foreign: article2
refClass: RelatedArticle
)

Maybe, when "refClassRelationAlias" option was invented to specifically point to a relation, instead of using "refClass", which can be used more times for one record and thus is not unambiguous, something for self referenced relations should be added as well. My "refClass: RelatedArticle" creates (probably) a relation from the foreign side too and Article contains two relations, which uses same refClass. Doctrine then doesn't know, which one should be used.

Comment by Pavel Campr [ 03/Jun/11 ]

Non-equal nest relations work properly, when refClassRelationAlias undocumented option is used, e.g.

Article:
...
relations:
RelatedArticles:
class: Article
local: article1
foreign: article2
refClass: RelatedArticle
refClassRelationAlias: RelatedArticleAlias

Anything can be used as a value for refClassRelationAlias.

Unfortunately, this doesn't fix equal nest relations.





[DC-290] Relations need alias Created: 25/Nov/09  Updated: 09/Jun/10

Status: Reopened
Project: Doctrine 1
Component/s: Relations
Affects Version/s: 1.2.0-RC1
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Christian Jaentsch Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None


 Description   

While implementing a Record_Template and manipulating a query by using the preDqlSelect Event, i got massive problems if the query was generated by a refresh() or refreshRelated() call. I found out that the issue appears because the query has no alias for the table then. This makes it hard to add forther (sub-)selects to the query via preDqlSelect, e.g.

$params = $event->getParams();
		$alias = $params['alias'];

                if(!$query->isSubquery() && $alias == $queryClone->getRootAlias()) {	
				
				
				$countQuery = '(SELECT COUNT('.$alias.'_tcount.uid) FROM '.$modelName.' '.$alias.'_tcount WHERE '.$alias.'.'.$groupId.'='.$alias.'_tcount.'.$groupId.') AS '.$this->_options['terminationCount'];
				
				$query->addSelect($countQuery);
			}

The issue is solved by adding an alias in the foreignKey and localKey relation types' fetchRelatedFor methods (at least that's sufficient for my issue, maybe there is a need to add similar lines to the other relation types).

Doctrine_Relation_ForeignKey (from line 60):

$alias = $this->getTable()->getComponentName().'_rel';
            	
                $dql  = 'FROM ' . $this->getTable()->getComponentName()
                      .' '.$alias. ' WHERE ' . $this->getCondition($alias) . $this->getOrderBy(null, false);

Doctrine_Relation_LocalKey (from line 58):

$alias = $this->getTable()->getComponentName().'_rel';
        	
            $dql  = 'FROM ' . $this->getTable()->getComponentName()
                 .' '.$alias. ' WHERE ' . $this->getCondition($alias) . $this->getOrderBy(null, false);


 Comments   
Comment by Jonathan H. Wage [ 30/Nov/09 ]

If no alias is explicitly defined, the alias is automatically set to the model name. So in your code change you changed it from "ModelName" to "ModelName_rel". If you had the following:

SELECT * FROM User

The alias would be "User" and it is the same as if you did:

SELECT * FROM User User
Comment by Christian Jaentsch [ 01/Dec/09 ]

unfortunately this does not solve my problem... i narrowed it down to be a problem with addPendingJoinCondition in such a case.

here is a short scenario of what i want to do...

$modelName = 'Exhibition';
$alias = "exhibitionalias";
$subAlias = 'exhibitionsub';
		
$query = Doctrine_Query::create()
->from($modelName.' '.$alias);
		
$subQuery .= 'SELECT '.$subAlias.'.id FROM '.$modelName.' '.$subAlias.' WHERE '.$subAlias.'.id = '.$alias.'.id';
$query->addPendingJoinCondition($alias, $alias.'.id IN ('.$subQuery.')');
		
$query->execute();

this works so far as the alias is different from the model name... but if i change

$alias = "Exhibition";

i get the exception

exception 'Doctrine_Exception' with message 'Couldn't find class exhibitionsub' in /var/www/erh_eeecore/core/lib/Doctrine/Doctrine/Table.php:299
Stack trace:
#0 /var/www/erh_eeecore/core/lib/Doctrine/Doctrine/Table.php(249): Doctrine_Table->initDefinition()
#1 /var/www/erh_eeecore/core/lib/Doctrine/Doctrine/Connection.php(1126): Doctrine_Table->__construct('exhibitionsub', Object(Doctrine_Connection_Mysql), true)
#2 /var/www/erh_eeecore/core/lib/Doctrine/Doctrine/Query.php(1924): Doctrine_Connection->getTable('exhibitionsub')
#3 /var/www/erh_eeecore/core/lib/Doctrine/Doctrine/Query.php(1722): Doctrine_Query->loadRoot('exhibitionsub', 'exhibitionsub')
#4 /var/www/erh_eeecore/core/lib/Doctrine/Doctrine/Query/Where.php(76): Doctrine_Query->load('exhibitionsub', false)
#5 /var/www/erh_eeecore/core/lib/Doctrine/Doctrine/Query/Condition.php(92): Doctrine_Query_Where->load('exhibitionsub.i...')
#6 /var/www/erh_eeecore/core/lib/Doctrine/Doctrine/Query/Abstract.php(2077): Doctrine_Query_Condition->parse('exhibitionsub.i...')
#7 /var/www/erh_eeecore/core/lib/Doctrine/Doctrine/Query.php(1156): Doctrine_Query_Abstract->_processDqlQueryPart('where', Array)
#8 /var/www/erh_eeecore/core/lib/Doctrine/Doctrine/Query.php(1122): Doctrine_Query->buildSqlQuery(false)
#9 /var/www/erh_eeecore/core/lib/Doctrine/Doctrine/Query/Abstract.php(1137): Doctrine_Query->getSqlQuery(Array, false)
#10 /var/www/erh_eeecore/core/lib/Doctrine/Doctrine/Query/Abstract.php(1106): Doctrine_Query_Abstract->_getDqlCallbackComponents(Array)
#11 /var/www/erh_eeecore/core/lib/Doctrine/Doctrine/Query.php(1143): Doctrine_Query_Abstract->_preQuery()
#12 /var/www/erh_eeecore/core/lib/Doctrine/Doctrine/Query.php(1122): Doctrine_Query->buildSqlQuery(true)
#13 /var/www/erh_eeecore/core/lib/Doctrine/Doctrine/Query/JoinCondition.php(87): Doctrine_Query->getSqlQuery()
#14 /var/www/erh_eeecore/core/lib/Doctrine/Doctrine/Query/Condition.php(92): Doctrine_Query_JoinCondition->load('Exhibition.id I...')
#15 /var/www/erh_eeecore/core/lib/Doctrine/Doctrine/Query.php(1089): Doctrine_Query_Condition->parse('Exhibition.id I...')
#16 /var/www/erh_eeecore/core/lib/Doctrine/Doctrine/Query.php(1013): Doctrine_Query->_processPendingJoinConditions('Exhibition')
#17 /var/www/erh_eeecore/core/lib/Doctrine/Doctrine/Query.php(1228): Doctrine_Query->_buildSqlFromPart()
#18 /var/www/erh_eeecore/core/lib/Doctrine/Doctrine/Query.php(1122): Doctrine_Query->buildSqlQuery(false)
#19 /var/www/erh_eeecore/core/lib/Doctrine/Doctrine/Query/Abstract.php(1137): Doctrine_Query->getSqlQuery(Array, false)
#20 /var/www/erh_eeecore/core/lib/Doctrine/Doctrine/Query/Abstract.php(1106): Doctrine_Query_Abstract->_getDqlCallbackComponents(Array)
#21 /var/www/erh_eeecore/core/lib/Doctrine/Doctrine/Query/Abstract.php(1001): Doctrine_Query_Abstract->_preQuery(Array)
#22 /var/www/erh_eeecore/app/modules/default/controllers/ExhibitionsController.php(75): Doctrine_Query_Abstract->execute()
Comment by Jonathan H. Wage [ 07/Dec/09 ]

Hmm. Christian, your issue doesn't seem at all related to the original issue. It seems like an entirely different problem, no?

Comment by Christian Jaentsch [ 08/Dec/09 ]

Well, I don't know where the reason for the problem is exactly... I just solved my problem by adding an alias to the foreignKey and localKey relations. The actual problem seems to be located in how the query is processed if the alias is equal to the name of the "from"-model. this causes problems while adding pending join conditions.

Comment by Jonathan H. Wage [ 08/Dec/09 ]

Ok, well what you described is totally un-related to this issue. If you have found a bug you can open another ticket with detailed information and a failing test case. Thanks, Jon

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

Can you show a patch with your changes?

Comment by Christian Jaentsch [ 09/Jun/10 ]

My patch is as shown in the description of this issue:

Doctrine_Relation_ForeignKey (from line 60):

$alias = $this->getTable()->getComponentName().'_rel';
            	
                $dql  = 'FROM ' . $this->getTable()->getComponentName()
                      .' '.$alias. ' WHERE ' . $this->getCondition($alias) . $this->getOrderBy(null, false);

Doctrine_Relation_LocalKey (from line 58):

$alias = $this->getTable()->getComponentName().'_rel';
        	
            $dql  = 'FROM ' . $this->getTable()->getComponentName()
                 .' '.$alias. ' WHERE ' . $this->getCondition($alias) . $this->getOrderBy(null, false);




[DC-993] Many-to-many Relation defined one way Created: 05/Apr/11  Updated: 17/Apr/14

Status: Open
Project: Doctrine 1
Component/s: Relations
Affects Version/s: 1.2.2, 1.2.3
Fix Version/s: None

Type: Bug Priority: Minor
Reporter: Klaas van der Weij Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 0
Labels: None
Environment:

MySQL database, Lenny



 Description   

When a many-tomany relation has been defined on only one of the end of the relation, and ofcourse in the cross-refClass, things get weird. I'll use the user-groups relation (as found in the documentation) as example.

If in the group model has not defined the hasMany, then a user can be instantiated and saved. When instantiated, the relation groups would return an empty array, groups can ben added like:

$u = new User();
var_dump($u->groups);
$u->groups[] = new Group();
var_dump($u->groups);

This would output an empty array, and subsequently an array containing the new group.

However, if a user would be retrieved from the database, and the relation groups would be called, then the following message will appear (which is not helpfull at alllll, I've spend hours figuring it out!):

Uncaught exception 'Doctrine_Record_UnknownPropertyException' with message 'Unknown record property / related component "groups"' .....

I will never forget this, but it's not described in the documentation and the error is not helping either. So either one of these step hvae to be taken. Or even better, making it work without requiring the hasMany in group, to users.






[DC-891] [PATCH] Relation array as the result of Doctrine_Table::bind() Created: 18/Oct/10  Updated: 18/Oct/10

Status: Open
Project: Doctrine 1
Component/s: Relations
Affects Version/s: None
Fix Version/s: None

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

Attachments: Text File bind.patch    

 Description   

It would be handy to return a relation array as the result of Doctrine_Table::bind(), because the relation parser's bind() already returns this value.






[DC-776] $record->link('Alias', $id) throws an exception because of getIdentifier returns array, not string Created: 05/Jul/10  Updated: 05/Jul/10

Status: Open
Project: Doctrine 1
Component/s: Record, Relations, Schema Files
Affects Version/s: 1.2.2
Fix Version/s: None

Type: Bug Priority: Minor
Reporter: Viktoras Bezaras Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Symfony 1.4.6-DEV


Sub-Tasks:
Key
Summary
Type
Status
Assignee
DC-775 $record->link('Alias', $id) throws an... Sub-task Resolved Jonathan H. Wage  

 Description   

I want to bookmark ads on my site. So i have Ads table, users table (sfDoctrineGuard) and a refclass Bookmarks. I've created an ajax link to an action, where i retrieved $ad object, $user_id and
$ad->link('Bookmarks', $user_id, true);
So I expected a record in a database to be created.

Bookmarks:
...
columns:
user_id:

{ type: integer(4), primary: true }

ad_id:

{ type: integer(4), primary: true }

relations:
sfGuardUser:

{ onDelete: CASCADE, local: user_id, foreign: id }

Ads:

{ onDelete: CASCADE, local: ad_id, foreign: ad_id }

As my Bookmarks table has 2 primary keys in the link method

if (count($ids) > 0)

{ $q->whereIn($rel->getTable()->getIdentifier(), array_values($this->identifier())); }

$rel->getTable()->getIdentifier() returned me an array('user_id', 'ad_id') instead of a string. So the query which was generated looked like
UPDATE bookmarks SET ad_id = ? WHERE (Array IN )
And Array is not the name of a column.

My schema:
http://pastie.org/private/2lr9gy1h3mtdwdsiwrwylq

I've solved an issue by creating a new Bookmark instance and saving it, but i presume that issue might distract someone.






[DC-560] Object1->Unlink(Relation, Id2) doesn't work, if primary key order in table of m2m reference isnt 1:Object 2: Id to unlink, when relation set to EQUAL= TRUE Created: 10/Mar/10  Updated: 27/Jan/11

Status: Reopened
Project: Doctrine 1
Component/s: Relations
Affects Version/s: 1.2.0
Fix Version/s: None

Type: Bug Priority: Minor
Reporter: Mariano Ramon Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 1
Labels: None
Environment:

Windows XP, Apache 2.2, PHP 5, Doctrine 1.2 on Symfony 1.4



 Description   

Object1->Unlink(Relation, Id2) doesn't work, if primary key order in table of m2m reference isnt 1:Object 2: Id to unlink, when relation set to EQUAL= TRUE

User:
  actAs: 
    Timestampable: ~
  columns:    
    name:         { type: string(255), notnull: false }
    last_name:    { type: string(255), notnull: false }
    picture:      { type: string(255), notnull: false }
    birthday:     { type: timestamp, notnull: false }
    gender:       { type: string(255) }
    rating:       { type: integer, default:0} 
    num_comments: { type: integer, default:0} 
    num_groups:   { type: integer, default:0} 
  inheritance:
    extends: Member
    type: column_aggregation
    keyField: type
    keyValue: 1                    
  relations:
    Friends:    { onDelete: CASCADE, class: User, foreignAlias: Friends, refClass: FriendReference, local: user1, foreign: user2, equal: true }
    Request:    { onDelete: CASCADE, class: User, foreignAlias: Pending, refClass: PendingReference, local: user1, foreign: user2 }
    Blocker:    { onDelete: CASCADE, class: User, foreignAlias: Blocked, refClass: BlockedReference, local: user1, foreign: user2 }

 
			if(isset($refToRemove))
			{
				switch ($refToRemove)
				{
					case 'FriendReference': $references = $currentUser->Friends; $relation = 'Friends';	break;
					case 'PendingReference': $references = $currentUser->Pending; $relation = 'Pending'; break;
					case 'BlockerReference': $references = $currentUser->Blocker; $relation = 'Blocker'; break;
					case 'RequestReference': $references = $currentUser->Request; $relation = 'Request'; break;
				}
				 
				foreach($references as $reference)
				{

					if ($reference->id == $user2->id)
                        $currentUser->unlink($relation, array($user2->id), $now = true);
				}
                
			}

when you count relations from one side and the other it show that when set to EQUAL = TRUE relations are reciprocal, but unlink still minds primary keys order in order to function



 Comments   
Comment by Jonathan H. Wage [ 15/Mar/10 ]

I am unable to reproduce the issue. When I test everything works as expected. We really need some more information and a test case in order to be sure of any issue.

Comment by Ian Ricketson [ 30/Mar/10 ]

I was able to reproduce this issue in Doctrine 1.2. The issue is a two part scenerio, which makes it kind of hard to debug. But here is how to reproduce it.

1.) Lets assume you have a Product model with ID 14.
2.) Lets assume you have an "equal" M:M table that links to itself, (product_product_group). "product_id_1" and "product_id_2" are a compound primary key which link back to the Product model.
3.) Lets assume you that Product 14 is currently linked to products with IDs 2, 5, and 13.
4.) Assuming $object is an instance of Product id 14, call $object->unlink(array(2));

  1. SQL QUERY LOG for Step 4.)
    482 Query START TRANSACTION
    482 Query DELETE FROM product_product_group WHERE (product_id_1 = '14' AND product_id_2 IN ('2'))
    482 Query UPDATE product_product_group SET product_id_1 = '5' WHERE product_id_1 = '14' AND product_id_2 = '5'
    482 Query UPDATE product_product_group SET product_id_1 = '13' WHERE product_id_1 = '14' AND product_id_2 = '13'
    482 Query DELETE FROM product_product_group WHERE product_id_2 = '2' AND product_id_1 = '14'
    482 Query COMMIT

The result is as follows:
a.) Doctrine properly unlinks ID 2
b.) Doctrine updates the M:M table and sets the remaining two IDs (5 and 13) and links them to themselves (it shouldn't run these updates). Now, all we have in our database are two links (5-5 and 13-13).

5.) Now, Product ID 14 has no links anymore in the M:M table. So we call $object->link(array(2, 5, 13));

  1. SQL QUERY LOG for Step 5.)
    512 Query START TRANSACTION
    512 Query SELECT ... FROM to_product_id t WHERE (t.id IN ('13', '2', '5'))
    512 Query INSERT INTO to_product_id_to_product_id_group (product_id_2, product_id_1) VALUES ('2', '14')
    512 Query INSERT INTO to_product_id_to_product_id_group (product_id_2, product_id_1) VALUES ('5', '14')
    512 Query INSERT INTO to_product_id_to_product_id_group (product_id_2, product_id_1) VALUES ('13', '14')
    512 Query COMMIT

This works as expected.

6.) Now, in our database, Product ID 14 properly links to Ids 2, 5, and 13. BUT IDs 5 and 13 also have a link to themselves as a byproduct of the UPDATE queries called in step 4.).
7.) Now, we call $object->unlink(array(2)) again.

  1. SQL QUERY LOG for Step 7.)
    432 Query START TRANSACTION
    432 Query DELETE FROM product_product_group WHERE (product_id_1 = '14' AND product_id_2 IN ('2'))
    432 Query UPDATE product_product_group SET product_id_1 = '5' WHERE product_id_1 = '2' AND product_id_2 = '5'
    432 Query UPDATE product_product_group SET product_id_1 = '5' WHERE product_id_1 = '14' AND product_id_2 = '5'
    432 Query ROLLBACK

The following error occurs:

  1. Mar 30 20:40:41 symfony [err] exception 'Doctrine_Connection_Mysql_Exception' with message 'SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '5-5' for key 1' in /path/to/symfony/1.4/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection.php:1082

So basically, it repeated the same queries from step 4.), however this time around, when attempting to set ID 5 to itself, it fails because there is already an entry this pair in the database. Since we have a compound primary key, this non-unique combination is not allowed. I don't know why its trying to run these UPDATE queries, but its definitely something to do with thre relationship being "equal".

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

It is hard to decipher the problem. It is best and most clear to provide a test case.

Comment by Ian Ricketson [ 27/Jan/11 ]

I know this is old, and is likely to never be resolved, but the problem does still exist.

Basically, "unlinking" an equal relation only unlinks one side of the relationship:

DELETE FROM user_user_group WHERE (user_id_1 = '20' AND user_id_2 IN ('9'))

However, if the relationship was created from the other side (i.e. user_id_1 = 9 and user_id_2 = 20), then it doesn't properly get rid of the relationship. Again, this only applies when a relationship is marked as "equal".

Here is another post about the same issue, with their work-around:
http://stackoverflow.com/questions/1385281/how-do-i-remove-a-self-referencing-nn-relation-in-doctrine





[DC-1032] [PATCH] Doctrine_Collection::isModified() does not support deep like Doctrine_Record but probably should Created: 23/Aug/11  Updated: 17/Apr/14

Status: Open
Project: Doctrine 1
Component/s: Relations
Affects Version/s: 1.2.3
Fix Version/s: None

Type: Improvement Priority: Trivial
Reporter: Christian Roy Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File DC-1032.patch    

 Description   

$record instanceof Doctrine_Record;
$collection instanceof Doctrine_Collection;

Using the $record object I can find out if it has been modified : $record->isModified().
I can also have this check all the relations also by passing true : $record->isModified(true);

However, the $collection object only support the first level and not the relations of its member records,
$collection->isModified() returns false if one of the entry has one its relations modified (as it should).

The improvement would be to allow this method to accept true, like it's $record counterpart, which would return true instead.

See attached patch.






[DC-730] "// ?? should this not be $this->_table->getComponentName() ??" in Doctrine/Relation/Parser.php Created: 12/Jun/10  Updated: 16/Jun/10

Status: Open
Project: Doctrine 1
Component/s: Relations
Affects Version/s: 1.2.2
Fix Version/s: None

Type: Task Priority: Trivial
Reporter: Guilliam X Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 0
Labels: None
Environment:

doctrine1 svn 1.2 rev. 7676


Attachments: Text File DC-730.patch    

 Description   

In class Doctrine_Relation_Parser, in method completeDefinition(), at line 508 (for svn r.7676) there is the code:

php
                foreach ((array) $this->_table->getIdentifierColumnNames() as $id) {
                    // ?? should this not be $this->_table->getComponentName() ??
                    $column = strtolower($table->getComponentName())
                            . '_' . $id;

The comment on line 509 seems right, since $table is a "temporary" variable created in a previous foreach loop a few lines before (l. 472) and not used anywhere else... (I didn't make a test case though, that's why I tagged it as "Task" rather than "Bug")

I attached a patch, just in case.

G.X



 Comments   
Comment by Guilliam X [ 15/Jun/10 ]

Edited the patch with "branches/1.2" as root

I can't provide a test case but they all run without failure after patching

Comment by Guilliam X [ 16/Jun/10 ]

Converted patch to Unix-like EOL style (was made on Windows...)





Generated at Thu Oct 23 00:09:44 UTC 2014 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.