1
0
mirror of synced 2025-01-18 22:41:43 +03:00

[2.0][DDC-614] Added support to multiple FROM identification variables. Also, fixed bug with missing lock on subselect.

This commit is contained in:
Guilherme Blanco 2010-07-20 00:51:01 -03:00
parent a05003016b
commit 2c28872af8
3 changed files with 93 additions and 54 deletions

View File

@ -77,9 +77,8 @@ class SqlWalker implements TreeWalker
/**
* The DQL alias of the root class of the currently traversed query.
* TODO: May need to be turned into a stack for usage in subqueries
*/
private $_currentRootAlias;
private $_rootAliases = array();
/**
* Flag that indicates whether to generate SQL table aliases in the SQL.
@ -187,6 +186,7 @@ class SqlWalker implements TreeWalker
/**
* Generates a unique, short SQL table alias.
*
* @param string $tableName Table name
* @param string $dqlAlias The DQL alias.
* @return string Generated table alias.
*/
@ -308,14 +308,15 @@ class SqlWalker implements TreeWalker
/**
* Generates a discriminator column SQL condition for the class with the given DQL alias.
*
* @param string $dqlAlias
* @param array $dqlAliases List of root DQL aliases to inspect for discriminator restrictions.
* @return string
*/
private function _generateDiscriminatorColumnConditionSQL($dqlAlias)
private function _generateDiscriminatorColumnConditionSQL(array $dqlAliases)
{
$encapsulate = false;
$sql = '';
if ($dqlAlias) {
foreach ($dqlAliases as $dqlAlias) {
$class = $this->_queryComponents[$dqlAlias]['metadata'];
if ($class->isInheritanceTypeSingleTable()) {
@ -329,14 +330,18 @@ class SqlWalker implements TreeWalker
$values[] = $conn->quote($this->_em->getClassMetadata($subclassName)->discriminatorValue);
}
$sql .= (($this->_useSqlTableAliases)
? $this->getSqlTableAlias($class->table['name'], $dqlAlias) . '.' : ''
) . $class->discriminatorColumn['name']
. ' IN (' . implode(', ', $values) . ')';
if ($sql != '') {
$sql .= ' AND ';
$encapsulate = true;
}
$sql .= ($sql != '' ? ' AND ' : '')
. (($this->_useSqlTableAliases) ? $this->getSqlTableAlias($class->table['name'], $dqlAlias) . '.' : '')
. $class->discriminatorColumn['name'] . ' IN (' . implode(', ', $values) . ')';
}
}
return $sql;
return ($encapsulate) ? '(' . $sql . ')' : $sql;
}
/**
@ -351,7 +356,7 @@ class SqlWalker implements TreeWalker
if (($whereClause = $AST->whereClause) !== null) {
$sql .= $this->walkWhereClause($whereClause);
} else if (($discSql = $this->_generateDiscriminatorColumnConditionSQL($this->_currentRootAlias)) !== '') {
} else if (($discSql = $this->_generateDiscriminatorColumnConditionSQL($this->_rootAliases)) !== '') {
$sql .= ' WHERE ' . $discSql;
}
@ -399,7 +404,7 @@ class SqlWalker implements TreeWalker
if (($whereClause = $AST->whereClause) !== null) {
$sql .= $this->walkWhereClause($whereClause);
} else if (($discSql = $this->_generateDiscriminatorColumnConditionSQL($this->_currentRootAlias)) !== '') {
} else if (($discSql = $this->_generateDiscriminatorColumnConditionSQL($this->_rootAliases)) !== '') {
$sql .= ' WHERE ' . $discSql;
}
@ -419,7 +424,7 @@ class SqlWalker implements TreeWalker
if (($whereClause = $AST->whereClause) !== null) {
$sql .= $this->walkWhereClause($whereClause);
} else if (($discSql = $this->_generateDiscriminatorColumnConditionSQL($this->_currentRootAlias)) !== '') {
} else if (($discSql = $this->_generateDiscriminatorColumnConditionSQL($this->_rootAliases)) !== '') {
$sql .= ' WHERE ' . $discSql;
}
@ -599,34 +604,40 @@ class SqlWalker implements TreeWalker
*/
public function walkFromClause($fromClause)
{
$sql = ' FROM ';
$identificationVarDecls = $fromClause->identificationVariableDeclarations;
$firstIdentificationVarDecl = $identificationVarDecls[0];
$rangeDecl = $firstIdentificationVarDecl->rangeVariableDeclaration;
$dqlAlias = $rangeDecl->aliasIdentificationVariable;
$sqlParts = array();
$this->_currentRootAlias = $dqlAlias;
foreach ($identificationVarDecls as $identificationVariableDecl) {
$sql = '';
$class = $this->_em->getClassMetadata($rangeDecl->abstractSchemaName);
$sql .= $class->getQuotedTableName($this->_platform) . ' '
. $this->getSqlTableAlias($class->table['name'], $dqlAlias);
$rangeDecl = $identificationVariableDecl->rangeVariableDeclaration;
$dqlAlias = $rangeDecl->aliasIdentificationVariable;
$this->_rootAliases[] = $dqlAlias;
if ($class->isInheritanceTypeJoined()) {
$sql .= $this->_generateClassTableInheritanceJoins($class, $dqlAlias);
$class = $this->_em->getClassMetadata($rangeDecl->abstractSchemaName);
$sql .= $class->getQuotedTableName($this->_platform) . ' '
. $this->getSqlTableAlias($class->table['name'], $dqlAlias);
if ($class->isInheritanceTypeJoined()) {
$sql .= $this->_generateClassTableInheritanceJoins($class, $dqlAlias);
}
foreach ($identificationVariableDecl->joinVariableDeclarations as $joinVarDecl) {
$sql .= $this->walkJoinVariableDeclaration($joinVarDecl);
}
if ($identificationVariableDecl->indexBy) {
$this->_rsm->addIndexBy(
$identificationVariableDecl->indexBy->simpleStateFieldPathExpression->identificationVariable,
$identificationVariableDecl->indexBy->simpleStateFieldPathExpression->parts[0]
);
}
$sqlParts[] = $this->_platform->appendLockHint($sql, $this->_query->getHint(Query::HINT_LOCK_MODE));
}
foreach ($firstIdentificationVarDecl->joinVariableDeclarations as $joinVarDecl) {
$sql .= $this->walkJoinVariableDeclaration($joinVarDecl);
}
if ($firstIdentificationVarDecl->indexBy) {
$this->_rsm->addIndexBy(
$firstIdentificationVarDecl->indexBy->simpleStateFieldPathExpression->identificationVariable,
$firstIdentificationVarDecl->indexBy->simpleStateFieldPathExpression->parts[0]
);
}
return $this->_platform->appendLockHint($sql, $this->_query->getHint(Query::HINT_LOCK_MODE));
return ' FROM ' . implode(', ', $sqlParts);
}
/**
@ -802,7 +813,7 @@ class SqlWalker implements TreeWalker
$sql .= ' AND (' . $this->walkConditionalExpression($condExpr) . ')';
}
$discrSql = $this->_generateDiscriminatorColumnConditionSQL($joinedDqlAlias);
$discrSql = $this->_generateDiscriminatorColumnConditionSQL(array($joinedDqlAlias));
if ($discrSql) {
$sql .= ' AND ' . $discrSql;
@ -1045,23 +1056,30 @@ class SqlWalker implements TreeWalker
public function walkSubselectFromClause($subselectFromClause)
{
$identificationVarDecls = $subselectFromClause->identificationVariableDeclarations;
$firstIdentificationVarDecl = $identificationVarDecls[0];
$rangeDecl = $firstIdentificationVarDecl->rangeVariableDeclaration;
$dqlAlias = $rangeDecl->aliasIdentificationVariable;
$sqlParts = array ();
$class = $this->_em->getClassMetadata($rangeDecl->abstractSchemaName);
$sql = ' FROM ' . $class->getQuotedTableName($this->_platform) . ' '
. $this->getSqlTableAlias($class->table['name'], $dqlAlias);
foreach ($identificationVarDecls as $subselectIdVarDecl) {
$sql = '';
if ($class->isInheritanceTypeJoined()) {
$sql .= $this->_generateClassTableInheritanceJoins($class, $dqlAlias);
$rangeDecl = $subselectIdVarDecl->rangeVariableDeclaration;
$dqlAlias = $rangeDecl->aliasIdentificationVariable;
$class = $this->_em->getClassMetadata($rangeDecl->abstractSchemaName);
$sql .= $class->getQuotedTableName($this->_platform) . ' '
. $this->getSqlTableAlias($class->table['name'], $dqlAlias);
if ($class->isInheritanceTypeJoined()) {
$sql .= $this->_generateClassTableInheritanceJoins($class, $dqlAlias);
}
foreach ($subselectIdVarDecl->joinVariableDeclarations as $joinVarDecl) {
$sql .= $this->walkJoinVariableDeclaration($joinVarDecl);
}
$sqlParts[] = $this->_platform->appendLockHint($sql, $this->_query->getHint(Query::HINT_LOCK_MODE));
}
foreach ($firstIdentificationVarDecl->joinVariableDeclarations as $joinVarDecl) {
$sql .= $this->walkJoinVariableDeclaration($joinVarDecl);
}
return $sql;
return ' FROM ' . implode(', ', $sqlParts);
}
/**
@ -1161,7 +1179,7 @@ class SqlWalker implements TreeWalker
$sql .= ' ' . $this->getSqlTableAlias($class->getTableName());
}
$this->_currentRootAlias = $deleteClause->aliasIdentificationVariable;
$this->_rootAliases[] = $deleteClause->aliasIdentificationVariable;
return $sql;
}
@ -1182,7 +1200,7 @@ class SqlWalker implements TreeWalker
$sql .= ' ' . $this->getSqlTableAlias($class->getTableName());
}
$this->_currentRootAlias = $updateClause->aliasIdentificationVariable;
$this->_rootAliases[] = $updateClause->aliasIdentificationVariable;
$sql .= ' SET ' . implode(
', ', array_map(array($this, 'walkUpdateItem'), $updateClause->updateItems)
@ -1227,7 +1245,7 @@ class SqlWalker implements TreeWalker
*/
public function walkWhereClause($whereClause)
{
$discrSql = $this->_generateDiscriminatorColumnConditionSql($this->_currentRootAlias);
$discrSql = $this->_generateDiscriminatorColumnConditionSql($this->_rootAliases);
$condSql = $this->walkConditionalExpression($whereClause->conditionalExpression);
return ' WHERE ' . (( ! $discrSql) ? $condSql : '(' . $condSql . ') AND ' . $discrSql);

View File

@ -79,6 +79,11 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
$this->assertValidDql('SELECT u.name, u.username FROM Doctrine\Tests\Models\CMS\CmsUser u');
}
public function testSelectMultipleComponentsUsingMultipleFrom()
{
$this->assertValidDql('SELECT u, p FROM Doctrine\Tests\Models\CMS\CmsUser u, Doctrine\Tests\Models\CMS\CmsPhonenumber p WHERE u = p.user');
}
public function testSelectMultipleComponentsWithAsterisk()
{
$this->assertValidDql('SELECT u, p FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.phonenumbers p');

View File

@ -72,6 +72,14 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
);
}
public function testSupportsSelectUsingMultipleFromComponents()
{
$this->assertSqlGeneration(
'SELECT u, p FROM Doctrine\Tests\Models\CMS\CmsUser u, Doctrine\Tests\Models\CMS\CmsPhonenumber p WHERE u = p.user',
'SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3, c1_.phonenumber AS phonenumber4 FROM cms_users c0_, cms_phonenumbers c1_ WHERE c0_.id = c1_.user_id'
);
}
public function testSupportsSelectWithCollectionAssociationJoin()
{
$this->assertSqlGeneration(
@ -187,8 +195,16 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
public function testSupportsMultipleEntitiesInFromClause()
{
$this->assertSqlGeneration(
'SELECT u, a FROM Doctrine\Tests\Models\CMS\CmsUser u, Doctrine\Tests\Models\CMS\CmsArticle a WHERE u.id = a.user.id',
'SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3, c1_.id AS id4, c1_.topic AS topic5, c1_.text AS text6, c1_.version AS version7 FROM cms_users c0_ INNER JOIN cms_users c2_ ON c1_.user_id = c2_.id WHERE c0_.id = c2_.id'
'SELECT u, a FROM Doctrine\Tests\Models\CMS\CmsUser u, Doctrine\Tests\Models\CMS\CmsArticle a JOIN a.user u2 WHERE u.id = u2.id',
'SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3, c1_.id AS id4, c1_.topic AS topic5, c1_.text AS text6, c1_.version AS version7 FROM cms_users c0_, cms_articles c1_ INNER JOIN cms_users c2_ ON c1_.user_id = c2_.id WHERE c0_.id = c2_.id'
);
}
public function testSupportsMultipleEntitiesInFromClauseUsingPathExpression()
{
$this->assertSqlGeneration(
'SELECT u, a FROM Doctrine\Tests\Models\CMS\CmsUser u, Doctrine\Tests\Models\CMS\CmsArticle a WHERE u.id = a.user',
'SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3, c1_.id AS id4, c1_.topic AS topic5, c1_.text AS text6, c1_.version AS version7 FROM cms_users c0_, cms_articles c1_ WHERE c0_.id = c1_.user_id'
);
}