#6245: HABTM primaryKey identified in one direction only, bad DELETE queries
---------------------------------+------------------------------------------
    Reporter:  cuppett           |          Type:  Bug    
      Status:  new               |      Priority:  High   
   Milestone:  1.2.x.x           |     Component:  General
     Version:  1.2 Final         |      Severity:  Major  
    Keywords:  HABTM primaryKey  |   Php_version:  PHP 5  
Cake_version:  1.2.2.8120        |  
---------------------------------+------------------------------------------
 Environment:

 Windows Server 2003
 PHP 5.2.8
 CakePHP 1.2.2 or 1.2.1
 Database: PostgreSQL 8.3.6

 Problem:

 When HABTM models are defined in both directions (e.g. within Tag and Post
 model definitions) with default values for 'with' and 'unique', it will
 define the $assoc model once for both of them and choose just one of the
 columns as primaryKey based on the first direction it sees.

 In the $assoc model, it seems that the $primaryKey attribute will be set
 to one of the columns in the join table (e.g. tag_id).  This $primaryKey
 is used for the DELETE query in both directions.  So, if you allow
 associating Tags on a Post as well as changing the Posts from a Tag, in
 one of the directions you'll get a bogus DELETE query that can remove the
 Post from all other Tags.

 Editing Post and Associating Tags to a Post:

 DELETE FROM posts_tags WHERE post_id IN ( 8 );
 INSERT;
 INSERT;
 INSERT;

 Editing Tags and Associating Posts to a Tag:

 DELETE FROM posts_tags WHERE post_id IN ( 8, 14, 23 );
 INSERT;
 INSERT;
 INSERT;

 In the second, it removes posts from all tags (instead of just the tag
 being used) before re-adding it to just the one Tag.

 This behavior seems to depend on the order which models are loaded in the
 controller.  The first one seems to get the primaryKey in the $assoc for
 both of them.

 I traced the code in Model->__saveMulti.  On line 1273 it seems
 $conditions would be good for the delete.  Then, by 1296, $idField seems
 to get the wrong idea about a primary key field.  Then, down in
 dbo_source.php on 1447, it gets back a WHERE clause containing only IDs
 for what it considers $primaryKey which is wrong in one of the two
 directions.

 Extra Information:

 I had defined the table as PRIMARY KEY (tag_id, post_id) and I thought
 when Cake loads up it was choosing one of the columns and trying to
 identify the multi-part key.  This is not the case.  I removed the primary
 key here and it didn't help.

 I tried re-ordering the models in my $uses array for the Controller.  This
 changed the direction in which the wrong DELETE would get executed, so it
 definitely seems related to schema recognition when it starts up rather
 than execution code happening in __saveMulti().  I also tried just putting
 an unset($this->{$join}->primaryKey) in various forms and places in there
 and it just made it barf in various ways deeper in the code or flow.

 Workaround:

 I was able to get around the problem by adding another 'id' column to the
 join table and setting it as the primary key.  In this way, it's
 unambiguous to CakePHP what the $primaryKey on the $join table is and
 DELETEs utilize that column to identify the relationship.  However, this
 will churn through the sequence relatively quickly with larger datasets
 and the DELETE before INSERT usage of HABTM.

-- 
Ticket URL: <https://trac.cakephp.org/ticket/6245>
CakePHP : The Rapid Development Framework for PHP <https://trac.cakephp.org/>
Cake is a rapid development framework for PHP which uses commonly known design 
patterns like ActiveRecord, Association Data Mapping, Front Controller and MVC. 
Our primary goal is to provide a structured framework that enables PHP users at 
all levels to rapidly develop robust web applications, without any loss to 
flexibility.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"tickets cakephp" group.
To post to this group, send email to tickets-cakephp@googlegroups.com
To unsubscribe from this group, send email to 
tickets-cakephp+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/tickets-cakephp?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to