[Doctrine] SQLiteでQuery::iterate()を使うとDBがロックする件
僕はSymfony+Doctrineプロジェクトで機能テストを作る際、 LiipFunctionalTestBundle を使ってテスト環境だけSQLiteで動作するようにしているのですが、ある時から途中でDBがロックしてしまい、テストスイートがパスしなくなってしまいました。
SQLSTATE[HY000]: General error: 5 database table is locked
原因を探っていくうちに、以下のテストケースに問題がある事が分かりました。
<?php $query = $entityRepository->createHogeQuery(); // Doctrine\ORM\Query $iterator = $query->iterate(); $iterator->rewind(); $this->assertSame($expectedEntity, $iterator->current()[0]);
実際にアプリケーションでも大量の結果セットを返す可能性のある::createHogeQuery()
はiterate()
して使っていたのでテストも同様にしたのですが、横着したのがいけなかったようです。
どう言う事かと言うと、iterate()
を使う場合は最後の行までフェッチしないと、内部のPDOStatement
がcloseCursor()
されないようで、その結果次回以降のテストに影響が出ていたと言うわけです。
テストに以下を追加する事でとりあえず解決しました。
<?php while ($iterator->next()); // cleanup
あるいは、テストデータの量はたかがしてれているのでそもそもテストではiterate()
を使わなければ良いのかもしれません。
ところでこれ、普通にforeach
したとしてもbreak
されたら同様の事が起きそうですよね。誰か試してみて下さい。