Wednesday, December 01, 2010

SQLite and Doctrine: in memory databases

Recently for a client's project, I incorporated a SQLite in memory database into my persistence tests as its a good (and fast) alternative to managing separate unit test and system databases. Typically in my test setup / tear down methods, I drop and recreate the unit test database to ensure clean testing conditions.... however I found that Doctrine doesn't support SQLite in memory database drops.

To drop an in memory db - I don't believe the standard sql drop statement works. As this is the case, when calling Doctrine::dropDatabases(), Doctrine's SQLite Driver produces in a 'Database could not be found' Exception in its dropDatabases method.

As the SQLite in memory databases exist for the life of the connection only, a good solution is to simply reset the connection.

Burrowing through the Doctrine framework, within the SQLite Driver (Doctrine/Connection/SQLite.php) I made the following modification:


 public function dropDatabase()
    {
        if ( ! $dsn = $this->getOption('dsn')) {
            throw new Doctrine_Connection_Exception('You must create your Doctrine_Connection by using a valid Doctrine style dsn in order to use the create/drop database functionality');
        }
        
        $info = $this->getManager()->parseDsn($dsn);
        
        //
        // BENS EDIT: If the db is in memory only - simply recreate a new connection
        //
        if(strcasecmp($info["dsn"], "sqlite::memory:") == 0)
        {         
         $c = $this->getManager()->getCurrentConnection();

  $this->getManager()->closeConnection($c);
  $this->getManager()->connection("sqlite::memory:","unit_test");
     
         return;
        }
        //
        // END BENS EDIT
        //

        $this->export->dropDatabase($info['database']);
    }

There are probably better ways to do this - so feel free to leave comments - however the above worked for me...