[DDC-934][DDC-1100][DDC-1331] Implemented support to multi-values in INSTANCE OF expression.
This commit is contained in:
parent
b9a24b5487
commit
f148912a28
6 changed files with 86 additions and 38 deletions
|
@ -195,6 +195,8 @@ abstract class AbstractQuery
|
|||
*/
|
||||
public function setParameter($key, $value, $type = null)
|
||||
{
|
||||
$key = trim($key, ':');
|
||||
|
||||
if ($type === null) {
|
||||
$type = Query\ParameterTypeInferer::inferType($value);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
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
|
||||
* @link www.doctrine-project.org
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
@ -2690,22 +2690,50 @@ class Parser
|
|||
}
|
||||
|
||||
$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)) {
|
||||
$this->match(Lexer::T_OF);
|
||||
while ($this->_lexer->isNextToken(Lexer::T_COMMA)) {
|
||||
$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)) {
|
||||
$this->match(Lexer::T_INPUT_PARAMETER);
|
||||
$exprValue = new AST\InputParameter($this->_lexer->token['value']);
|
||||
} else {
|
||||
$exprValue = $this->AliasIdentificationVariable();
|
||||
}
|
||||
$exprValues[] = $this->InstanceOfParameter();
|
||||
|
||||
$instanceOfExpression->value = $exprValue;
|
||||
$instanceOfExpression->value = $exprValues;
|
||||
|
||||
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]
|
||||
|
|
|
@ -1756,34 +1756,41 @@ class SqlWalker implements TreeWalker
|
|||
if ($this->_useSqlTableAliases) {
|
||||
$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) {
|
||||
// We need to modify the parameter value to be its correspondent mapped value
|
||||
$dqlParamKey = $instanceOfExpr->value->name;
|
||||
$paramValue = $this->_query->getParameter($dqlParamKey);
|
||||
|
||||
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($parameter)->name;
|
||||
}
|
||||
|
||||
$entityClassName = $paramValue->name;
|
||||
} else {
|
||||
// Get name from ClassMetadata to resolve aliases.
|
||||
$entityClassName = $this->_em->getClassMetadata($instanceOfExpr->value)->name;
|
||||
}
|
||||
|
||||
if ($entityClassName == $class->name) {
|
||||
$sql .= $this->_conn->quote($class->discriminatorValue);
|
||||
} else {
|
||||
$discrMap = array_flip($class->discriminatorMap);
|
||||
if (!isset($discrMap[$entityClassName])) {
|
||||
throw QueryException::instanceOfUnrelatedClass($entityClassName, $class->rootEntityName);
|
||||
if ($entityClassName == $class->name) {
|
||||
$sqlParameterList[] = $this->_conn->quote($class->discriminatorValue);
|
||||
} else {
|
||||
$discrMap = array_flip($class->discriminatorMap);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -323,6 +323,8 @@ class QueryBuilder
|
|||
*/
|
||||
public function setParameter($key, $value, $type = null)
|
||||
{
|
||||
$key = trim($key, ':');
|
||||
|
||||
if ($type === null) {
|
||||
$type = Query\ParameterTypeInferer::inferType($value);
|
||||
}
|
||||
|
|
|
@ -380,7 +380,15 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
|||
{
|
||||
$this->assertSqlGeneration(
|
||||
"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(
|
||||
"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(
|
||||
"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(
|
||||
"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(
|
||||
"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'))
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue