1
0
mirror of synced 2025-01-18 06:21:40 +03:00

[DDC-551] Altered persisters to make filters work with EXTRA_LAZY associations

This commit is contained in:
Alexander 2011-08-16 16:24:50 +02:00
parent 2653d735e2
commit 3800581947
4 changed files with 205 additions and 8 deletions

View File

@ -861,9 +861,17 @@ class BasicEntityPersister
$lockSql = ' ' . $this->_platform->getWriteLockSql();
}
$alias = $this->_getSQLTableAlias($this->_class->name);
$filterSql = $this->generateFilterConditionSQL($this->_class, $alias);
if('' !== $filterSql) {
if($conditionSql) $conditionSql .= ' AND ';
$conditionSql .= $filterSql;
}
return $this->_platform->modifyLimitQuery('SELECT ' . $this->_getSelectColumnListSQL()
. $this->_platform->appendLockHint(' FROM ' . $this->_class->getQuotedTableName($this->_platform) . ' '
. $this->_getSQLTableAlias($this->_class->name), $lockMode)
. $alias, $lockMode)
. $this->_selectJoinSql . $joinSql
. ($conditionSql ? ' WHERE ' . $conditionSql : '')
. $orderBySql, $limit, $offset)
@ -1340,10 +1348,33 @@ class BasicEntityPersister
$criteria = array_merge($criteria, $extraConditions);
}
$alias = $this->_getSQLTableAlias($this->_class->name);
$sql = 'SELECT 1 FROM ' . $this->_class->getQuotedTableName($this->_platform)
. ' ' . $this->_getSQLTableAlias($this->_class->name)
. ' ' . $alias
. ' WHERE ' . $this->_getSelectConditionSQL($criteria);
$filterSql = $this->generateFilterConditionSQL($this->_class, $alias);
if('' !== $filterSql) {
$sql .= ' AND ' . $filterSql;
}
return (bool) $this->_conn->fetchColumn($sql, array_values($criteria));
}
private function generateFilterConditionSQL(ClassMetadata $targetEntity, $targetTableAlias)
{
$filterSql = '';
$first = true;
foreach($this->_em->getEnabledFilters() as $filter) {
if("" !== $filterExpr = $filter->addFilterConstraint($targetEntity, $targetTableAlias)) {
if ( ! $first) $sql .= ' AND '; else $first = false;
$filterSql .= '(' . $filterExpr . ')';
}
}
return $filterSql;
}
}

View File

@ -208,7 +208,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
if ($whereClause !== '') {
$whereClause .= ' AND ';
}
$whereClause .= "$joinTableColumn = ?";
$whereClause .= "t.$joinTableColumn = ?";
if ($class->containsForeignIdentifier) {
$params[] = $id[$class->getFieldForColumn($joinColumns[$joinTableColumn])];
@ -217,7 +217,14 @@ class ManyToManyPersister extends AbstractCollectionPersister
}
}
}
$sql = 'SELECT count(*) FROM ' . $joinTable['name'] . ' WHERE ' . $whereClause;
list($joinTargetEntitySQL, $filterSql) = $this->getFilterSql($mapping);
$sql = 'SELECT count(*)'
. ' FROM ' . $joinTable['name'] . ' t'
. $joinTargetEntitySQL
. ' WHERE ' . $whereClause
. $filterSql;
return $this->_conn->fetchColumn($sql, $params);
}
@ -293,8 +300,44 @@ class ManyToManyPersister extends AbstractCollectionPersister
}
}
}
$sql = 'SELECT 1 FROM ' . $joinTable['name'] . ' WHERE ' . $whereClause;
list($joinTargetEntitySQL, $filterSql) = $this->getFilterSql($mapping);
$sql = 'SELECT 1'
. ' FROM ' . $joinTable['name'] . ' t'
. $joinTargetEntitySQL
. ' WHERE ' . $whereClause
. $filterSql;
return (bool)$this->_conn->fetchColumn($sql, $params);
}
public function getFilterSql($mapping)
{
$targetClass = $this->_em->getClassMetadata($mapping['targetEntity']);
// Get the SQL for the filters
$filterSql = '';
foreach($this->_em->getEnabledFilters() as $filter) {
if("" !== $filterExpr = $filter->addFilterConstraint($targetClass, 'te')) {
$filterSql .= ' AND (' . $filterExpr . ')';
}
}
// A join is needed if there is filtering on the target entity
$joinTargetEntitySQL = '';
if('' !== $filterSql) {
$joinTargetEntitySQL = ' JOIN '
. $targetClass->getQuotedTableName($this->_conn->getDatabasePlatform()) . ' te'
. ' ON';
$first = true;
foreach($mapping['relationToTargetKeyColumns'] as $joinTableColumn => $targetTableColumn) {
if(!$first) $joinTargetEntitySQL .= ' AND '; else $first = false;
$joinTargetEntitySQL .= ' t.' . $joinTableColumn . ' = ' . 'te.' . $targetTableColumn;
}
}
return array($joinTargetEntitySQL, $filterSql);
}
}

View File

@ -133,7 +133,7 @@ class OneToManyPersister extends AbstractCollectionPersister
if ($where != '') {
$where .= ' AND ';
}
$where .= $joinColumn['name'] . " = ?";
$where .= 't.' . $joinColumn['name'] . " = ?";
if ($class->containsForeignIdentifier) {
$params[] = $id[$class->getFieldForColumn($joinColumn['referencedColumnName'])];
} else {
@ -141,7 +141,15 @@ class OneToManyPersister extends AbstractCollectionPersister
}
}
$sql = "SELECT count(*) FROM " . $class->getQuotedTableName($this->_conn->getDatabasePlatform()) . " WHERE " . $where;
$sql = "SELECT count(*) FROM " . $class->getQuotedTableName($this->_conn->getDatabasePlatform()) . " t WHERE " . $where;
// Apply the filters
foreach($this->_em->getEnabledFilters() as $filter) {
if("" !== $filterExpr = $filter->addFilterConstraint($class, 't')) {
$sql .= ' AND (' . $filterExpr . ')';
}
}
return $this->_conn->fetchColumn($sql, $params);
}

View File

@ -25,6 +25,7 @@ require_once __DIR__ . '/../../TestInit.php';
class SQLFilterTest extends \Doctrine\Tests\OrmFunctionalTestCase
{
private $userId, $userId2, $articleId, $articleId2;
private $groupId, $groupId2;
public function setUp()
{
@ -32,6 +33,15 @@ class SQLFilterTest extends \Doctrine\Tests\OrmFunctionalTestCase
parent::setUp();
}
public function tearDown()
{
parent::tearDown();
$class = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
$class->associationMappings['groups']['fetch'] = ClassMetadataInfo::FETCH_LAZY;
$class->associationMappings['articles']['fetch'] = ClassMetadataInfo::FETCH_LAZY;
}
public function testConfigureFilter()
{
$config = new \Doctrine\ORM\Configuration();
@ -307,6 +317,109 @@ class SQLFilterTest extends \Doctrine\Tests\OrmFunctionalTestCase
}
private function loadLazyFixtureData()
{
$class = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
$class->associationMappings['articles']['fetch'] = ClassMetadataInfo::FETCH_EXTRA_LAZY;
$class->associationMappings['groups']['fetch'] = ClassMetadataInfo::FETCH_EXTRA_LAZY;
$this->loadFixtureData();
}
private function useCMSArticleTopicFilter()
{
$conf = $this->_em->getConfiguration();
$conf->addFilter("article_topic", "\Doctrine\Tests\ORM\Functional\CMSArticleTopicFilter");
$this->_em->enableFilter("article_topic")->setParameter("topic", "Test1", \Doctrine\DBAL\Types\Type::getType(\Doctrine\DBAL\Types\Type::STRING)->getBindingType());
}
public function testOneToMany_ExtraLazyCountWithFilter()
{
$this->loadLazyFixtureData();
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId);
$this->assertFalse($user->articles->isInitialized());
$this->assertEquals(2, count($user->articles));
$this->useCMSArticleTopicFilter();
$this->assertEquals(1, count($user->articles));
}
public function testOneToMany_ExtraLazyContainsWithFilter()
{
$this->loadLazyFixtureData();
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId);
$filteredArticle = $this->_em->find('Doctrine\Tests\Models\CMS\CmsArticle', $this->articleId2);
$this->assertFalse($user->articles->isInitialized());
$this->assertTrue($user->articles->contains($filteredArticle));
$this->useCMSArticleTopicFilter();
$this->assertFalse($user->articles->contains($filteredArticle));
}
public function testOneToMany_ExtraLazySliceWithFilter()
{
$this->loadLazyFixtureData();
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId);
$this->assertFalse($user->articles->isInitialized());
$this->assertEquals(2, count($user->articles->slice(0,10)));
$this->useCMSArticleTopicFilter();
$this->assertEquals(1, count($user->articles->slice(0,10)));
}
private function useCMSGroupPrefixFilter()
{
$conf = $this->_em->getConfiguration();
$conf->addFilter("group_prefix", "\Doctrine\Tests\ORM\Functional\CMSGroupPrefixFilter");
$this->_em->enableFilter("group_prefix")->setParameter("prefix", "foo%", \Doctrine\DBAL\Types\Type::getType(\Doctrine\DBAL\Types\Type::STRING)->getBindingType());
}
public function testManyToMany_ExtraLazyCountWithFilter()
{
$this->loadLazyFixtureData();
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId2);
$this->assertFalse($user->groups->isInitialized());
$this->assertEquals(2, count($user->groups));
$this->useCMSGroupPrefixFilter();
$this->assertEquals(1, count($user->groups));
}
public function testManyToMany_ExtraLazyContainsWithFilter()
{
$this->loadLazyFixtureData();
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId2);
$filteredArticle = $this->_em->find('Doctrine\Tests\Models\CMS\CmsGroup', $this->groupId2);
$this->assertFalse($user->groups->isInitialized());
$this->assertTrue($user->groups->contains($filteredArticle));
$this->useCMSGroupPrefixFilter();
$this->assertFalse($user->groups->contains($filteredArticle));
}
public function testManyToMany_ExtraLazySliceWithFilter()
{
$this->loadLazyFixtureData();
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId2);
$this->assertFalse($user->groups->isInitialized());
$this->assertEquals(2, count($user->groups->slice(0,10)));
$this->useCMSGroupPrefixFilter();
$this->assertEquals(1, count($user->groups->slice(0,10)));
}
private function loadFixtureData()
{
$user = new CmsUser;
@ -367,6 +480,8 @@ class SQLFilterTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->userId2 = $user2->getId();
$this->articleId = $article1->id;
$this->articleId2 = $article2->id;
$this->groupId = $group->id;
$this->groupId2 = $group2->id;
}
}