}

$t->diag('sfDoctrineFinder::with() and left joins');

Doctrine_Query::create()->delete()->from('DComment')->execute();
Doctrine_Query::create()->delete()->from('DArticle')->execute();
Doctrine_Query::create()->delete()->from('DCategory')->execute();

$category1 = new DCategory();
$category1->setName('cat1');
$category1->save();
$article1 = new DArticle();
$article1->setTitle('aaa');
$article1->setCategory($category1);
$article1->save();
$article2 = new DArticle();
$article2->setTitle('bbb');
$article2->save();

$article = sfDoctrineFinder::from('DArticle')->leftJoin('DCategory')->with('DCategory')->findLast();
$category = $article->getCategory();
if (is_object($category))
{
  $t->isa_ok($article->getCategory(), 'Doctrine_Null', 'In a left join using with(), empty related objects are not hydrated');
}
else
{
  $t->isa_ok($article->getCategory(), 'NULL', 'In a left join using with(), empty related objects are not hydrated');
}

Doctrine_Query::create()->delete()->from('DComment')->execute();
$t = new lime_test(33, new lime_output_color());

$article1 = new DArticle();
$article1->setTitle('tt1');
$article1->save();
$article2 = new DArticle();
$article2->setTitle('tt2');
$article2->save();
$article3 = new DArticle();
$article3->setTitle('tt3');
$article3->save();
$article4 = new DArticle();
$article4->setTitle('tt4');
$article4->save();
$article5 = new DArticle();
$article5->setTitle('t5');
$article5->save();

$t->diag('sfDoctrineFinderPager');

$pager = new sfDoctrineFinderPager('DArticle', 2);
$pager->setPage(1);
$pager->init();

$t->is($pager->getNbResults(), 5, 'sfDoctrineFinderPager::getNbResults() return the total nb of results');
$t->is($pager->getLastPage(), 3, 'sfDoctrineFinderPager::getLastPage() return the total nb of pages');
$t->is($pager->getFirstIndice(), 1, 'sfDoctrineFinderPager::getFirstIndice() return offset of the first result of the page');
$articles = $pager->getResults();
$t->is(count($articles), 2, 'sfDoctrineFinderPager::getResults() return an array of max $maxPerPage results');
$t->is(@$articles[0]->getTitle(), 'tt1', 'sfDoctrineFinderPager::getResults() return an array of BaseObject instances');
           DbFinder::from('DArticle')->useCache($cache, 10)->where('Title', 'foo1')->findOne(); // normal query
$article = DbFinder::from('DArticle')->useCache($cache, 10)->where('Title', 'foo1')->findOne(); // cached query
$t->isa_ok($article, 'DArticle', 'Cached finder queries return Model objects');
$t->is($article->getId(), $article1->getId(), 'find() finder queries can be cached');

      DbFinder::from('DArticle')->useCache($cache, 10)->where('Title', 'foo1')->count(); // normal query
$nb = DbFinder::from('DArticle')->useCache($cache, 10)->where('Title', 'foo1')->count(); // cached query
$t->is($nb, 1, 'count() finder queries can be cached');

apc_clear_cache('user');

           DbFinder::from('DArticle')->useCache($cache, 10)->where('Title', 'foo1')->limit(1)->find(); // normal query
$article = DbFinder::from('DArticle')->useCache($cache, 10)->where('Title', 'foo1')->findOne();        // cached query
$t->isa_ok($article, 'DArticle', 'Cached queries return the correct result type');

$t->diag('useCache(true)');

apc_clear_cache('user');

Doctrine_Query::create()->delete()->from('DArticle')->execute();
$article1 = new DArticle();
$article1->setTitle('foo1');
$article1->save();

$finder = DbFinder::from('DArticle')->useCache(true, 10);
$finder->where('Title', 'foo1')->limit(1);
$key = $finder->getQueryObject()->calculateResultCacheHash();
$t->is($cache->fetch($key), null, 'No cache is set until the query is written');
$finder->find();
$t->isnt($cache->fetch($key), null, 'useCache(true) automatically selects available cache backend');
$article2->setTitle('bar');
$article2->save();
$finder = sfDoctrineFinder::from('DArticle')->where('Title', 'foo');
$t->is($finder->set(array('Title' => 'updated title')), 1, 'set() returns the number of updated rows');
$t->is($finder->getLatestQuery(), 'UPDATE d_article SET title = \'updated title\' WHERE title = \'foo\'', 'set() issues an Update query when passed a finder');
$t->is(sfDoctrineFinder::from('DArticle')->where('Title', 'updated title')->count(), 1, 'set() updates only the records found based on the array of values');
$finder = sfDoctrineFinder::from('DArticle')->where('Title', 'bar');
$t->is($finder->set(array('Title' => 'updated title'), true), 1, 'set() returns the number of updated rows, even with $forceIndividualSaves set to true');
$t->isnt($finder->getLatestQuery(), 'UPDATE d_article SET title = \'updated title\' WHERE title = \'bar\'', 'set() issues an Update query on every record when passed a finder with $forceIndividualSaves set to true');
$t->is(sfDoctrineFinder::from('DArticle')->where('Title', 'updated title')->count(), 2, 'set() updates only the records found based on the array of values, even with $forceIndividualSaves set to true');
try {
    sfDoctrineFinder::from('DComment')->joinArticle()->where('DArticle.Title', 'updated title')->set(array('Title' => 3));
    $t->fail('set() throws an exception when called on a finder with join()');
} catch (Exception $e) {
    $t->pass('set() throws an exception when called on a finder with join()');
}
$t->diag('Table alias');
Doctrine_Query::create()->delete()->from('DArticle')->execute();
$article1 = new DArticle();
$article1->setTitle('abc');
$article1->save();
$article = sfDoctrineFinder::from('DArticle a')->where('a.Title', 'abc')->findOne();
$t->is($article->getId(), $article1->getId(), 'from() accepts a table alias');
$t->diag('Debugging functions');
$finder = sfDoctrineFinder::from('DArticle')->where('Title', 'foo');
$t->isa_ok($finder->getQueryObject(), 'Doctrine_Query', 'getQueryObject() returns the query object as composed by the finder');
$finder->findOne();
$t->is($finder->getLatestQuery(), 'SELECT d.id AS d__id, d.title AS d__title, d.category_id AS d__category_id FROM d_article d WHERE d.title = \'foo\' LIMIT 1', 'getLatestQuery() returns the latest SQL query');
$finder = sfDoctrineFinder::from('DArticle d')->addWhere('d.title = :foo', array(':foo' => 'bar'));
$finder->findOne();
$t->is($finder->getLatestQuery(), 'SELECT d.id AS d__id, d.title AS d__title, d.category_id AS d__category_id FROM d_article d WHERE d.title = \'bar\' LIMIT 1', 'you can call Doctrine_Query methods directly on the finder object to modify its query');
  where('grandfather.Name', 'John');
$humans = $finder->find();
$t->is(count($humans), 1, 'join() allows to join to the current table with several foreign keys using an alias');
$t->is($finder->getLatestQuery(), 'SELECT d.id AS d__id, d.name AS d__name, d.father_id AS d__father_id, d.mother_id AS d__mother_id FROM d_human d INNER JOIN d_human d2 ON d.father_id = d2.id INNER JOIN d_human d3 ON d2.father_id = d3.id WHERE d3.name = \'John\'', 'join() uses aliased table names when using an alias relation');

/******************************************/
/* sfDoctrineFinder::join() and relations */ 
/******************************************/

$t->diag('sfDoctrineFinder::join() and relations');

Doctrine_Query::create()->delete()->from('DAuthor')->execute();
Doctrine_Query::create()->delete()->from('DComment')->execute();
Doctrine_Query::create()->delete()->from('DArticle')->execute();

$article1 = new DArticle();
$article1->setTitle('aaaaa');
$article1->setCategory($category1);
$article1->save();
$author1 = new DAuthor();
$author1->setName('John');
$author1->save();
$comment = new DComment();
$comment->setContent('foo');
$comment->setArticleId($article1->getId());
$comment->setAuthor($author1);
$comment->save();
$article = sfDoctrineFinder::from('DArticle')->
  join('DComment')->
  join('DAuthor')->
  where('DAuthor.Name', 'John')->
Doctrine_Query::create()->delete()->from('DCategory')->execute();
$category1 = new DCategory();
$category1->setName('cat1');
$category1->save();
$category2 = new DCategory();
$category2->setName('cat2');
$category2->save();
$article1 = new DArticle();
$article1->setTitle('art1');
$article1->setCategory($category1);
$article1->save();
$article2 = new DArticle();
$article2->setTitle('art2');
$article2->setCategory($category2);
$article2->save();
$article3 = new DArticle();
$article3->setTitle('art3');
$article3->setCategory($category1);
$article3->save();

$finder = sfDoctrineFinder::from('DArticle')->
  withColumn('DCategory.Name')->
  select(array('DArticle.Title', 'DCategory.Name'));
$data = $finder->findOne();
$t->is($finder->getLatestQuery(), doctrine_sql('SELECT [D011d.id AS d__id, ]d.title AS d__title, d2.name AS d2__0 FROM d_article d INNER JOIN d_category d2 ON d.category_id = d2.id LIMIT 1'), 'select() can cope with a column added with withColumn()');
$t->is_deeply($data, array('DArticle.Title' => 'art1', 'DCategory.Name' => 'cat1'), 'find() does not request twice the columns added by way of withColumn() and select()');

$finder = sfDoctrineFinder::from('DArticle')->
  join('DCategory')->
  withColumn('DCategory.Name', 'cname')->
  select(array('DArticle.Title', 'cname'));