Implemented missing support in CollectionMemberComparison. Removed old todo in ArrayHydrator. Finished implementation of IdentificationVariable in ArithmeticPrimary.
This commit is contained in:
parent
2642daa438
commit
2f6b930a8d
@ -28,11 +28,6 @@ use PDO, Doctrine\DBAL\Connection, Doctrine\ORM\Mapping\ClassMetadata;
|
||||
* @since 2.0
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @author Guilherme Blanco <guilhermeblanoc@hotmail.com>
|
||||
*
|
||||
* @todo General behavior is "wrong" if you define an alias to selected IdentificationVariable.
|
||||
* Example: SELECT u AS user FROM User u
|
||||
* The result should contains an array where each array index is an array: array('user' => [User object])
|
||||
* Problem must be solved somehow by removing the isMixed in ResultSetMapping
|
||||
*/
|
||||
class ArrayHydrator extends AbstractHydrator
|
||||
{
|
||||
|
@ -2607,7 +2607,7 @@ class Parser
|
||||
return $this->InputParameter();
|
||||
}
|
||||
|
||||
return $this->IdentificationVariable();
|
||||
return $this->StateFieldPathExpression();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -411,7 +411,8 @@ class SqlWalker implements TreeWalker
|
||||
{
|
||||
$this->_useSqlTableAliases = false;
|
||||
|
||||
return $this->walkUpdateClause($AST->updateClause) . $this->walkWhereClause($AST->whereClause);
|
||||
return $this->walkUpdateClause($AST->updateClause)
|
||||
. $this->walkWhereClause($AST->whereClause);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -424,9 +425,29 @@ class SqlWalker implements TreeWalker
|
||||
{
|
||||
$this->_useSqlTableAliases = false;
|
||||
|
||||
return $this->walkDeleteClause($AST->deleteClause) . $this->walkWhereClause($AST->whereClause);
|
||||
return $this->walkDeleteClause($AST->deleteClause)
|
||||
. $this->walkWhereClause($AST->whereClause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Walks down an IdentificationVariable AST node, thereby generating the appropriate SQL.
|
||||
* This one differs of ->walkIdentificationVariable() because it generates the entity identifiers.
|
||||
*
|
||||
* @param string $identVariable
|
||||
* @return string
|
||||
*/
|
||||
public function walkEntityIdentificationVariable($identVariable)
|
||||
{
|
||||
$class = $this->_queryComponents[$identVariable]['metadata'];
|
||||
$tableAlias = $this->getSQLTableAlias($class->getTableName(), $identVariable);
|
||||
$sqlParts = array();
|
||||
|
||||
foreach ($class->getQuotedIdentifierColumnNames($this->_platform) as $columnName) {
|
||||
$sqlParts[] = $tableAlias . '.' . $columnName;
|
||||
}
|
||||
|
||||
return implode(', ', $sqlParts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Walks down an IdentificationVariable (no AST node associated), thereby generating the SQL.
|
||||
@ -689,7 +710,7 @@ class SqlWalker implements TreeWalker
|
||||
$expr = $orderByItem->expression;
|
||||
$sql = ($expr instanceof AST\PathExpression)
|
||||
? $this->walkPathExpression($expr)
|
||||
: $this->_scalarResultAliasMap[$this->_queryComponents[$expr]['token']['value']];
|
||||
: $this->walkResultVariable($this->_queryComponents[$expr]['token']['value']);
|
||||
|
||||
return $sql . ' ' . strtoupper($orderByItem->type);
|
||||
}
|
||||
@ -1287,15 +1308,7 @@ class SqlWalker implements TreeWalker
|
||||
break;
|
||||
|
||||
default: // IdentificationVariable
|
||||
$class = $this->_queryComponents[$expr]['metadata'];
|
||||
$tableAlias = $this->getSQLTableAlias($class->getTableName(), $expr);
|
||||
$sqlParts = array();
|
||||
|
||||
foreach ($class->getQuotedIdentifierColumnNames($this->_platform) as $columnName) {
|
||||
$sqlParts[] = $tableAlias . '.' . $columnName;
|
||||
}
|
||||
|
||||
$sql .= implode(', ', $sqlParts);
|
||||
$sql .= $this->walkEntityIdentificationVariable($expr);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1558,20 +1571,30 @@ class SqlWalker implements TreeWalker
|
||||
{
|
||||
$sql = $collMemberExpr->not ? 'NOT ' : '';
|
||||
$sql .= 'EXISTS (SELECT 1 FROM ';
|
||||
$entityExpr = $collMemberExpr->entityExpression;
|
||||
|
||||
$entityExpr = $collMemberExpr->entityExpression;
|
||||
$collPathExpr = $collMemberExpr->collectionValuedPathExpression;
|
||||
|
||||
$fieldName = $collPathExpr->field;
|
||||
$dqlAlias = $collPathExpr->identificationVariable;
|
||||
$dqlAlias = $collPathExpr->identificationVariable;
|
||||
|
||||
$class = $this->_queryComponents[$dqlAlias]['metadata'];
|
||||
|
||||
if ($entityExpr instanceof AST\InputParameter) {
|
||||
$dqlParamKey = $entityExpr->name;
|
||||
$entity = $this->_query->getParameter($dqlParamKey);
|
||||
} else {
|
||||
//TODO
|
||||
throw new \BadMethodCallException("Not implemented");
|
||||
switch (true) {
|
||||
// InputParameter
|
||||
case ($entityExpr instanceof AST\InputParameter):
|
||||
$dqlParamKey = $entityExpr->name;
|
||||
$entity = $this->_query->getParameter($dqlParamKey);
|
||||
$entitySql = '?';
|
||||
break;
|
||||
|
||||
// SingleValuedAssociationPathExpression | IdentificationVariable
|
||||
case ($entityExpr instanceof AST\PathExpression):
|
||||
$entitySql = $this->walkPathExpression($entityExpr);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \BadMethodCallException("Not implemented");
|
||||
}
|
||||
|
||||
$assoc = $class->associationMappings[$fieldName];
|
||||
@ -1584,25 +1607,23 @@ class SqlWalker implements TreeWalker
|
||||
$sql .= $targetClass->getQuotedTableName($this->_platform) . ' ' . $targetTableAlias . ' WHERE ';
|
||||
|
||||
$owningAssoc = $targetClass->associationMappings[$assoc['mappedBy']];
|
||||
$first = true;
|
||||
$sqlParts = array();
|
||||
|
||||
foreach ($owningAssoc['targetToSourceKeyColumns'] as $targetColumn => $sourceColumn) {
|
||||
if ($first) $first = false; else $sql .= ' AND ';
|
||||
$targetColumn = $class->getQuotedColumnName($class->fieldNames[$targetColumn], $this->_platform);
|
||||
|
||||
$sql .= $sourceTableAlias . '.' . $class->getQuotedColumnName($class->fieldNames[$targetColumn], $this->_platform)
|
||||
. ' = '
|
||||
. $targetTableAlias . '.' . $sourceColumn;
|
||||
$sqlParts[] = $sourceTableAlias . '.' . $targetColumn . ' = ' . $targetTableAlias . '.' . $sourceColumn;
|
||||
}
|
||||
|
||||
$sql .= ' AND ';
|
||||
$first = true;
|
||||
|
||||
foreach ($targetClass->getQuotedIdentifierColumnNames($this->_platform) as $targetColumnName) {
|
||||
if ($first) $first = false; else $sql .= ' AND ';
|
||||
if (isset($dqlParamKey)) {
|
||||
$this->_parserResult->addParameterMapping($dqlParamKey, $this->_sqlParamIndex++);
|
||||
}
|
||||
|
||||
$this->_parserResult->addParameterMapping($dqlParamKey, $this->_sqlParamIndex++);
|
||||
$sql .= $targetTableAlias . '.' . $targetColumnName . ' = ?';
|
||||
$sqlParts[] = $targetTableAlias . '.' . $targetColumnName . ' = ' . $entitySql;
|
||||
}
|
||||
|
||||
$sql .= implode(' AND ', $sqlParts);
|
||||
} else { // many-to-many
|
||||
$targetClass = $this->_em->getClassMetadata($assoc['targetEntity']);
|
||||
|
||||
@ -1619,39 +1640,42 @@ class SqlWalker implements TreeWalker
|
||||
. ' INNER JOIN ' . $targetClass->getQuotedTableName($this->_platform) . ' ' . $targetTableAlias . ' ON ';
|
||||
|
||||
// join conditions
|
||||
$joinColumns = $assoc['isOwningSide']
|
||||
? $joinTable['inverseJoinColumns']
|
||||
: $joinTable['joinColumns'];
|
||||
$joinColumns = $assoc['isOwningSide'] ? $joinTable['inverseJoinColumns'] : $joinTable['joinColumns'];
|
||||
$joinSqlParts = array();
|
||||
|
||||
$first = true;
|
||||
foreach ($joinColumns as $joinColumn) {
|
||||
if ($first) $first = false; else $sql .= ' AND ';
|
||||
$targetColumn = $targetClass->getQuotedColumnName(
|
||||
$targetClass->fieldNames[$joinColumn['referencedColumnName']],
|
||||
$this->_platform
|
||||
);
|
||||
|
||||
$sql .= $joinTableAlias . '.' . $joinColumn['name'] . ' = '
|
||||
. $targetTableAlias . '.' . $targetClass->getQuotedColumnName($targetClass->fieldNames[$joinColumn['referencedColumnName']], $this->_platform);
|
||||
$joinSqlParts[] = $joinTableAlias . '.' . $joinColumn['name'] . ' = ' . $targetTableAlias . '.' . $targetColumn;
|
||||
}
|
||||
|
||||
$sql .= implode(' AND ', $joinSqlParts);
|
||||
$sql .= ' WHERE ';
|
||||
|
||||
$joinColumns = $assoc['isOwningSide'] ? $joinTable['joinColumns'] : $joinTable['inverseJoinColumns'];
|
||||
$first = true;
|
||||
$sqlParts = array();
|
||||
|
||||
foreach ($joinColumns as $joinColumn) {
|
||||
if ($first) $first = false; else $sql .= ' AND ';
|
||||
$targetColumn = $class->getQuotedColumnName(
|
||||
$class->fieldNames[$joinColumn['referencedColumnName']],
|
||||
$this->_platform
|
||||
);
|
||||
|
||||
$sql .= $joinTableAlias . '.' . $joinColumn['name'] . ' = '
|
||||
. $sourceTableAlias . '.' . $class->getQuotedColumnName($class->fieldNames[$joinColumn['referencedColumnName']], $this->_platform);
|
||||
$sqlParts[] = $joinTableAlias . '.' . $joinColumn['name'] . ' = ' . $sourceTableAlias . '.' . $targetColumn;
|
||||
}
|
||||
|
||||
$sql .= ' AND ';
|
||||
$first = true;
|
||||
|
||||
foreach ($targetClass->getQuotedIdentifierColumnNames($this->_platform) as $targetColumnName) {
|
||||
if ($first) $first = false; else $sql .= ' AND ';
|
||||
if (isset($dqlParamKey)) {
|
||||
$this->_parserResult->addParameterMapping($dqlParamKey, $this->_sqlParamIndex++);
|
||||
}
|
||||
|
||||
$this->_parserResult->addParameterMapping($dqlParamKey, $this->_sqlParamIndex++);
|
||||
$sql .= $targetTableAlias . '.' . $targetColumnName . ' = ?';
|
||||
$sqlParts[] = $targetTableAlias . '.' . $targetColumnName . ' = ' . $entitySql;
|
||||
}
|
||||
|
||||
$sql .= implode(' AND ', $sqlParts);
|
||||
}
|
||||
|
||||
return $sql . ')';
|
||||
@ -1946,7 +1970,7 @@ class SqlWalker implements TreeWalker
|
||||
{
|
||||
if (is_string($term)) {
|
||||
return (isset($this->_queryComponents[$term]))
|
||||
? $this->_scalarResultAliasMap[$this->_queryComponents[$term]['token']['value']]
|
||||
? $this->walkResultVariable($this->_queryComponents[$term]['token']['value'])
|
||||
: $term;
|
||||
}
|
||||
|
||||
@ -1998,8 +2022,7 @@ class SqlWalker implements TreeWalker
|
||||
return $primary->dispatch($this);
|
||||
}
|
||||
|
||||
// TODO: We need to deal with IdentificationVariable here
|
||||
return '';
|
||||
return $this->walkEntityIdentificationVariable($primary);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -196,7 +196,7 @@ public function <methodName>()
|
||||
if ($this->_backupExisting && file_exists($path)) {
|
||||
$backupPath = dirname($path) . DIRECTORY_SEPARATOR . basename($path) . "~";
|
||||
if (!copy($path, $backupPath)) {
|
||||
throw new \RuntimeException("Attempt to backup overwritten entitiy file but copy operation failed.");
|
||||
throw new \RuntimeException("Attempt to backup overwritten entity file but copy operation failed.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -754,7 +754,7 @@ public function <methodName>()
|
||||
'<variableName>' => Inflector::camelize($fieldName),
|
||||
'<methodName>' => $methodName,
|
||||
'<fieldName>' => $fieldName,
|
||||
'<variableDefault>' => ($defaultValue !== null ) ? ('='.$defaultValue) : '',
|
||||
'<variableDefault>' => ($defaultValue !== null ) ? (' = '.$defaultValue) : '',
|
||||
'<entity>' => $this->_getClassName($metadata)
|
||||
);
|
||||
|
||||
|
@ -536,43 +536,71 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
);
|
||||
}
|
||||
|
||||
public function testSupportsMemberOfExpression()
|
||||
public function testSupportsMemberOfExpressionOneToMany()
|
||||
{
|
||||
// "Get all users who have $phone as a phonenumber." (*cough* doesnt really make sense...)
|
||||
$q1 = $this->_em->createQuery('SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE :param MEMBER OF u.phonenumbers');
|
||||
$q1->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true);
|
||||
$q = $this->_em->createQuery('SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE :param MEMBER OF u.phonenumbers');
|
||||
$q->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true);
|
||||
|
||||
$phone = new \Doctrine\Tests\Models\CMS\CmsPhonenumber;
|
||||
$phone->phonenumber = 101;
|
||||
$q1->setParameter('param', $phone);
|
||||
$q->setParameter('param', $phone);
|
||||
|
||||
$this->assertEquals(
|
||||
'SELECT c0_.id AS id0 FROM cms_users c0_ WHERE EXISTS (SELECT 1 FROM cms_phonenumbers c1_ WHERE c0_.id = c1_.user_id AND c1_.phonenumber = ?)',
|
||||
$q1->getSql()
|
||||
$q->getSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testSupportsMemberOfExpressionManyToMany()
|
||||
{
|
||||
// "Get all users who are members of $group."
|
||||
$q2 = $this->_em->createQuery('SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE :param MEMBER OF u.groups');
|
||||
$q2->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true);
|
||||
$q = $this->_em->createQuery('SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE :param MEMBER OF u.groups');
|
||||
$q->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true);
|
||||
|
||||
$group = new \Doctrine\Tests\Models\CMS\CmsGroup;
|
||||
$group->id = 101;
|
||||
$q2->setParameter('param', $group);
|
||||
$q->setParameter('param', $group);
|
||||
|
||||
$this->assertEquals(
|
||||
'SELECT c0_.id AS id0 FROM cms_users c0_ WHERE EXISTS (SELECT 1 FROM cms_users_groups c1_ INNER JOIN cms_groups c2_ ON c1_.group_id = c2_.id WHERE c1_.user_id = c0_.id AND c2_.id = ?)',
|
||||
$q2->getSql()
|
||||
$q->getSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testSupportsMemberOfExpressionSelfReferencing()
|
||||
{
|
||||
// "Get all persons who have $person as a friend."
|
||||
// Tough one: Many-many self-referencing ("friends") with class table inheritance
|
||||
$q3 = $this->_em->createQuery('SELECT p FROM Doctrine\Tests\Models\Company\CompanyPerson p WHERE :param MEMBER OF p.friends');
|
||||
$q = $this->_em->createQuery('SELECT p FROM Doctrine\Tests\Models\Company\CompanyPerson p WHERE :param MEMBER OF p.friends');
|
||||
$person = new \Doctrine\Tests\Models\Company\CompanyPerson;
|
||||
$this->_em->getClassMetadata(get_class($person))->setIdentifierValues($person, array('id' => 101));
|
||||
$q3->setParameter('param', $person);
|
||||
$q->setParameter('param', $person);
|
||||
$this->assertEquals(
|
||||
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.title AS title2, c2_.salary AS salary3, c2_.department AS department4, c2_.startDate AS startDate5, c0_.discr AS discr6, c0_.spouse_id AS spouse_id7, c1_.car_id AS car_id8 FROM company_persons c0_ LEFT JOIN company_managers c1_ ON c0_.id = c1_.id LEFT JOIN company_employees c2_ ON c0_.id = c2_.id WHERE EXISTS (SELECT 1 FROM company_persons_friends c3_ INNER JOIN company_persons c4_ ON c3_.friend_id = c4_.id WHERE c3_.person_id = c0_.id AND c4_.id = ?)',
|
||||
$q3->getSql()
|
||||
$q->getSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testSupportsMemberOfWithSingleValuedAssociation()
|
||||
{
|
||||
// Impossible example, but it illustrates the purpose
|
||||
$q = $this->_em->createQuery('SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.email MEMBER OF u.groups');
|
||||
|
||||
$this->assertEquals(
|
||||
'SELECT c0_.id AS id0 FROM cms_users c0_ WHERE EXISTS (SELECT 1 FROM cms_users_groups c1_ INNER JOIN cms_groups c2_ ON c1_.group_id = c2_.id WHERE c1_.user_id = c0_.id AND c2_.id = c0_.email_id)',
|
||||
$q->getSql()
|
||||
);
|
||||
}
|
||||
|
||||
public function testSupportsMemberOfWithIdentificationVariable()
|
||||
{
|
||||
// Impossible example, but it illustrates the purpose
|
||||
$q = $this->_em->createQuery('SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u MEMBER OF u.groups');
|
||||
|
||||
$this->assertEquals(
|
||||
'SELECT c0_.id AS id0 FROM cms_users c0_ WHERE EXISTS (SELECT 1 FROM cms_users_groups c1_ INNER JOIN cms_groups c2_ ON c1_.group_id = c2_.id WHERE c1_.user_id = c0_.id AND c2_.id = c0_.id)',
|
||||
$q->getSql()
|
||||
);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user