5

I am using Doctrine and it fails to INSERT data the first time I do a persist/flush but works the second time, and fails the 3rd time:

// there is no code executed between any of the attempts

$entity = new My\Entity();
$entity->setTag('A');  // just a random field
$em->persist($entity);
$em->flush();
// INSERT not performed
// if I exit here and check the database, no entry is added

$entity = new My\Entity();
$entity->setTag('B');
$em->persist($entity);
$em->flush();
// INSERT performed
// if I exit here and check the database, 1 entry has been added
// and I can see it's "B"

$entity = new My\Entity();
$entity->setTag('C');
$em->persist($entity);
$em->flush();
// INSERT not performed
// if I exit here and check the database, there is still only 1 entry added
// and I can see it's "B"

Here is what I notice on failing attempts:
- There is nothing in the PHP logs (error_reporting is set to all, other Doctrine and PHP issues, including warnings, do show up in the logs).
- The Doctrine SQLLogger doesn't show anything (on the second attempt it does show the INSERT).

Some troubleshooting steps:
- I wanted to troubleshoot further by replacing the failing attempt with a DQL INSERT query but "INSERT statements are not allowed in DQL" :(
- Doing an additional flush before instantiating $entity in the failing attempt doesn't help - I can insert as many entries as I want to the database manually and it works, even on first attempt.
- I have the same issue with 2.4.0-DEV.
- I have the same issue with 2.2.2.

I might add that the code is executed inside a PHPunit test, and that in a previous test, I am not experiencing the issue (i.e. Doctrine does properly perform an INSERT on the first persist/flush).

Any idea where the problem might be coming from ?

Version info:
-PHP 5.4
-Doctrine 2.3.0 (pdo_mysql driver)
-MySQL 5.5.24
-Ubuntu 12.04
-PHPUnit 3.7.7

Update 1:

Alright, this is part of the answer. The problem seems to by a routine I use in my PHPUnit setUp() to truncate my database tables between each test:

  • if I truncate my tables between each test, I have problems (i.e. some INSERTs fail).
  • if I don't truncate, everything works fines.

The way the INSERTs fail seem to be mode random than initially thought, as I created 2 tests of 3 inserts each (and only ran those). When truncating tables between each test, here is what happens to the 3 inserts in each test:
-test 1: SUCCESS / SUCCESS / SUCCESS
-test 2: SUCCESS / SUCCESS / FAILURE (I don't have FAILURE / SUCCESS / FAILURE like I used to).

Here is the piece of code I'm using to truncate the tables:

$cmd = $em->getClassMetadata($className);
$connection = $em->getConnection();
$dbPlatform = $connection->getDatabasePlatform();
$connection->beginTransaction();
try {
    $connection->query('SET FOREIGN_KEY_CHECKS=0');
    $q = $dbPlatform->getTruncateTableSql($cmd->getTableName());
    $connection->executeUpdate($q);
    $connection->query('SET FOREIGN_KEY_CHECKS=1');
    $connection->commit();
}
catch (\Exception $e) {
    $connection->rollback();
}

I got the code from this SO post and as far as I can see it looks good. I have the same issue if I use this other code:

$connection = $entityManager->getConnection();
$platform   = $connection->getDatabasePlatform();
$connection->executeUpdate($platform->getTruncateTableSQL('my_table', true /* whether to cascade */));

I modified my schema to test with and without the foreign keys and I have the same issue in both cases.

Community
  • 1
  • 1
Max
  • 12,794
  • 30
  • 90
  • 142
  • How do you know it isn't working the first time and failing the second time? – Jez Oct 18 '12 at 12:11
  • 1
    Because if I exit after the first attempt and check the database, there is no entry inserted. I'll add that to the code snippet. – Max Oct 18 '12 at 12:13

1 Answers1

0

In the end it appears that the issue occurred when:
-truncating the tables between each test in the setUp function.
AND
-instantiating the Doctrine instance only once in setUpBeforeClass (that I was then accessing with self::$em).

If I don't truncate the tables between each test OR if I instantiate my Doctrine instance in setUp, everything works fine.

I used to like setUpBeforeClass, not such more anymore...

Max
  • 12,794
  • 30
  • 90
  • 142