SizeFunction.php 4.16 KB
Newer Older
1
<?php
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
 *  $Id$
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the LGPL. For more information, see
 * <http://www.doctrine-project.org>.
20 21 22 23
 */

namespace Doctrine\ORM\Query\AST\Functions;

24 25
use Doctrine\ORM\Query\Lexer;

26 27 28
/**
 * "SIZE" "(" CollectionValuedPathExpression ")"
 *
29 30 31 32 33 34 35
 * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
 * @link    www.doctrine-project.org
 * @since   2.0
 * @version $Revision: 3938 $
 * @author  Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author  Jonathan Wage <jonwage@gmail.com>
 * @author  Roman Borschel <roman@code-factory.org>
36
 * @author  Benjamin Eberlei <kontakt@beberlei.de>
37 38 39
 */
class SizeFunction extends FunctionNode
{
40
    public $collectionPathExpression;
41 42 43

    /**
     * @override
44
     * @todo If the collection being counted is already joined, the SQL can be simpler (more efficient).
45 46 47
     */
    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
48 49
        $dqlAlias = $this->collectionPathExpression->identificationVariable;
        $parts = $this->collectionPathExpression->parts;
50 51 52 53 54
        $assocField = array_pop($parts);

        $qComp = $sqlWalker->getQueryComponent(implode('.', array_merge((array) $dqlAlias, $parts)));
        $assoc = $qComp['metadata']->associationMappings[$assocField];
        $sql = '';
55 56 57
        
        if ($assoc->isOneToMany()) {
            $targetClass = $sqlWalker->getEntityManager()->getClassMetadata($assoc->targetEntityName);
58
            $targetAssoc = $targetClass->associationMappings[$assoc->mappedBy];
59 60 61 62 63
            
            $targetTableAlias = $sqlWalker->getSqlTableAlias($targetClass->primaryTable['name']);
            $sourceTableAlias = $sqlWalker->getSqlTableAlias($qComp['metadata']->primaryTable['name'], $dqlAlias);
            
            $whereSql = '';
64

65
            foreach ($targetAssoc->targetToSourceKeyColumns as $targetKeyColumn => $sourceKeyColumn) {
66 67 68
                $whereSql .= (($whereSql == '') ? ' WHERE ' : ' AND ')
                           . $targetTableAlias . '.' . $sourceKeyColumn . ' = ' 
                           . $sourceTableAlias . '.' . $targetKeyColumn;
69
            }
70 71

            $tableName = $targetClass->primaryTable['name'];
72 73 74 75 76 77 78 79 80 81 82 83
        } else if ($assoc->isManyToMany()) {
            $targetTableAlias = $sqlWalker->getSqlTableAlias($assoc->joinTable['name']);
            $sourceTableAlias = $sqlWalker->getSqlTableAlias($qComp['metadata']->primaryTable['name'], $dqlAlias);
            
            $whereSql = '';

            foreach ($assoc->relationToSourceKeyColumns as $targetKeyColumn => $sourceKeyColumn) {
                $whereSql .= (($whereSql == '') ? ' WHERE ' : ' AND ')
                           . $targetTableAlias . '.' . $targetKeyColumn . ' = ' 
                           . $sourceTableAlias . '.' . $sourceKeyColumn;
            }

84
            $tableName = $assoc->joinTable['name'];
85 86
        }
        
87
        return '(SELECT COUNT(*) FROM ' . $tableName . ' ' . $targetTableAlias . $whereSql . ')';
88 89 90 91 92 93 94 95
    }

    /**
     * @override
     */
    public function parse(\Doctrine\ORM\Query\Parser $parser)
    {
        $lexer = $parser->getLexer();
96
        
97 98
        $parser->match(Lexer::T_SIZE);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);
99 100 101
        
        $this->collectionPathExpression = $parser->CollectionValuedPathExpression();
        
102
        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
103 104 105
    }
}