[DDC-551] Altered persisters to make filters work with EXTRA_LAZY associations
This commit is contained in:
parent
2653d735e2
commit
3800581947
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user