Merge branch 'master' of github.com:doctrine/doctrine2
This commit is contained in:
commit
4d561651a1
@ -88,6 +88,7 @@
|
||||
<xs:attribute name="repository-class" type="xs:string"/>
|
||||
<xs:attribute name="inheritance-type" type="orm:inheritance-type"/>
|
||||
<xs:attribute name="change-tracking-policy" type="orm:change-tracking-policy" />
|
||||
<xs:attribute name="read-only" type="xs:boolean" default="false" />
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="mapped-superclass" >
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id: Abstract.php 1393 2008-03-06 17:49:16Z guilhermeblanco $
|
||||
*
|
||||
* 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
|
||||
@ -415,6 +413,31 @@ abstract class AbstractQuery
|
||||
return $this->execute(array(), self::HYDRATE_SCALAR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get exactly one result or null.
|
||||
*
|
||||
* @throws NonUniqueResultException
|
||||
* @param int $hydrationMode
|
||||
* @return mixed
|
||||
*/
|
||||
public function getOneOrNullResult($hydrationMode = null)
|
||||
{
|
||||
$result = $this->execute(array(), $hydrationMode);
|
||||
|
||||
if ($this->_hydrationMode !== self::HYDRATE_SINGLE_SCALAR && ! $result) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (is_array($result)) {
|
||||
if (count($result) > 1) {
|
||||
throw new NonUniqueResultException;
|
||||
}
|
||||
return array_shift($result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the single result of the query.
|
||||
*
|
||||
@ -501,10 +524,20 @@ abstract class AbstractQuery
|
||||
* @param integer $hydrationMode The hydration mode to use.
|
||||
* @return IterableResult
|
||||
*/
|
||||
public function iterate(array $params = array(), $hydrationMode = self::HYDRATE_OBJECT)
|
||||
public function iterate(array $params = array(), $hydrationMode = null)
|
||||
{
|
||||
if ($hydrationMode !== null) {
|
||||
$this->setHydrationMode($hydrationMode);
|
||||
}
|
||||
|
||||
if ($params) {
|
||||
$this->setParameters($params);
|
||||
}
|
||||
|
||||
$stmt = $this->_doExecute();
|
||||
|
||||
return $this->_em->newHydrator($this->_hydrationMode)->iterate(
|
||||
$this->_doExecute($params, $hydrationMode), $this->_resultSetMapping, $this->_hints
|
||||
$stmt, $this->_resultSetMapping, $this->_hints
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -97,12 +97,16 @@ class EntityManager implements ObjectManager
|
||||
private $proxyFactory;
|
||||
|
||||
/**
|
||||
* @var ExpressionBuilder The expression builder instance used to generate query expressions.
|
||||
* The expression builder instance used to generate query expressions.
|
||||
*
|
||||
* @var Doctrine\ORM\Query\Expr
|
||||
*/
|
||||
private $expressionBuilder;
|
||||
|
||||
/**
|
||||
* Whether the EntityManager is closed or not.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $closed = false;
|
||||
|
||||
@ -164,7 +168,7 @@ class EntityManager implements ObjectManager
|
||||
* ->where($expr->orX($expr->eq('u.id', 1), $expr->eq('u.id', 2)));
|
||||
* </code>
|
||||
*
|
||||
* @return ExpressionBuilder
|
||||
* @return Doctrine\ORM\Query\Expr
|
||||
*/
|
||||
public function getExpressionBuilder()
|
||||
{
|
||||
|
54
lib/Doctrine/ORM/Event/OnClearEventArgs.php
Normal file
54
lib/Doctrine/ORM/Event/OnClearEventArgs.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/*
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Event;
|
||||
|
||||
/**
|
||||
* Provides event arguments for the onClear event.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.com
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
* @author Roman Borschel <roman@code-factory.de>
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
*/
|
||||
class OnClearEventArgs extends \Doctrine\Common\EventArgs
|
||||
{
|
||||
/**
|
||||
* @var \Doctrine\ORM\EntityManager
|
||||
*/
|
||||
private $em;
|
||||
|
||||
/**
|
||||
* @param \Doctrine\ORM\EntityManager $em
|
||||
*/
|
||||
public function __construct($em)
|
||||
{
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Doctrine\ORM\EntityManager
|
||||
*/
|
||||
public function getEntityManager()
|
||||
{
|
||||
return $this->em;
|
||||
}
|
||||
}
|
@ -119,4 +119,12 @@ final class Events
|
||||
* @var string
|
||||
*/
|
||||
const onFlush = 'onFlush';
|
||||
|
||||
/**
|
||||
* The onClear event occurs when the EntityManager#clear() operation is invoked,
|
||||
* after all references to entities have been removed from the unit of work.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const onClear = 'onClear';
|
||||
}
|
@ -63,10 +63,10 @@ class ClassMetadata extends ClassMetadataInfo
|
||||
*/
|
||||
public function __construct($entityName)
|
||||
{
|
||||
parent::__construct($entityName);
|
||||
$this->reflClass = new ReflectionClass($entityName);
|
||||
$this->namespace = $this->reflClass->getNamespaceName();
|
||||
$this->table['name'] = $this->reflClass->getShortName();
|
||||
parent::__construct($this->reflClass->getName()); // do not use $entityName, possible case-problems
|
||||
}
|
||||
|
||||
/**
|
||||
@ -334,6 +334,10 @@ class ClassMetadata extends ClassMetadataInfo
|
||||
$serialized[] = 'namedQueries';
|
||||
}
|
||||
|
||||
if ($this->isReadOnly) {
|
||||
$serialized[] = 'isReadOnly';
|
||||
}
|
||||
|
||||
return $serialized;
|
||||
}
|
||||
|
||||
|
@ -484,6 +484,17 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
*/
|
||||
public $reflClass;
|
||||
|
||||
/**
|
||||
* Is this entity marked as "read-only"?
|
||||
*
|
||||
* That means it is never considered for change-tracking in the UnitOfWork. It is a very helpful performance
|
||||
* optimization for entities that are immutable, either in your domain or through the relation database
|
||||
* (coming from a view, or a history table for example).
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $isReadOnly = false;
|
||||
|
||||
/**
|
||||
* Initializes a new ClassMetadata instance that will hold the object-relational mapping
|
||||
* metadata of the class with the given name.
|
||||
@ -1818,4 +1829,14 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
{
|
||||
$this->versionField = $versionField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark this class as read only, no change tracking is applied to it.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function markReadOnly()
|
||||
{
|
||||
$this->isReadOnly = true;
|
||||
}
|
||||
}
|
||||
|
@ -132,6 +132,10 @@ class AnnotationDriver implements Driver
|
||||
if (isset($classAnnotations['Doctrine\ORM\Mapping\Entity'])) {
|
||||
$entityAnnot = $classAnnotations['Doctrine\ORM\Mapping\Entity'];
|
||||
$metadata->setCustomRepositoryClass($entityAnnot->repositoryClass);
|
||||
|
||||
if ($entityAnnot->readOnly) {
|
||||
$metadata->markReadOnly();
|
||||
}
|
||||
} else if (isset($classAnnotations['Doctrine\ORM\Mapping\MappedSuperclass'])) {
|
||||
$metadata->isMappedSuperclass = true;
|
||||
} else {
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $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
|
||||
@ -27,6 +25,7 @@ use Doctrine\Common\Annotations\Annotation;
|
||||
|
||||
final class Entity extends Annotation {
|
||||
public $repositoryClass;
|
||||
public $readOnly = false;
|
||||
}
|
||||
final class MappedSuperclass extends Annotation {}
|
||||
final class InheritanceType extends Annotation {}
|
||||
|
@ -55,6 +55,9 @@ class XmlDriver extends AbstractFileDriver
|
||||
$metadata->setCustomRepositoryClass(
|
||||
isset($xmlRoot['repository-class']) ? (string)$xmlRoot['repository-class'] : null
|
||||
);
|
||||
if (isset($xmlRoot['read-only']) && $xmlRoot['read-only'] == "true") {
|
||||
$metadata->markReadOnly();
|
||||
}
|
||||
} else if ($xmlRoot->getName() == 'mapped-superclass') {
|
||||
$metadata->isMappedSuperclass = true;
|
||||
} else {
|
||||
|
@ -49,6 +49,9 @@ class YamlDriver extends AbstractFileDriver
|
||||
$metadata->setCustomRepositoryClass(
|
||||
isset($element['repositoryClass']) ? $element['repositoryClass'] : null
|
||||
);
|
||||
if (isset($element['readOnly']) && $element['readOnly'] == true) {
|
||||
$metadata->markReadOnly();
|
||||
}
|
||||
} else if ($element['type'] == 'mappedSuperclass') {
|
||||
$metadata->isMappedSuperclass = true;
|
||||
} else {
|
||||
|
@ -375,7 +375,7 @@ class BasicEntityPersister
|
||||
|
||||
$result = $this->_conn->executeUpdate($sql, $params, $types);
|
||||
|
||||
if ($this->_class->isVersioned && ! $result) {
|
||||
if ($versioned && ! $result) {
|
||||
throw OptimisticLockException::lockFailed($entity);
|
||||
}
|
||||
}
|
||||
@ -777,6 +777,7 @@ class BasicEntityPersister
|
||||
$criteria = array();
|
||||
$sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
|
||||
if ($assoc['isOwningSide']) {
|
||||
$quotedJoinTable = $sourceClass->getQuotedJoinTableName($assoc, $this->_platform);
|
||||
foreach ($assoc['relationToSourceKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) {
|
||||
if ($sourceClass->containsForeignIdentifier) {
|
||||
$field = $sourceClass->getFieldForColumn($sourceKeyColumn);
|
||||
@ -785,9 +786,10 @@ class BasicEntityPersister
|
||||
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
|
||||
$value = $value[$this->_em->getClassMetadata($assoc['targetEntity'])->identifier[0]];
|
||||
}
|
||||
$criteria[$relationKeyColumn] = $value;
|
||||
|
||||
$criteria[$quotedJoinTable . "." . $relationKeyColumn] = $value;
|
||||
} else if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
|
||||
$criteria[$relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
||||
$criteria[$quotedJoinTable . "." . $relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
||||
} else {
|
||||
throw MappingException::joinColumnMustPointToMappedField(
|
||||
$sourceClass->name, $sourceKeyColumn
|
||||
@ -796,6 +798,7 @@ class BasicEntityPersister
|
||||
}
|
||||
} else {
|
||||
$owningAssoc = $this->_em->getClassMetadata($assoc['targetEntity'])->associationMappings[$assoc['mappedBy']];
|
||||
$quotedJoinTable = $sourceClass->getQuotedJoinTableName($owningAssoc, $this->_platform);
|
||||
// TRICKY: since the association is inverted source and target are flipped
|
||||
foreach ($owningAssoc['relationToTargetKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) {
|
||||
if ($sourceClass->containsForeignIdentifier) {
|
||||
@ -805,9 +808,9 @@ class BasicEntityPersister
|
||||
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
|
||||
$value = $value[$this->_em->getClassMetadata($assoc['targetEntity'])->identifier[0]];
|
||||
}
|
||||
$criteria[$relationKeyColumn] = $value;
|
||||
$criteria[$quotedJoinTable . "." . $relationKeyColumn] = $value;
|
||||
} else if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
|
||||
$criteria[$relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
||||
$criteria[$quotedJoinTable . "." . $relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
||||
} else {
|
||||
throw MappingException::joinColumnMustPointToMappedField(
|
||||
$sourceClass->name, $sourceKeyColumn
|
||||
@ -1194,18 +1197,16 @@ class BasicEntityPersister
|
||||
}
|
||||
|
||||
$conditionSql .= $this->_class->associationMappings[$field]['joinColumns'][0]['name'];
|
||||
} else if ($assoc !== null) {
|
||||
if ($assoc['type'] == ClassMetadata::MANY_TO_MANY) {
|
||||
$owningAssoc = $assoc['isOwningSide'] ? $assoc : $this->_em->getClassMetadata($assoc['targetEntity'])
|
||||
->associationMappings[$assoc['mappedBy']];
|
||||
$conditionSql .= $this->_class->getQuotedJoinTableName($owningAssoc, $this->_platform) . '.' . $field;
|
||||
} else {
|
||||
$conditionSql .= $field;
|
||||
}
|
||||
} else if ($assoc !== null && strpos($field, " ") === false && strpos($field, "(") === false) {
|
||||
// very careless developers could potentially open up this normally hidden api for userland attacks,
|
||||
// therefore checking for spaces and function calls which are not allowed.
|
||||
|
||||
// found a join column condition, not really a "field"
|
||||
$conditionSql .= $field;
|
||||
} else {
|
||||
throw ORMException::unrecognizedField($field);
|
||||
}
|
||||
$conditionSql .= (is_array($value)) ? ' IN (?)' : ' = ?';
|
||||
$conditionSql .= (is_array($value)) ? ' IN (?)' : (($value === null) ? ' IS NULL' : ' = ?');
|
||||
}
|
||||
return $conditionSql;
|
||||
}
|
||||
@ -1254,6 +1255,11 @@ class BasicEntityPersister
|
||||
$criteria = array();
|
||||
$owningAssoc = $this->_class->associationMappings[$assoc['mappedBy']];
|
||||
$sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
|
||||
|
||||
$tableAlias = isset($owningAssoc['inherited']) ?
|
||||
$this->_getSQLTableAlias($owningAssoc['inherited'])
|
||||
: $this->_getSQLTableAlias($this->_class->name);
|
||||
|
||||
foreach ($owningAssoc['targetToSourceKeyColumns'] as $sourceKeyColumn => $targetKeyColumn) {
|
||||
if ($sourceClass->containsForeignIdentifier) {
|
||||
$field = $sourceClass->getFieldForColumn($sourceKeyColumn);
|
||||
@ -1262,9 +1268,9 @@ class BasicEntityPersister
|
||||
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
|
||||
$value = $value[$this->_em->getClassMetadata($assoc['targetEntity'])->identifier[0]];
|
||||
}
|
||||
$criteria[$targetKeyColumn] = $value;
|
||||
$criteria[$tableAlias . "." . $targetKeyColumn] = $value;
|
||||
} else {
|
||||
$criteria[$targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
||||
$criteria[$tableAlias . "." . $targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1285,6 +1291,10 @@ class BasicEntityPersister
|
||||
$params = $types = array();
|
||||
|
||||
foreach ($criteria AS $field => $value) {
|
||||
if ($value === null) {
|
||||
continue; // skip null values.
|
||||
}
|
||||
|
||||
$type = null;
|
||||
if (isset($this->_class->fieldMappings[$field])) {
|
||||
$type = Type::getType($this->_class->fieldMappings[$field]['type'])->getBindingType();
|
||||
|
@ -249,7 +249,12 @@ final class Query extends AbstractQuery
|
||||
$idValues = $class->getIdentifierValues($value);
|
||||
}
|
||||
$sqlPositions = $paramMappings[$key];
|
||||
$sqlParams += array_combine((array)$sqlPositions, $idValues);
|
||||
$cSqlPos = count($sqlPositions);
|
||||
$cIdValues = count($idValues);
|
||||
$idValues = array_values($idValues);
|
||||
for ($i = 0; $i < $cSqlPos; $i++) {
|
||||
$sqlParams[$sqlPositions[$i]] = $idValues[ ($i % $cIdValues) ];
|
||||
}
|
||||
} else {
|
||||
foreach ($paramMappings[$key] as $position) {
|
||||
$sqlParams[$position] = $value;
|
||||
|
71
lib/Doctrine/ORM/Query/AST/Functions/DateAddFunction.php
Normal file
71
lib/Doctrine/ORM/Query/AST/Functions/DateAddFunction.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/*
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Query\AST\Functions;
|
||||
|
||||
use Doctrine\ORM\Query\Lexer;
|
||||
use Doctrine\ORM\Query\SqlWalker;
|
||||
use Doctrine\ORM\Query\Parser;
|
||||
use Doctrine\ORM\Query\QueryException;
|
||||
|
||||
/**
|
||||
* "DATE_ADD(date1, interval, unit)"
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
*/
|
||||
class DateAddFunction extends FunctionNode
|
||||
{
|
||||
public $firstDateExpression = null;
|
||||
public $intervalExpression = null;
|
||||
public $unit = null;
|
||||
|
||||
public function getSql(SqlWalker $sqlWalker)
|
||||
{
|
||||
$unit = strtolower($this->unit);
|
||||
if ($unit == "day") {
|
||||
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddDaysExpression(
|
||||
$this->firstDateExpression->dispatch($sqlWalker),
|
||||
$this->intervalExpression->dispatch($sqlWalker)
|
||||
);
|
||||
} else if ($unit == "month") {
|
||||
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddMonthExpression(
|
||||
$this->firstDateExpression->dispatch($sqlWalker),
|
||||
$this->intervalExpression->dispatch($sqlWalker)
|
||||
);
|
||||
} else {
|
||||
throw QueryException::semanticalError('DATE_ADD() only supports units of type day and month.');
|
||||
}
|
||||
}
|
||||
|
||||
public function parse(Parser $parser)
|
||||
{
|
||||
$parser->match(Lexer::T_IDENTIFIER);
|
||||
$parser->match(Lexer::T_OPEN_PARENTHESIS);
|
||||
|
||||
$this->firstDateExpression = $parser->ArithmeticPrimary();
|
||||
$parser->match(Lexer::T_COMMA);
|
||||
$this->intervalExpression = $parser->ArithmeticPrimary();
|
||||
$parser->match(Lexer::T_COMMA);
|
||||
$this->unit = $parser->StringPrimary();
|
||||
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
|
||||
}
|
||||
}
|
58
lib/Doctrine/ORM/Query/AST/Functions/DateDiffFunction.php
Normal file
58
lib/Doctrine/ORM/Query/AST/Functions/DateDiffFunction.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/*
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Query\AST\Functions;
|
||||
|
||||
use Doctrine\ORM\Query\Lexer;
|
||||
use Doctrine\ORM\Query\SqlWalker;
|
||||
use Doctrine\ORM\Query\Parser;
|
||||
|
||||
/**
|
||||
* "DATE_DIFF(date1, date2)"
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
*/
|
||||
class DateDiffFunction extends FunctionNode
|
||||
{
|
||||
public $date1;
|
||||
public $date2;
|
||||
|
||||
public function getSql(SqlWalker $sqlWalker)
|
||||
{
|
||||
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateDiffExpression(
|
||||
$this->date1->dispatch($sqlWalker),
|
||||
$this->date2->dispatch($sqlWalker)
|
||||
);
|
||||
}
|
||||
|
||||
public function parse(Parser $parser)
|
||||
{
|
||||
$parser->match(Lexer::T_IDENTIFIER);
|
||||
$parser->match(Lexer::T_OPEN_PARENTHESIS);
|
||||
|
||||
$this->date1 = $parser->ArithmeticPrimary();
|
||||
$parser->match(Lexer::T_COMMA);
|
||||
$this->date2 = $parser->ArithmeticPrimary();
|
||||
|
||||
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
|
||||
}
|
||||
}
|
58
lib/Doctrine/ORM/Query/AST/Functions/DateSubFunction.php
Normal file
58
lib/Doctrine/ORM/Query/AST/Functions/DateSubFunction.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/*
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Query\AST\Functions;
|
||||
|
||||
use Doctrine\ORM\Query\Lexer;
|
||||
use Doctrine\ORM\Query\SqlWalker;
|
||||
use Doctrine\ORM\Query\Parser;
|
||||
use Doctrine\ORM\Query\QueryException;
|
||||
|
||||
/**
|
||||
* "DATE_ADD(date1, interval, unit)"
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
*/
|
||||
class DateSubFunction extends DateAddFunction
|
||||
{
|
||||
public $firstDateExpression = null;
|
||||
public $intervalExpression = null;
|
||||
public $unit = null;
|
||||
|
||||
public function getSql(SqlWalker $sqlWalker)
|
||||
{
|
||||
$unit = strtolower($this->unit);
|
||||
if ($unit == "day") {
|
||||
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubDaysExpression(
|
||||
$this->firstDateExpression->dispatch($sqlWalker),
|
||||
$this->intervalExpression->dispatch($sqlWalker)
|
||||
);
|
||||
} else if ($unit == "month") {
|
||||
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubMonthExpression(
|
||||
$this->firstDateExpression->dispatch($sqlWalker),
|
||||
$this->intervalExpression->dispatch($sqlWalker)
|
||||
);
|
||||
} else {
|
||||
throw QueryException::semanticalError('DATE_SUB() only supports units of type day and month.');
|
||||
}
|
||||
}
|
||||
}
|
@ -45,19 +45,22 @@ class Parser
|
||||
|
||||
/** READ-ONLY: Maps BUILT-IN numeric function names to AST class names. */
|
||||
private static $_NUMERIC_FUNCTIONS = array(
|
||||
'length' => 'Doctrine\ORM\Query\AST\Functions\LengthFunction',
|
||||
'locate' => 'Doctrine\ORM\Query\AST\Functions\LocateFunction',
|
||||
'abs' => 'Doctrine\ORM\Query\AST\Functions\AbsFunction',
|
||||
'sqrt' => 'Doctrine\ORM\Query\AST\Functions\SqrtFunction',
|
||||
'mod' => 'Doctrine\ORM\Query\AST\Functions\ModFunction',
|
||||
'size' => 'Doctrine\ORM\Query\AST\Functions\SizeFunction'
|
||||
'length' => 'Doctrine\ORM\Query\AST\Functions\LengthFunction',
|
||||
'locate' => 'Doctrine\ORM\Query\AST\Functions\LocateFunction',
|
||||
'abs' => 'Doctrine\ORM\Query\AST\Functions\AbsFunction',
|
||||
'sqrt' => 'Doctrine\ORM\Query\AST\Functions\SqrtFunction',
|
||||
'mod' => 'Doctrine\ORM\Query\AST\Functions\ModFunction',
|
||||
'size' => 'Doctrine\ORM\Query\AST\Functions\SizeFunction',
|
||||
'date_diff' => 'Doctrine\ORM\Query\AST\Functions\DateDiffFunction',
|
||||
);
|
||||
|
||||
/** READ-ONLY: Maps BUILT-IN datetime function names to AST class names. */
|
||||
private static $_DATETIME_FUNCTIONS = array(
|
||||
'current_date' => 'Doctrine\ORM\Query\AST\Functions\CurrentDateFunction',
|
||||
'current_time' => 'Doctrine\ORM\Query\AST\Functions\CurrentTimeFunction',
|
||||
'current_timestamp' => 'Doctrine\ORM\Query\AST\Functions\CurrentTimestampFunction'
|
||||
'current_timestamp' => 'Doctrine\ORM\Query\AST\Functions\CurrentTimestampFunction',
|
||||
'date_add' => 'Doctrine\ORM\Query\AST\Functions\DateAddFunction',
|
||||
'date_sub' => 'Doctrine\ORM\Query\AST\Functions\DateSubFunction',
|
||||
);
|
||||
|
||||
/**
|
||||
@ -1328,6 +1331,10 @@ class Parser
|
||||
$token = $this->_lexer->lookahead;
|
||||
$identVariable = $this->IdentificationVariable();
|
||||
|
||||
if (!isset($this->_queryComponents[$identVariable])) {
|
||||
$this->semanticalError('Cannot group by undefined identification variable.');
|
||||
}
|
||||
|
||||
return $identVariable;
|
||||
}
|
||||
|
||||
@ -1637,7 +1644,7 @@ class Parser
|
||||
return $this->StateFieldPathExpression();
|
||||
} else if ($lookahead == Lexer::T_INTEGER || $lookahead == Lexer::T_FLOAT) {
|
||||
return $this->SimpleArithmeticExpression();
|
||||
} else if ($this->_isFunction()) {
|
||||
} else if ($this->_isFunction() || $this->_isAggregateFunction($this->_lexer->lookahead['type'])) {
|
||||
// We may be in an ArithmeticExpression (find the matching ")" and inspect for Math operator)
|
||||
$this->_lexer->peek(); // "("
|
||||
$peek = $this->_peekBeyondClosingParenthesis();
|
||||
@ -1645,8 +1652,12 @@ class Parser
|
||||
if ($this->_isMathOperator($peek)) {
|
||||
return $this->SimpleArithmeticExpression();
|
||||
}
|
||||
|
||||
return $this->FunctionDeclaration();
|
||||
|
||||
if ($this->_isAggregateFunction($this->_lexer->lookahead['type'])) {
|
||||
return $this->AggregateExpression();
|
||||
} else {
|
||||
return $this->FunctionDeclaration();
|
||||
}
|
||||
} else if ($lookahead == Lexer::T_STRING) {
|
||||
return $this->StringPrimary();
|
||||
} else if ($lookahead == Lexer::T_INPUT_PARAMETER) {
|
||||
@ -1721,7 +1732,8 @@ class Parser
|
||||
$expression = $this->PartialObjectExpression();
|
||||
$identVariable = $expression->identificationVariable;
|
||||
} else if ($this->_lexer->lookahead['type'] == Lexer::T_INTEGER ||
|
||||
$this->_lexer->lookahead['type'] == Lexer::T_FLOAT) {
|
||||
$this->_lexer->lookahead['type'] == Lexer::T_FLOAT ||
|
||||
$this->_lexer->lookahead['type'] == Lexer::T_STRING) {
|
||||
// Shortcut: ScalarExpression => SimpleArithmeticExpression
|
||||
$expression = $this->SimpleArithmeticExpression();
|
||||
} else {
|
||||
@ -1790,15 +1802,8 @@ class Parser
|
||||
}
|
||||
|
||||
$this->_lexer->peek();
|
||||
$beyond = $this->_peekBeyondClosingParenthesis();
|
||||
|
||||
if ($this->_isMathOperator($beyond)) {
|
||||
$expression = $this->ScalarExpression();
|
||||
} else if ($this->_isAggregateFunction($this->_lexer->lookahead['type'])) {
|
||||
$expression = $this->AggregateExpression();
|
||||
} else {
|
||||
$expression = $this->FunctionDeclaration();
|
||||
}
|
||||
$expression = $this->ScalarExpression();
|
||||
|
||||
$expr = new AST\SimpleSelectExpression($expression);
|
||||
|
||||
|
@ -75,8 +75,7 @@ class QueryException extends \Doctrine\ORM\ORMException
|
||||
public static function invalidPathExpression($pathExpr)
|
||||
{
|
||||
return new self(
|
||||
"Invalid PathExpression '" . $pathExpr->identificationVariable .
|
||||
"." . implode('.', $pathExpr->parts) . "'."
|
||||
"Invalid PathExpression '" . $pathExpr->identificationVariable . "." . $pathExpr->field . "'."
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -961,7 +961,8 @@ class SqlWalker implements TreeWalker
|
||||
$expr instanceof AST\SimpleArithmeticExpression ||
|
||||
$expr instanceof AST\ArithmeticTerm ||
|
||||
$expr instanceof AST\ArithmeticFactor ||
|
||||
$expr instanceof AST\ArithmeticPrimary
|
||||
$expr instanceof AST\ArithmeticPrimary ||
|
||||
$expr instanceof AST\Literal
|
||||
) {
|
||||
if ( ! $selectExpression->fieldIdentificationVariable) {
|
||||
$resultAlias = $this->_scalarResultCounter++;
|
||||
@ -970,7 +971,11 @@ class SqlWalker implements TreeWalker
|
||||
}
|
||||
|
||||
$columnAlias = 'sclr' . $this->_aliasCounter++;
|
||||
$sql .= $this->walkSimpleArithmeticExpression($expr) . ' AS ' . $columnAlias;
|
||||
if ($expr instanceof AST\Literal) {
|
||||
$sql .= $this->walkLiteral($expr) . ' AS ' .$columnAlias;
|
||||
} else {
|
||||
$sql .= $this->walkSimpleArithmeticExpression($expr) . ' AS ' . $columnAlias;
|
||||
}
|
||||
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
|
||||
|
||||
$columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
|
||||
@ -1254,9 +1259,25 @@ class SqlWalker implements TreeWalker
|
||||
*/
|
||||
public function walkGroupByClause($groupByClause)
|
||||
{
|
||||
return ' GROUP BY ' . implode(
|
||||
', ', array_map(array($this, 'walkGroupByItem'), $groupByClause->groupByItems)
|
||||
);
|
||||
$sql = '';
|
||||
foreach ($groupByClause->groupByItems AS $groupByItem) {
|
||||
if (is_string($groupByItem)) {
|
||||
foreach ($this->_queryComponents[$groupByItem]['metadata']->identifier AS $idField) {
|
||||
if ($sql != '') {
|
||||
$sql .= ', ';
|
||||
}
|
||||
$groupByItem = new AST\PathExpression(AST\PathExpression::TYPE_STATE_FIELD, $groupByItem, $idField);
|
||||
$groupByItem->type = AST\PathExpression::TYPE_STATE_FIELD;
|
||||
$sql .= $this->walkGroupByItem($groupByItem);
|
||||
}
|
||||
} else {
|
||||
if ($sql != '') {
|
||||
$sql .= ', ';
|
||||
}
|
||||
$sql .= $this->walkGroupByItem($groupByItem);
|
||||
}
|
||||
}
|
||||
return ' GROUP BY ' . $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -514,9 +514,9 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$class = $this->em->getClassMetadata($className);
|
||||
|
||||
// Skip class if instances are read-only
|
||||
//if ($class->isReadOnly) {
|
||||
// continue;
|
||||
//}
|
||||
if ($class->isReadOnly) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If change tracking is explicit or happens through notification, then only compute
|
||||
// changes on entities of that type that are explicitly marked for synchronization.
|
||||
@ -1790,6 +1790,10 @@ class UnitOfWork implements PropertyChangedListener
|
||||
if ($this->commitOrderCalculator !== null) {
|
||||
$this->commitOrderCalculator->clear();
|
||||
}
|
||||
|
||||
if ($this->evm->hasListeners(Events::onClear)) {
|
||||
$this->evm->dispatchEvent(Events::onClear, new Event\OnClearEventArgs($this->em));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
2
lib/vendor/doctrine-dbal
vendored
2
lib/vendor/doctrine-dbal
vendored
@ -1 +1 @@
|
||||
Subproject commit 9cd6df38d841abb4719286ea35a1b37aa2679f8d
|
||||
Subproject commit 0a99438729e59bcb5262b22c06c782de4dfacbb0
|
@ -58,6 +58,8 @@ class AllTests
|
||||
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\DatabaseDriverTest');
|
||||
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\PostgreSQLIdentityStrategyTest');
|
||||
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\ExtraLazyCollectionTest');
|
||||
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\ClearEventTest');
|
||||
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\ReadOnlyTest');
|
||||
|
||||
$suite->addTest(Locking\AllTests::suite());
|
||||
$suite->addTest(Ticket\AllTests::suite());
|
||||
|
@ -410,4 +410,29 @@ class ClassTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$ref = $this->_em->getReference('Doctrine\Tests\Models\Company\CompanyManager', $manager->getId());
|
||||
$this->assertInstanceOf('Doctrine\ORM\Proxy\Proxy', $ref, "A proxy can be generated only if no subclasses exists for the requested reference.");
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-992
|
||||
*/
|
||||
public function testGetSubClassManyToManyCollection()
|
||||
{
|
||||
$manager = new CompanyManager();
|
||||
$manager->setName('gblanco');
|
||||
$manager->setSalary(1234);
|
||||
$manager->setTitle('Awesome!');
|
||||
$manager->setDepartment('IT');
|
||||
|
||||
$person = new CompanyPerson();
|
||||
$person->setName('friend');
|
||||
|
||||
$manager->addFriend($person);
|
||||
|
||||
$this->_em->persist($manager);
|
||||
$this->_em->persist($person);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$manager = $this->_em->find('Doctrine\Tests\Models\Company\CompanyManager', $manager->getId());
|
||||
$this->assertEquals(1, count($manager->getFriends()));
|
||||
}
|
||||
}
|
||||
|
40
tests/Doctrine/Tests/ORM/Functional/ClearEventTest.php
Normal file
40
tests/Doctrine/Tests/ORM/Functional/ClearEventTest.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional;
|
||||
|
||||
use Doctrine\ORM\Event\OnClearEventArgs;
|
||||
use Doctrine\ORM\Events;
|
||||
|
||||
require_once __DIR__ . '/../../TestInit.php';
|
||||
|
||||
/**
|
||||
* ClearEventTest
|
||||
*
|
||||
* @author Michael Ridgway <mcridgway@gmail.com>
|
||||
*/
|
||||
class ClearEventTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
public function testEventIsCalledOnClear()
|
||||
{
|
||||
$listener = new OnClearListener;
|
||||
$this->_em->getEventManager()->addEventListener(Events::onClear, $listener);
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
$this->assertTrue($listener->called);
|
||||
}
|
||||
}
|
||||
|
||||
class OnClearListener
|
||||
{
|
||||
public $called = false;
|
||||
|
||||
public function onClear(OnClearEventArgs $args)
|
||||
{
|
||||
$this->called = true;
|
||||
}
|
||||
}
|
@ -307,5 +307,18 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$repos->createNamedQuery('invalidNamedQuery');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1087
|
||||
*/
|
||||
public function testIsNullCriteria()
|
||||
{
|
||||
$repos = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsUser');
|
||||
$users = $repos->findBy(array('status' => null, 'username' => 'romanb'));
|
||||
|
||||
$params = $this->_sqlLoggerStack->queries[$this->_sqlLoggerStack->currentQuery]['params'];
|
||||
$this->assertEquals(1, count($params), "Should only execute with one parameter.");
|
||||
$this->assertEquals(array('romanb'), $params);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -268,7 +268,49 @@ class QueryDqlFunctionTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertEquals('Guilherme B.Complaint Department', $arg[2]['namedep']);
|
||||
$this->assertEquals('Benjamin E.HR', $arg[3]['namedep']);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-1014
|
||||
*/
|
||||
public function testDateDiff()
|
||||
{
|
||||
$arg = $this->_em->createQuery("SELECT DATE_DIFF(CURRENT_TIMESTAMP(), '2011-01-01') AS diff FROM Doctrine\Tests\Models\Company\CompanyManager m")
|
||||
->getARrayResult();
|
||||
|
||||
$this->assertTrue($arg[0]['diff'] > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1014
|
||||
*/
|
||||
public function testDateAdd()
|
||||
{
|
||||
$arg = $this->_em->createQuery("SELECT DATE_ADD(CURRENT_TIMESTAMP(), 10, 'day') AS add FROM Doctrine\Tests\Models\Company\CompanyManager m")
|
||||
->getArrayResult();
|
||||
|
||||
$this->assertTrue(strtotime($arg[0]['add']) > 0);
|
||||
|
||||
$arg = $this->_em->createQuery("SELECT DATE_ADD(CURRENT_TIMESTAMP(), 10, 'month') AS add FROM Doctrine\Tests\Models\Company\CompanyManager m")
|
||||
->getArrayResult();
|
||||
|
||||
$this->assertTrue(strtotime($arg[0]['add']) > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1014
|
||||
*/
|
||||
public function testDateSub()
|
||||
{
|
||||
$arg = $this->_em->createQuery("SELECT DATE_SUB(CURRENT_TIMESTAMP(), 10, 'day') AS add FROM Doctrine\Tests\Models\Company\CompanyManager m")
|
||||
->getArrayResult();
|
||||
|
||||
$this->assertTrue(strtotime($arg[0]['add']) > 0);
|
||||
|
||||
$arg = $this->_em->createQuery("SELECT DATE_SUB(CURRENT_TIMESTAMP(), 10, 'month') AS add FROM Doctrine\Tests\Models\Company\CompanyManager m")
|
||||
->getArrayResult();
|
||||
|
||||
$this->assertTrue(strtotime($arg[0]['add']) > 0);
|
||||
}
|
||||
|
||||
protected function generateFixture()
|
||||
{
|
||||
|
@ -5,6 +5,7 @@ namespace Doctrine\Tests\ORM\Functional;
|
||||
use Doctrine\Tests\Models\CMS\CmsUser,
|
||||
Doctrine\Tests\Models\CMS\CmsArticle;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Query;
|
||||
|
||||
require_once __DIR__ . '/../../TestInit.php';
|
||||
|
||||
@ -136,6 +137,39 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$users = $q->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1070
|
||||
*/
|
||||
public function testIterateResultAsArrayAndParams()
|
||||
{
|
||||
$article1 = new CmsArticle;
|
||||
$article1->topic = "Doctrine 2";
|
||||
$article1->text = "This is an introduction to Doctrine 2.";
|
||||
|
||||
$article2 = new CmsArticle;
|
||||
$article2->topic = "Symfony 2";
|
||||
$article2->text = "This is an introduction to Symfony 2.";
|
||||
|
||||
$this->_em->persist($article1);
|
||||
$this->_em->persist($article2);
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
$articleId = $article1->id;
|
||||
|
||||
$query = $this->_em->createQuery("select a from Doctrine\Tests\Models\CMS\CmsArticle a WHERE a.topic = ?1");
|
||||
$articles = $query->iterate(array(1 => 'Doctrine 2'), Query::HYDRATE_ARRAY);
|
||||
|
||||
$found = array();
|
||||
foreach ($articles AS $article) {
|
||||
$found[] = $article;
|
||||
}
|
||||
$this->assertEquals(1, count($found));
|
||||
$this->assertEquals(array(
|
||||
array(array('id' => $articleId, 'topic' => 'Doctrine 2', 'text' => 'This is an introduction to Doctrine 2.', 'version' => 1))
|
||||
), $found);
|
||||
}
|
||||
|
||||
public function testIterateResult_IterativelyBuildUpUnitOfWork()
|
||||
{
|
||||
$article1 = new CmsArticle;
|
||||
@ -344,4 +378,64 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertNotInstanceOf('Doctrine\ORM\Proxy\Proxy', $article);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-991
|
||||
*/
|
||||
public function testgetOneOrNullResult()
|
||||
{
|
||||
$user = new CmsUser;
|
||||
$user->name = 'Guilherme';
|
||||
$user->username = 'gblanco';
|
||||
$user->status = 'developer';
|
||||
$this->_em->persist($user);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$query = $this->_em->createQuery("select u from Doctrine\Tests\Models\CMS\CmsUser u where u.username = 'gblanco'");
|
||||
|
||||
$fetchedUser = $query->getOneOrNullResult();
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $fetchedUser);
|
||||
$this->assertEquals('gblanco', $fetchedUser->username);
|
||||
|
||||
$query = $this->_em->createQuery("select u.username from Doctrine\Tests\Models\CMS\CmsUser u where u.username = 'gblanco'");
|
||||
$fetchedUsername = $query->getOneOrNullResult(Query::HYDRATE_SINGLE_SCALAR);
|
||||
$this->assertEquals('gblanco', $fetchedUsername);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-991
|
||||
*/
|
||||
public function testgetOneOrNullResultSeveralRows()
|
||||
{
|
||||
$user = new CmsUser;
|
||||
$user->name = 'Guilherme';
|
||||
$user->username = 'gblanco';
|
||||
$user->status = 'developer';
|
||||
$this->_em->persist($user);
|
||||
$user = new CmsUser;
|
||||
$user->name = 'Roman';
|
||||
$user->username = 'romanb';
|
||||
$user->status = 'developer';
|
||||
$this->_em->persist($user);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$query = $this->_em->createQuery("select u from Doctrine\Tests\Models\CMS\CmsUser u");
|
||||
|
||||
$this->setExpectedException('Doctrine\ORM\NonUniqueResultException');
|
||||
$fetchedUser = $query->getOneOrNullResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-991
|
||||
*/
|
||||
public function testgetOneOrNullResultNoRows()
|
||||
{
|
||||
$query = $this->_em->createQuery("select u from Doctrine\Tests\Models\CMS\CmsUser u");
|
||||
$this->assertNull($query->getOneOrNullResult());
|
||||
|
||||
$query = $this->_em->createQuery("select u.username from Doctrine\Tests\Models\CMS\CmsUser u where u.username = 'gblanco'");
|
||||
$this->assertNull($query->getOneOrNullResult(Query::HYDRATE_SCALAR));
|
||||
}
|
||||
}
|
61
tests/Doctrine/Tests/ORM/Functional/ReadOnlyTest.php
Normal file
61
tests/Doctrine/Tests/ORM/Functional/ReadOnlyTest.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional;
|
||||
|
||||
require_once __DIR__ . '/../../TestInit.php';
|
||||
|
||||
/**
|
||||
* Functional Query tests.
|
||||
*
|
||||
* @group DDC-692
|
||||
*/
|
||||
class ReadOnlyTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\ReadOnlyEntity'),
|
||||
));
|
||||
}
|
||||
|
||||
public function testReadOnlyEntityNeverChangeTracked()
|
||||
{
|
||||
$readOnly = new ReadOnlyEntity("Test1", 1234);
|
||||
$this->_em->persist($readOnly);
|
||||
$this->_em->flush();
|
||||
|
||||
$readOnly->name = "Test2";
|
||||
$readOnly->number = 4321;
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$dbReadOnly = $this->_em->find('Doctrine\Tests\ORM\Functional\ReadOnlyEntity', $readOnly->id);
|
||||
$this->assertEquals("Test1", $dbReadOnly->name);
|
||||
$this->assertEquals(1234, $dbReadOnly->number);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity(readOnly=true)
|
||||
*/
|
||||
class ReadOnlyEntity
|
||||
{
|
||||
/**
|
||||
* @Id @GeneratedValue @Column(type="integer")
|
||||
* @var int
|
||||
*/
|
||||
public $id;
|
||||
/** @column(type="string") */
|
||||
public $name;
|
||||
/** @Column(type="integer") */
|
||||
public $number;
|
||||
|
||||
public function __construct($name, $number)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->number = $number;
|
||||
}
|
||||
}
|
83
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1040Test.php
Normal file
83
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1040Test.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Tests\Models\CMS\CmsArticle;
|
||||
use Doctrine\Tests\Models\CMS\CmsUser;
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
/**
|
||||
* @group DDC-1040
|
||||
*/
|
||||
class DDC1040Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
$this->useModelSet('cms');
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
public function testReuseNamedEntityParameter()
|
||||
{
|
||||
$user = new CmsUser();
|
||||
$user->name = "John Galt";
|
||||
$user->username = "jgalt";
|
||||
$user->status = "inactive";
|
||||
|
||||
$article = new CmsArticle();
|
||||
$article->topic = "This is John Galt speaking!";
|
||||
$article->text = "Yadda Yadda!";
|
||||
$article->setAuthor($user);
|
||||
|
||||
$this->_em->persist($user);
|
||||
$this->_em->persist($article);
|
||||
$this->_em->flush();
|
||||
|
||||
$dql = "SELECT a FROM Doctrine\Tests\Models\CMS\CmsArticle a WHERE a.user = :author";
|
||||
$this->_em->createQuery($dql)
|
||||
->setParameter('author', $user)
|
||||
->getResult();
|
||||
|
||||
$dql = "SELECT a FROM Doctrine\Tests\Models\CMS\CmsArticle a WHERE a.user = :author AND a.user = :author";
|
||||
$this->_em->createQuery($dql)
|
||||
->setParameter('author', $user)
|
||||
->getResult();
|
||||
|
||||
$dql = "SELECT a FROM Doctrine\Tests\Models\CMS\CmsArticle a WHERE a.topic = :topic AND a.user = :author AND a.user = :author AND a.text = :text";
|
||||
$farticle = $this->_em->createQuery($dql)
|
||||
->setParameter('author', $user)
|
||||
->setParameter('topic', 'This is John Galt speaking!')
|
||||
->setParameter('text', 'Yadda Yadda!')
|
||||
->getSingleResult();
|
||||
|
||||
$this->assertSame($article, $farticle);
|
||||
}
|
||||
|
||||
public function testUseMultiplePositionalParameters()
|
||||
{
|
||||
$user = new CmsUser();
|
||||
$user->name = "John Galt";
|
||||
$user->username = "jgalt";
|
||||
$user->status = "inactive";
|
||||
|
||||
$article = new CmsArticle();
|
||||
$article->topic = "This is John Galt speaking!";
|
||||
$article->text = "Yadda Yadda!";
|
||||
$article->setAuthor($user);
|
||||
|
||||
$this->_em->persist($user);
|
||||
$this->_em->persist($article);
|
||||
$this->_em->flush();
|
||||
|
||||
$dql = "SELECT a FROM Doctrine\Tests\Models\CMS\CmsArticle a WHERE a.topic = ?1 AND a.user = ?2 AND a.user = ?3 AND a.text = ?4";
|
||||
$farticle = $this->_em->createQuery($dql)
|
||||
->setParameter(1, 'This is John Galt speaking!')
|
||||
->setParameter(2, $user)
|
||||
->setParameter(3, $user)
|
||||
->setParameter(4, 'Yadda Yadda!')
|
||||
->getSingleResult();
|
||||
|
||||
$this->assertSame($article, $farticle);
|
||||
}
|
||||
}
|
147
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC992Test.php
Normal file
147
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC992Test.php
Normal file
@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
/**
|
||||
* @group DDC-992
|
||||
*/
|
||||
class DDC992Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
try {
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC992Role'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC992Parent'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC992Child'),
|
||||
));
|
||||
} catch(\Exception $e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public function testIssue()
|
||||
{
|
||||
$role = new DDC992Role();
|
||||
$role->name = "Parent";
|
||||
$child = new DDC992Role();
|
||||
$child->name = "child";
|
||||
|
||||
$role->extendedBy[] = $child;
|
||||
$child->extends[] = $role;
|
||||
|
||||
$this->_em->persist($role);
|
||||
$this->_em->persist($child);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$child = $this->_em->getRepository(get_class($role))->find($child->roleID);
|
||||
$parents = count($child->extends);
|
||||
$this->assertEquals(1, $parents);
|
||||
foreach ($child->extends AS $parent) {
|
||||
$this->assertEquals($role->getRoleID(), $parent->getRoleID());
|
||||
}
|
||||
}
|
||||
|
||||
public function testOneToManyChild()
|
||||
{
|
||||
$parent = new DDC992Parent();
|
||||
$child = new DDC992Child();
|
||||
$child->parent = $parent;
|
||||
$parent->childs[] = $child;
|
||||
|
||||
$this->_em->persist($parent);
|
||||
$this->_em->persist($child);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$parentRepository = $this->_em->getRepository(get_class($parent));
|
||||
$childRepository = $this->_em->getRepository(get_class($child));
|
||||
|
||||
$parent = $parentRepository->find($parent->id);
|
||||
$this->assertEquals(1, count($parent->childs));
|
||||
$this->assertEquals(0, count($parent->childs[0]->childs()));
|
||||
|
||||
$child = $parentRepository->findOneBy(array("id" => $child->id));
|
||||
$this->assertSame($parent->childs[0], $child);
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
$child = $parentRepository->find($child->id);
|
||||
$this->assertEquals(0, count($child->childs));
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
$child = $childRepository->find($child->id);
|
||||
$this->assertEquals(0, count($child->childs));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @InheritanceType("JOINED")
|
||||
* @DiscriminatorMap({"child" = "DDC992Child", "parent" = "DDC992Parent"})
|
||||
*/
|
||||
class DDC992Parent
|
||||
{
|
||||
/** @Id @GeneratedValue @Column(type="integer") */
|
||||
public $id;
|
||||
/** @ManyToOne(targetEntity="DDC992Parent", inversedBy="childs") */
|
||||
public $parent;
|
||||
/** @OneToMany(targetEntity="DDC992Child", mappedBy="parent") */
|
||||
public $childs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC992Child extends DDC992Parent
|
||||
{
|
||||
public function childs()
|
||||
{
|
||||
return $this->childs;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC992Role
|
||||
{
|
||||
public function getRoleID()
|
||||
{
|
||||
return $this->roleID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Id @Column(name="roleID", type="integer")
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
public $roleID;
|
||||
/**
|
||||
* @Column (name="name", type="string", length="45")
|
||||
*/
|
||||
public $name;
|
||||
/**
|
||||
* @ManyToMany (targetEntity="DDC992Role", mappedBy="extends")
|
||||
*/
|
||||
public $extendedBy;
|
||||
/**
|
||||
* @ManyToMany (targetEntity="DDC992Role", inversedBy="extendedBy")
|
||||
* @JoinTable (name="RoleRelations",
|
||||
* joinColumns={@JoinColumn(name="roleID", referencedColumnName="roleID")},
|
||||
* inverseJoinColumns={@JoinColumn(name="extendsRoleID", referencedColumnName="roleID")}
|
||||
* )
|
||||
*/
|
||||
public $extends;
|
||||
|
||||
public function __construct() {
|
||||
$this->extends = new ArrayCollection;
|
||||
$this->extendedBy = new ArrayCollection;
|
||||
}
|
||||
}
|
@ -30,6 +30,8 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
|
||||
$cm->setCustomRepositoryClass("UserRepository");
|
||||
$cm->setDiscriminatorColumn(array('name' => 'disc', 'type' => 'integer'));
|
||||
$cm->mapOneToOne(array('fieldName' => 'phonenumbers', 'targetEntity' => 'Bar', 'mappedBy' => 'foo'));
|
||||
$cm->markReadOnly();
|
||||
$cm->addNamedQuery(array('name' => 'dql', 'query' => 'foo'));
|
||||
$this->assertEquals(1, count($cm->associationMappings));
|
||||
|
||||
$serialized = serialize($cm);
|
||||
@ -51,6 +53,8 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
|
||||
$this->assertTrue($oneOneMapping['fetch'] == ClassMetadata::FETCH_LAZY);
|
||||
$this->assertEquals('phonenumbers', $oneOneMapping['fieldName']);
|
||||
$this->assertEquals('Doctrine\Tests\Models\CMS\Bar', $oneOneMapping['targetEntity']);
|
||||
$this->assertTrue($cm->isReadOnly);
|
||||
$this->assertEquals(array('dql' => 'foo'), $cm->namedQueries);
|
||||
}
|
||||
|
||||
public function testFieldIsNullable()
|
||||
@ -446,4 +450,14 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
|
||||
'query' => 'SELECT u FROM __CLASS__ u WHERE u.id = ?1'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1068
|
||||
*/
|
||||
public function testClassCaseSensitivity()
|
||||
{
|
||||
$user = new \Doctrine\Tests\Models\CMS\CmsUser();
|
||||
$cm = new ClassMetadata('DOCTRINE\TESTS\MODELS\CMS\CMSUSER');
|
||||
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $cm->name);
|
||||
}
|
||||
}
|
||||
|
@ -251,6 +251,23 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
|
||||
$this->assertValidDQL("SELECT (SELECT (SUM(u.id) / COUNT(u.id)) FROM Doctrine\Tests\Models\CMS\CmsUser u2) value FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name = 'jon'");
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1079
|
||||
*/
|
||||
public function testSelectLiteralInSubselect()
|
||||
{
|
||||
$this->assertValidDQL('SELECT (SELECT 1 FROM Doctrine\Tests\Models\CMS\CmsUser u2) value FROM Doctrine\Tests\Models\CMS\CmsUser u');
|
||||
$this->assertValidDQL('SELECT (SELECT 0 FROM Doctrine\Tests\Models\CMS\CmsUser u2) value FROM Doctrine\Tests\Models\CMS\CmsUser u');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1077
|
||||
*/
|
||||
public function testConstantValueInSelect()
|
||||
{
|
||||
$this->assertValidDQL("SELECT u.name, 'foo' AS bar FROM Doctrine\Tests\Models\CMS\CmsUser u", true);
|
||||
}
|
||||
|
||||
public function testDuplicateAliasInSubselectPart()
|
||||
{
|
||||
$this->assertInvalidDQL("SELECT (SELECT SUM(u.id) / COUNT(u.id) AS foo FROM Doctrine\Tests\Models\CMS\CmsUser u2) foo FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name = 'jon'");
|
||||
@ -496,6 +513,30 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
|
||||
$this->assertInvalidDQL('SELECT g FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1053
|
||||
*/
|
||||
public function testGroupBy()
|
||||
{
|
||||
$this->assertValidDQL('SELECT g.id, count(u.id) FROM Doctrine\Tests\Models\CMS\CmsGroup g JOIN g.users u GROUP BY g.id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1053
|
||||
*/
|
||||
public function testGroupByIdentificationVariable()
|
||||
{
|
||||
$this->assertValidDQL('SELECT g, count(u.id) FROM Doctrine\Tests\Models\CMS\CmsGroup g JOIN g.users u GROUP BY g');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1053
|
||||
*/
|
||||
public function testGroupByUnknownIdentificationVariable()
|
||||
{
|
||||
$this->assertInvalidDQL('SELECT g, count(u.id) FROM Doctrine\Tests\Models\CMS\CmsGroup g JOIN g.users u GROUP BY m');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-117
|
||||
*/
|
||||
|
@ -42,7 +42,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
parent::assertEquals($sqlToBeConfirmed, $query->getSql());
|
||||
$query->free();
|
||||
} catch (\Exception $e) {
|
||||
$this->fail($e->getMessage());
|
||||
$this->fail($e->getMessage() ."\n".$e->getTraceAsString());
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,6 +170,17 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
);
|
||||
}*/
|
||||
|
||||
/**
|
||||
* @group DDC-1077
|
||||
*/
|
||||
public function testConstantValueInSelect()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
"SELECT u.name, 'foo' AS bar FROM Doctrine\Tests\Models\CMS\CmsUser u",
|
||||
"SELECT c0_.name AS name0, 'foo' AS sclr1 FROM cms_users c0_"
|
||||
);
|
||||
}
|
||||
|
||||
public function testSupportsOrderByWithAscAsDefault()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
@ -851,6 +862,28 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
'SELECT f0_.id AS id0, f0_.extension AS extension1, f0_.name AS name2 FROM "file" f0_ INNER JOIN Directory d1_ ON f0_.parentDirectory_id = d1_.id WHERE f0_.id = ?'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1053
|
||||
*/
|
||||
public function testGroupBy()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT g.id, count(u.id) FROM Doctrine\Tests\Models\CMS\CmsGroup g JOIN g.users u GROUP BY g.id',
|
||||
'SELECT c0_.id AS id0, count(c1_.id) AS sclr1 FROM cms_groups c0_ INNER JOIN cms_users_groups c2_ ON c0_.id = c2_.group_id INNER JOIN cms_users c1_ ON c1_.id = c2_.user_id GROUP BY c0_.id'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1053
|
||||
*/
|
||||
public function testGroupByIdentificationVariable()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT g, count(u.id) FROM Doctrine\Tests\Models\CMS\CmsGroup g JOIN g.users u GROUP BY g',
|
||||
'SELECT c0_.id AS id0, c0_.name AS name1, count(c1_.id) AS sclr2 FROM cms_groups c0_ INNER JOIN cms_users_groups c2_ ON c0_.id = c2_.group_id INNER JOIN cms_users c1_ ON c1_.id = c2_.user_id GROUP BY c0_.id'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user