1
0
Fork 0
mirror of synced 2025-04-03 13:23:37 +03:00

[DDC-934][DDC-1100][DDC-1331] Implemented support to multi-values in INSTANCE OF expression.

This commit is contained in:
Guilherme Blanco 2011-08-15 01:53:56 -03:00
parent b9a24b5487
commit f148912a28
6 changed files with 86 additions and 38 deletions

View file

@ -195,6 +195,8 @@ abstract class AbstractQuery
*/ */
public function setParameter($key, $value, $type = null) public function setParameter($key, $value, $type = null)
{ {
$key = trim($key, ':');
if ($type === null) { if ($type === null) {
$type = Query\ParameterTypeInferer::inferType($value); $type = Query\ParameterTypeInferer::inferType($value);
} }

View file

@ -20,7 +20,8 @@
namespace Doctrine\ORM\Query\AST; namespace Doctrine\ORM\Query\AST;
/** /**
* InstanceOfExpression ::= IdentificationVariable ["NOT"] "INSTANCE" ["OF"] (AbstractSchemaName | InputParameter) * InstanceOfExpression ::= IdentificationVariable ["NOT"] "INSTANCE" ["OF"] (InstanceOfParameter | "(" InstanceOfParameter {"," InstanceOfParameter}* ")")
* InstanceOfParameter ::= AbstractSchemaName | InputParameter
* *
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org * @link www.doctrine-project.org

View file

@ -2676,7 +2676,7 @@ class Parser
} }
/** /**
* InstanceOfExpression ::= IdentificationVariable ["NOT"] "INSTANCE" ["OF"] (AbstractSchemaName | InputParameter) * InstanceOfExpression ::= IdentificationVariable ["NOT"] "INSTANCE" ["OF"] (InstanceOfParameter | "(" InstanceOfParameter {"," InstanceOfParameter}* ")")
* *
* @return \Doctrine\ORM\Query\AST\InstanceOfExpression * @return \Doctrine\ORM\Query\AST\InstanceOfExpression
*/ */
@ -2690,22 +2690,50 @@ class Parser
} }
$this->match(Lexer::T_INSTANCE); $this->match(Lexer::T_INSTANCE);
$this->match(Lexer::T_OF);
$exprValues = array();
if ($this->_lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS)) {
$this->match(Lexer::T_OPEN_PARENTHESIS);
$exprValues[] = $this->InstanceOfParameter();
if ($this->_lexer->isNextToken(Lexer::T_OF)) { while ($this->_lexer->isNextToken(Lexer::T_COMMA)) {
$this->match(Lexer::T_OF); $this->match(Lexer::T_COMMA);
$exprValues[] = $this->InstanceOfParameter();
}
$this->match(Lexer::T_CLOSE_PARENTHESIS);
$instanceOfExpression->value = $exprValues;
return $instanceOfExpression;
} }
if ($this->_lexer->isNextToken(Lexer::T_INPUT_PARAMETER)) { $exprValues[] = $this->InstanceOfParameter();
$this->match(Lexer::T_INPUT_PARAMETER);
$exprValue = new AST\InputParameter($this->_lexer->token['value']);
} else {
$exprValue = $this->AliasIdentificationVariable();
}
$instanceOfExpression->value = $exprValue; $instanceOfExpression->value = $exprValues;
return $instanceOfExpression; return $instanceOfExpression;
} }
/**
* InstanceOfParameter ::= AbstractSchemaName | InputParameter
*
* @return mixed
*/
public function InstanceOfParameter()
{
if ($this->_lexer->isNextToken(Lexer::T_INPUT_PARAMETER)) {
$this->match(Lexer::T_INPUT_PARAMETER);
return new AST\InputParameter($this->_lexer->token['value']);
}
return $this->AliasIdentificationVariable();
}
/** /**
* LikeExpression ::= StringExpression ["NOT"] "LIKE" (string | input_parameter) ["ESCAPE" char] * LikeExpression ::= StringExpression ["NOT"] "LIKE" (string | input_parameter) ["ESCAPE" char]

View file

@ -1756,34 +1756,41 @@ class SqlWalker implements TreeWalker
if ($this->_useSqlTableAliases) { if ($this->_useSqlTableAliases) {
$sql .= $this->getSQLTableAlias($discrClass->table['name'], $dqlAlias) . '.'; $sql .= $this->getSQLTableAlias($discrClass->table['name'], $dqlAlias) . '.';
} }
$sql .= $class->discriminatorColumn['name'] . ($instanceOfExpr->not ? ' NOT IN ' : ' IN ');
$sqlParameterList = array();
foreach ($instanceOfExpr->value as $parameter) {
if ($parameter instanceof AST\InputParameter) {
// We need to modify the parameter value to be its correspondent mapped value
$dqlParamKey = $parameter->name;
$paramValue = $this->_query->getParameter($dqlParamKey);
$sql .= $class->discriminatorColumn['name'] . ($instanceOfExpr->not ? ' <> ' : ' = '); if ( ! ($paramValue instanceof \Doctrine\ORM\Mapping\ClassMetadata)) {
throw QueryException::invalidParameterType('ClassMetadata', get_class($paramValue));
}
if ($instanceOfExpr->value instanceof AST\InputParameter) { $entityClassName = $paramValue->name;
// We need to modify the parameter value to be its correspondent mapped value } else {
$dqlParamKey = $instanceOfExpr->value->name; // Get name from ClassMetadata to resolve aliases.
$paramValue = $this->_query->getParameter($dqlParamKey); $entityClassName = $this->_em->getClassMetadata($parameter)->name;
if ( ! ($paramValue instanceof \Doctrine\ORM\Mapping\ClassMetadata)) {
throw QueryException::invalidParameterType('ClassMetadata', get_class($paramValue));
} }
$entityClassName = $paramValue->name;
} else {
// Get name from ClassMetadata to resolve aliases.
$entityClassName = $this->_em->getClassMetadata($instanceOfExpr->value)->name;
}
if ($entityClassName == $class->name) { if ($entityClassName == $class->name) {
$sql .= $this->_conn->quote($class->discriminatorValue); $sqlParameterList[] = $this->_conn->quote($class->discriminatorValue);
} else { } else {
$discrMap = array_flip($class->discriminatorMap); $discrMap = array_flip($class->discriminatorMap);
if (!isset($discrMap[$entityClassName])) {
throw QueryException::instanceOfUnrelatedClass($entityClassName, $class->rootEntityName); if (!isset($discrMap[$entityClassName])) {
throw QueryException::instanceOfUnrelatedClass($entityClassName, $class->rootEntityName);
}
$sqlParameterList[] = $this->_conn->quote($discrMap[$entityClassName]);
} }
$sql .= $this->_conn->quote($discrMap[$entityClassName]);
} }
$sql .= '(' . implode(', ', $sqlParameterList) . ')';
return $sql; return $sql;
} }

View file

@ -323,6 +323,8 @@ class QueryBuilder
*/ */
public function setParameter($key, $value, $type = null) public function setParameter($key, $value, $type = null)
{ {
$key = trim($key, ':');
if ($type === null) { if ($type === null) {
$type = Query\ParameterTypeInferer::inferType($value); $type = Query\ParameterTypeInferer::inferType($value);
} }

View file

@ -380,7 +380,15 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
{ {
$this->assertSqlGeneration( $this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF Doctrine\Tests\Models\Company\CompanyEmployee", "SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF Doctrine\Tests\Models\Company\CompanyEmployee",
"SELECT c0_.id AS id0, c0_.name AS name1, c0_.discr AS discr2 FROM company_persons c0_ WHERE c0_.discr = 'employee'" "SELECT c0_.id AS id0, c0_.name AS name1, c0_.discr AS discr2 FROM company_persons c0_ WHERE c0_.discr IN ('employee')"
);
}
public function testSupportsInstanceOfExpressionInWherePartWithMultipleValues()
{
$this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF (Doctrine\Tests\Models\Company\CompanyEmployee, \Doctrine\Tests\Models\Company\CompanyManager)",
"SELECT c0_.id AS id0, c0_.name AS name1, c0_.discr AS discr2 FROM company_persons c0_ WHERE c0_.discr IN ('employee', 'manager')"
); );
} }
@ -391,7 +399,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
{ {
$this->assertSqlGeneration( $this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF \Doctrine\Tests\Models\Company\CompanyEmployee", "SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF \Doctrine\Tests\Models\Company\CompanyEmployee",
"SELECT c0_.id AS id0, c0_.name AS name1, c0_.discr AS discr2 FROM company_persons c0_ WHERE c0_.discr = 'employee'" "SELECT c0_.id AS id0, c0_.name AS name1, c0_.discr AS discr2 FROM company_persons c0_ WHERE c0_.discr IN ('employee')"
); );
} }
@ -410,7 +418,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
{ {
$this->assertSqlGeneration( $this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\Company\CompanyEmployee u WHERE u INSTANCE OF Doctrine\Tests\Models\Company\CompanyManager", "SELECT u FROM Doctrine\Tests\Models\Company\CompanyEmployee u WHERE u INSTANCE OF Doctrine\Tests\Models\Company\CompanyManager",
"SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c0_.discr AS discr4 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id WHERE c0_.discr = 'manager'" "SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c0_.discr AS discr4 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id WHERE c0_.discr IN ('manager')"
); );
} }
@ -418,7 +426,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
{ {
$this->assertSqlGeneration( $this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\Company\CompanyManager u WHERE u INSTANCE OF Doctrine\Tests\Models\Company\CompanyManager", "SELECT u FROM Doctrine\Tests\Models\Company\CompanyManager u WHERE u INSTANCE OF Doctrine\Tests\Models\Company\CompanyManager",
"SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c2_.title AS title4, c0_.discr AS discr5 FROM company_managers c2_ INNER JOIN company_employees c1_ ON c2_.id = c1_.id INNER JOIN company_persons c0_ ON c2_.id = c0_.id WHERE c0_.discr = 'manager'" "SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c2_.title AS title4, c0_.discr AS discr5 FROM company_managers c2_ INNER JOIN company_employees c1_ ON c2_.id = c1_.id INNER JOIN company_persons c0_ ON c2_.id = c0_.id WHERE c0_.discr IN ('manager')"
); );
} }
@ -426,7 +434,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
{ {
$this->assertSqlGeneration( $this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF ?1", "SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF ?1",
"SELECT c0_.id AS id0, c0_.name AS name1, c0_.discr AS discr2 FROM company_persons c0_ WHERE c0_.discr = 'employee'", "SELECT c0_.id AS id0, c0_.name AS name1, c0_.discr AS discr2 FROM company_persons c0_ WHERE c0_.discr IN ('employee')",
array(), array(1 => $this->_em->getClassMetadata('Doctrine\Tests\Models\Company\CompanyEmployee')) array(), array(1 => $this->_em->getClassMetadata('Doctrine\Tests\Models\Company\CompanyEmployee'))
); );
} }