[DC-377] Cannot delete a taggable record (Taggable Extension) Created: 22/Dec/09  Updated: 10/Aug/12  Resolved: 15/Mar/10

Status: Closed
Project: Doctrine 1
Component/s: Extensions
Affects Version/s: 1.2.0, 1.2.1
Fix Version/s: 1.2.2

Type: Bug Priority: Major
Reporter: Fabien Pennequin Assignee: Jonathan H. Wage
Resolution: Fixed Votes: 1
Labels: None
Environment:

PHP 5.3.1, Mac OS X (10.6), MySQL 5.0.86, Symfony 1.4.1


Attachments: Text File TaggableConstraintError.patch    

 Description   

With Taggable extension, when I try to delete a record using Taggable, I get this exception :

SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (`sf_sandbox/article_taggable_tag`, CONSTRAINT `article_taggable_tag_id_article_id` FOREIGN KEY (`id`) REFERENCES `article` (`id`))

If I check the sql queries generated by Doctrine, there are not "onDelete CASCADE" for one of relation added by Taggable extension.

I have write some test cases for reproduce this bug (checking if relation has a property onDelete setted to CASCADE) but I can't reproduce the thrown exception in test case because sqlite omits queries with constraint. Also, I found how to fix this bug.

The fix and test cases are available in the file attached to this ticket.



 Comments   
Comment by Jason [ 20/Apr/10 ]

Hi Jon-

Where can I find this fix?

http://svn.doctrine-project.org/extensions/Taggable/branches/1.2-1.0 (the link referenced from the docs at http://www.doctrine-project.org/extension/Taggable) doesn't have this fix.

Comment by Jason [ 20/Apr/10 ]

Sorry, it appears the patch attached above is in SVN, however this is still broken.

With Doctrine 1.2.2 sandbox configured to work with MySQL 5.x database on 5.2.10, using the following schema

{{
BlogPost:
actAs: [Taggable]
columns:
title:
type: string(255)
notnull: true
description:
type: string(255)
notnull: true
}}

the CASCADE in the constraints for the table being applied the Taggable behavior are still not being applied (see first constraint below)

{{
CREATE TABLE `blog_post_taggable_tag` (
`id` bigint(20) NOT NULL DEFAULT '0',
`tag_id` bigint(20) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`,`tag_id`),
KEY `blog_post_taggable_tag_tag_id_taggable_tag_id` (`tag_id`),
CONSTRAINT `blog_post_taggable_tag_id_blog_post_id` FOREIGN KEY (`id`) REFERENCES `blog_post` (`id`),
CONSTRAINT `blog_post_taggable_tag_tag_id_taggable_tag_id` FOREIGN KEY (`tag_id`) REFERENCES `taggable_tag` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
}}

Comment by Malcolm Hall [ 10/Aug/12 ]

I use Doctrine v1.2.4 and created a fix for this problem, change the _options array initialization in Taggable.php to this:

protected $_options = array(
'builderOptions' => array(),
'tagField' => null,
'cascadeDelete' => true
);

This works because parent::buildRelation() calls the buildLocalRelation() method in Generator.php which looks for the cascadeDelete and if true then it adds the necessary CASCADE params, as you can see below:

public function buildLocalRelation($alias = null)
{
...
if (isset($this->_options['cascadeDelete']) && $this->_options['cascadeDelete'] && ! $this->_options['appLevelDelete'])

{ $options['onDelete'] = 'CASCADE'; $options['onUpdate'] = 'CASCADE'; }

...

Now both parts of the taggable relation get the cascade on delete feature. So if you delete a tag OR you delete a post, the row in the taggable_tag table gets deleted too.

Generated at Wed Sep 17 03:39:56 UTC 2014 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.