1
0
mirror of synced 2024-12-13 22:56:04 +03:00

Major optimizations in SqlWalker code, reducing overhead, reducing lookahead checks.

This commit is contained in:
Guilherme Blanco 2011-11-03 02:44:50 -02:00
parent 058242fa27
commit 3c31d88810
3 changed files with 235 additions and 328 deletions

View File

@ -47,6 +47,11 @@ class QueryException extends \Doctrine\ORM\ORMException
return new self('[Semantical Error] ' . $message); return new self('[Semantical Error] ' . $message);
} }
public static function invalidLockMode()
{
return new self('Invalid lock mode hint provided.');
}
public static function invalidParameterType($expected, $received) public static function invalidParameterType($expected, $received)
{ {
return new self('Invalid parameter type, ' . $received . ' given, but ' . $expected . ' expected.'); return new self('Invalid parameter type, ' . $received . ' given, but ' . $expected . ' expected.');

View File

@ -257,29 +257,35 @@ class SqlWalker implements TreeWalker
// If this is a joined association we must use left joins to preserve the correct result. // If this is a joined association we must use left joins to preserve the correct result.
$sql .= isset($this->_queryComponents[$dqlAlias]['relation']) ? ' LEFT ' : ' INNER '; $sql .= isset($this->_queryComponents[$dqlAlias]['relation']) ? ' LEFT ' : ' INNER ';
$sql .= 'JOIN ' . $parentClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON '; $sql .= 'JOIN ' . $parentClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
$first = true;
$sqlParts = array();
foreach ($class->getQuotedIdentifierColumnNames($this->_platform) as $columnName) { foreach ($class->getQuotedIdentifierColumnNames($this->_platform) as $columnName) {
if ($first) $first = false; else $sql .= ' AND '; $sqlParts[] = $baseTableAlias . '.' . $columnName . ' = ' . $tableAlias . '.' . $columnName;
$sql .= $baseTableAlias . '.' . $columnName . ' = ' . $tableAlias . '.' . $columnName;
}
} }
// LEFT JOIN subclass tables, if partial objects disallowed. $sql .= implode(' AND ', $sqlParts);
if ( ! $this->_query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) { }
// Ignore subclassing inclusion if partial objects is disallowed
if ($this->_query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) {
return $sql;
}
// LEFT JOIN child class tables
foreach ($class->subClasses as $subClassName) { foreach ($class->subClasses as $subClassName) {
$subClass = $this->_em->getClassMetadata($subClassName); $subClass = $this->_em->getClassMetadata($subClassName);
$tableAlias = $this->getSQLTableAlias($subClass->getTableName(), $dqlAlias); $tableAlias = $this->getSQLTableAlias($subClass->getTableName(), $dqlAlias);
$sql .= ' LEFT JOIN ' . $subClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON '; $sql .= ' LEFT JOIN ' . $subClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
$first = true;
foreach ($class->getQuotedIdentifierColumnNames($this->_platform) as $columnName) { $sqlParts = array();
if ($first) $first = false; else $sql .= ' AND ';
$sql .= $baseTableAlias . '.' . $columnName . ' = ' . $tableAlias . '.' . $columnName; foreach ($subClass->getQuotedIdentifierColumnNames($this->_platform) as $columnName) {
} $sqlParts[] = $baseTableAlias . '.' . $columnName . ' = ' . $tableAlias . '.' . $columnName;
} }
$sql .= implode(' AND ', $sqlParts);
} }
return $sql; return $sql;
@ -287,28 +293,24 @@ class SqlWalker implements TreeWalker
private function _generateOrderedCollectionOrderByItems() private function _generateOrderedCollectionOrderByItems()
{ {
$sql = ''; $sqlParts = array();
foreach ($this->_selectedClasses AS $dqlAlias => $class) { foreach ($this->_selectedClasses AS $dqlAlias => $class) {
$qComp = $this->_queryComponents[$dqlAlias]; $qComp = $this->_queryComponents[$dqlAlias];
if (isset($qComp['relation']['orderBy'])) { if ( ! isset($qComp['relation']['orderBy'])) continue;
foreach ($qComp['relation']['orderBy'] AS $fieldName => $orientation) { foreach ($qComp['relation']['orderBy'] AS $fieldName => $orientation) {
$columnName = $qComp['metadata']->getQuotedColumnName($fieldName, $this->_platform);
$tableName = ($qComp['metadata']->isInheritanceTypeJoined()) $tableName = ($qComp['metadata']->isInheritanceTypeJoined())
? $this->_em->getUnitOfWork()->getEntityPersister($class->name)->getOwningTable($fieldName) ? $this->_em->getUnitOfWork()->getEntityPersister($class->name)->getOwningTable($fieldName)
: $qComp['metadata']->getTableName(); : $qComp['metadata']->getTableName();
if ($sql != '') { $sqlParts[] = $this->getSQLTableAlias($tableName, $dqlAlias) . '.' . $columnName . ' ' . $orientation;
$sql .= ', ';
}
$sql .= $this->getSQLTableAlias($tableName, $dqlAlias) . '.'
. $qComp['metadata']->getQuotedColumnName($fieldName, $this->_platform) . ' ' . $orientation;
}
} }
} }
return $sql; return implode(', ', $sqlParts);
} }
/** /**
@ -319,13 +321,13 @@ class SqlWalker implements TreeWalker
*/ */
private function _generateDiscriminatorColumnConditionSQL(array $dqlAliases) private function _generateDiscriminatorColumnConditionSQL(array $dqlAliases)
{ {
$encapsulate = false; $sqlParts = array();
$sql = '';
foreach ($dqlAliases as $dqlAlias) { foreach ($dqlAliases as $dqlAlias) {
$class = $this->_queryComponents[$dqlAlias]['metadata']; $class = $this->_queryComponents[$dqlAlias]['metadata'];
if ($class->isInheritanceTypeSingleTable()) { if ( ! $class->isInheritanceTypeSingleTable()) continue;
$conn = $this->_em->getConnection(); $conn = $this->_em->getConnection();
$values = array(); $values = array();
@ -337,18 +339,13 @@ class SqlWalker implements TreeWalker
$values[] = $conn->quote($this->_em->getClassMetadata($subclassName)->discriminatorValue); $values[] = $conn->quote($this->_em->getClassMetadata($subclassName)->discriminatorValue);
} }
if ($sql != '') { $sqlParts[] = (($this->_useSqlTableAliases) ? $this->getSQLTableAlias($class->getTableName(), $dqlAlias) . '.' : '')
$sql .= ' AND ';
$encapsulate = true;
}
$sql .= ($sql != '' ? ' AND ' : '')
. (($this->_useSqlTableAliases) ? $this->getSQLTableAlias($class->getTableName(), $dqlAlias) . '.' : '')
. $class->discriminatorColumn['name'] . ' IN (' . implode(', ', $values) . ')'; . $class->discriminatorColumn['name'] . ' IN (' . implode(', ', $values) . ')';
} }
}
return ($encapsulate) ? '(' . $sql . ')' : $sql; $sql = implode(' AND ', $sqlParts);
return (count($sqlParts) > 1) ? '(' . $sql . ')' : $sql;
} }
/** /**
@ -375,16 +372,25 @@ class SqlWalker implements TreeWalker
); );
if (($lockMode = $this->_query->getHint(Query::HINT_LOCK_MODE)) !== false) { if (($lockMode = $this->_query->getHint(Query::HINT_LOCK_MODE)) !== false) {
if ($lockMode == LockMode::PESSIMISTIC_READ) { switch ($lockMode) {
case LockMode::PESSIMISTIC_READ:
$sql .= ' ' . $this->_platform->getReadLockSQL(); $sql .= ' ' . $this->_platform->getReadLockSQL();
} else if ($lockMode == LockMode::PESSIMISTIC_WRITE) { break;
case LockMode::PESSIMISTIC_WRITE:
$sql .= ' ' . $this->_platform->getWriteLockSQL(); $sql .= ' ' . $this->_platform->getWriteLockSQL();
} else if ($lockMode == LockMode::OPTIMISTIC) { break;
case LockMode::PESSIMISTIC_OPTIMISTIC:
foreach ($this->_selectedClasses AS $class) { foreach ($this->_selectedClasses AS $class) {
if ( ! $class->isVersioned) { if ( ! $class->isVersioned) {
throw \Doctrine\ORM\OptimisticLockException::lockFailed($class->name); throw \Doctrine\ORM\OptimisticLockException::lockFailed($class->name);
} }
} }
break;
default:
throw \Doctrine\ORM\Query\QueryException::invalidLockMode();
} }
} }
@ -538,18 +544,17 @@ class SqlWalker implements TreeWalker
$this->_rsm->setDiscriminatorColumn($dqlAlias, $columnAlias); $this->_rsm->setDiscriminatorColumn($dqlAlias, $columnAlias);
$this->_rsm->addMetaResult($dqlAlias, $columnAlias, $discrColumn['fieldName']); $this->_rsm->addMetaResult($dqlAlias, $columnAlias, $discrColumn['fieldName']);
}
// Add foreign key columns to SQL, if necessary // Add foreign key columns to SQL, if necessary
if ($addMetaColumns) { if ( ! $addMetaColumns) continue;
//FIXME: Include foreign key columns of child classes also!!??
// Add foreign key columns of class and also parent classes
foreach ($class->associationMappings as $assoc) { foreach ($class->associationMappings as $assoc) {
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) { if ( ! ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE)) continue;
if (isset($assoc['inherited'])) {
$owningClass = $this->_em->getClassMetadata($assoc['inherited']); $owningClass = (isset($assoc['inherited'])) ? $this->_em->getClassMetadata($assoc['inherited']) : $class;
$sqlTableAlias = $this->getSQLTableAlias($owningClass->getTableName(), $dqlAlias); $sqlTableAlias = $this->getSQLTableAlias($owningClass->getTableName(), $dqlAlias);
} else {
$sqlTableAlias = $this->getSQLTableAlias($class->getTableName(), $dqlAlias);
}
foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) { foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
$columnAlias = $this->getSQLColumnAlias($srcColumn); $columnAlias = $this->getSQLColumnAlias($srcColumn);
@ -559,23 +564,24 @@ class SqlWalker implements TreeWalker
$this->_rsm->addMetaResult($dqlAlias, $columnAlias, $srcColumn, (isset($assoc['id']) && $assoc['id'] === true)); $this->_rsm->addMetaResult($dqlAlias, $columnAlias, $srcColumn, (isset($assoc['id']) && $assoc['id'] === true));
} }
} }
}
}
} else {
// Add foreign key columns to SQL, if necessary
if ($addMetaColumns) {
$sqlTableAlias = $this->getSQLTableAlias($class->getTableName(), $dqlAlias);
foreach ($class->associationMappings as $assoc) { // Add foreign key columns of subclasses
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) { foreach ($class->subClasses as $subClassName) {
$subClass = $this->_em->getClassMetadata($subClassName);
$sqlTableAlias = $this->getSQLTableAlias($subClass->getTableName(), $dqlAlias);
foreach ($subClass->associationMappings as $assoc) {
// Skip if association is inherited
if (isset($assoc['inherited'])) continue;
if ( ! ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE)) continue;
foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) { foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
$columnAlias = $this->getSQLColumnAlias($srcColumn); $columnAlias = $this->getSQLColumnAlias($srcColumn);
$sqlSelectExpressions[] = $sqlTableAlias . '.' . $srcColumn . ' AS ' . $columnAlias; $sqlSelectExpressions[] = $sqlTableAlias . '.' . $srcColumn . ' AS ' . $columnAlias;
$this->_rsm->addMetaResult($dqlAlias, $columnAlias, $srcColumn, (isset($assoc['id']) && $assoc['id'] === true)); $this->_rsm->addMetaResult($dqlAlias, $columnAlias, $srcColumn);
}
}
} }
} }
} }
@ -654,15 +660,13 @@ class SqlWalker implements TreeWalker
*/ */
public function walkOrderByClause($orderByClause) public function walkOrderByClause($orderByClause)
{ {
$colSql = $this->_generateOrderedCollectionOrderByItems(); $orderByItems = array_map(array($this, 'walkOrderByItem'), $orderByClause->orderByItems);
if ($colSql != '') {
$colSql = ", ".$colSql; if (($collectionOrderByItems = $this->_generateOrderedCollectionOrderByItems()) !== '') {
$orderByItems = array_merge($orderByItems, (array) $collectionOrderByItems);
} }
// OrderByClause ::= "ORDER" "BY" OrderByItem {"," OrderByItem}* return ' ORDER BY ' . implode(', ', $orderByItems);
return ' ORDER BY ' . implode(
', ', array_map(array($this, 'walkOrderByItem'), $orderByClause->orderByItems)
) . $colSql;
} }
/** /**
@ -673,16 +677,10 @@ class SqlWalker implements TreeWalker
*/ */
public function walkOrderByItem($orderByItem) public function walkOrderByItem($orderByItem)
{ {
$sql = '';
$expr = $orderByItem->expression; $expr = $orderByItem->expression;
$sql = ($expr instanceof AST\PathExpression)
if ($expr instanceof AST\PathExpression) { ? $this->walkPathExpression($expr)
$sql = $this->walkPathExpression($expr); : $this->_scalarResultAliasMap[$this->_queryComponents[$expr]['token']['value']];
} else {
$columnName = $this->_queryComponents[$expr]['token']['value'];
$sql = $this->_scalarResultAliasMap[$columnName];
}
return $sql . ' ' . strtoupper($orderByItem->type); return $sql . ' ' . strtoupper($orderByItem->type);
} }
@ -708,20 +706,9 @@ class SqlWalker implements TreeWalker
{ {
$join = $joinVarDecl->join; $join = $joinVarDecl->join;
$joinType = $join->joinType; $joinType = $join->joinType;
$sql = ($joinType == AST\Join::JOIN_TYPE_LEFT || $joinType == AST\Join::JOIN_TYPE_LEFTOUTER)
if ($joinVarDecl->indexBy) { ? ' LEFT JOIN '
// For Many-To-One or One-To-One associations this obviously makes no sense, but is ignored silently. : ' INNER JOIN ';
$this->_rsm->addIndexBy(
$joinVarDecl->indexBy->simpleStateFieldPathExpression->identificationVariable,
$joinVarDecl->indexBy->simpleStateFieldPathExpression->field
);
}
if ($joinType == AST\Join::JOIN_TYPE_LEFT || $joinType == AST\Join::JOIN_TYPE_LEFTOUTER) {
$sql = ' LEFT JOIN ';
} else {
$sql = ' INNER JOIN ';
}
$joinAssocPathExpr = $join->joinAssociationPathExpression; $joinAssocPathExpr = $join->joinAssociationPathExpression;
$joinedDqlAlias = $join->aliasIdentificationVariable; $joinedDqlAlias = $join->aliasIdentificationVariable;
@ -737,11 +724,9 @@ class SqlWalker implements TreeWalker
// Ensure we got the owning side, since it has all mapping info // Ensure we got the owning side, since it has all mapping info
$assoc = ( ! $relation['isOwningSide']) ? $targetClass->associationMappings[$relation['mappedBy']] : $relation; $assoc = ( ! $relation['isOwningSide']) ? $targetClass->associationMappings[$relation['mappedBy']] : $relation;
if ($this->_query->getHint(Query::HINT_INTERNAL_ITERATION) == true) { if ($this->_query->getHint(Query::HINT_INTERNAL_ITERATION) == true && $relation['type'] & ClassMetadata::TO_MANY) {
if ($relation['type'] == ClassMetadata::ONE_TO_MANY || $relation['type'] == ClassMetadata::MANY_TO_MANY) {
throw QueryException::iterateWithFetchJoinNotAllowed($assoc); throw QueryException::iterateWithFetchJoinNotAllowed($assoc);
} }
}
if ($joinVarDecl->indexBy) { if ($joinVarDecl->indexBy) {
// For Many-To-One or One-To-One associations this obviously makes no sense, but is ignored silently. // For Many-To-One or One-To-One associations this obviously makes no sense, but is ignored silently.
@ -757,7 +742,6 @@ class SqlWalker implements TreeWalker
// be the owning side and previously we ensured that $assoc is always the owning side of the associations. // be the owning side and previously we ensured that $assoc is always the owning side of the associations.
// The owning side is necessary at this point because only it contains the JoinColumn information. // The owning side is necessary at this point because only it contains the JoinColumn information.
if ($assoc['type'] & ClassMetadata::TO_ONE) { if ($assoc['type'] & ClassMetadata::TO_ONE) {
$sql .= $targetTableName . ' ' . $targetTableAlias . ' ON '; $sql .= $targetTableName . ' ' . $targetTableAlias . ' ON ';
$first = true; $first = true;
@ -984,7 +968,8 @@ class SqlWalker implements TreeWalker
$expr = $selectExpression->expression; $expr = $selectExpression->expression;
$hidden = $selectExpression->hiddenAliasResultVariable; $hidden = $selectExpression->hiddenAliasResultVariable;
if ($expr instanceof AST\PathExpression) { switch (true) {
case ($expr instanceof AST\PathExpression):
if ($expr->type !== AST\PathExpression::TYPE_STATE_FIELD) { if ($expr->type !== AST\PathExpression::TYPE_STATE_FIELD) {
throw QueryException::invalidPathExpression($expr->type); throw QueryException::invalidPathExpression($expr->type);
} }
@ -994,112 +979,60 @@ class SqlWalker implements TreeWalker
$qComp = $this->_queryComponents[$dqlAlias]; $qComp = $this->_queryComponents[$dqlAlias];
$class = $qComp['metadata']; $class = $qComp['metadata'];
$resultAlias = ( ! $selectExpression->fieldIdentificationVariable) $resultAlias = $selectExpression->fieldIdentificationVariable ?: $fieldName;
? $fieldName
: $selectExpression->fieldIdentificationVariable;
$tableName = ($class->isInheritanceTypeJoined()) $tableName = ($class->isInheritanceTypeJoined())
? $this->_em->getUnitOfWork()->getEntityPersister($class->name)->getOwningTable($fieldName) ? $this->_em->getUnitOfWork()->getEntityPersister($class->name)->getOwningTable($fieldName)
: $class->getTableName(); : $class->getTableName();
$sqlTableAlias = $this->getSQLTableAlias($tableName, $dqlAlias); $sqlTableAlias = $this->getSQLTableAlias($tableName, $dqlAlias);
$columnName = $class->getQuotedColumnName($fieldName, $this->_platform); $columnName = $class->getQuotedColumnName($fieldName, $this->_platform);
$columnAlias = $this->getSQLColumnAlias($columnName); $columnAlias = $this->getSQLColumnAlias($columnName);
$sql .= $sqlTableAlias . '.' . $columnName . ' AS ' . $columnAlias; $sql .= $sqlTableAlias . '.' . $columnName . ' AS ' . $columnAlias;
if ( ! $hidden) { if ( ! $hidden) {
$this->_rsm->addScalarResult($columnAlias, $resultAlias); $this->_rsm->addScalarResult($columnAlias, $resultAlias);
$this->_scalarFields[$dqlAlias][$fieldName] = $columnAlias; $this->_scalarFields[$dqlAlias][$fieldName] = $columnAlias;
} }
} else if ($expr instanceof AST\AggregateExpression) { break;
if ( ! $selectExpression->fieldIdentificationVariable) {
$resultAlias = $this->_scalarResultCounter++;
} else {
$resultAlias = $selectExpression->fieldIdentificationVariable;
}
case ($expr instanceof AST\AggregateExpression):
case ($expr instanceof AST\Functions\FunctionNode):
case ($expr instanceof AST\SimpleArithmeticExpression):
case ($expr instanceof AST\ArithmeticTerm):
case ($expr instanceof AST\ArithmeticFactor):
case ($expr instanceof AST\ArithmeticPrimary):
case ($expr instanceof AST\Literal):
case ($expr instanceof AST\NullIfExpression):
case ($expr instanceof AST\CoalesceExpression):
case ($expr instanceof AST\GeneralCaseExpression):
case ($expr instanceof AST\SimpleCaseExpression):
$columnAlias = $this->getSQLColumnAlias('sclr'); $columnAlias = $this->getSQLColumnAlias('sclr');
$sql .= $this->walkAggregateExpression($expr) . ' AS ' . $columnAlias; $resultAlias = $selectExpression->fieldIdentificationVariable ?: $this->_scalarResultCounter++;
$sql .= $expr->dispatch($this) . ' AS ' . $columnAlias;
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias; $this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
if ( ! $hidden) { if ( ! $hidden) {
$this->_rsm->addScalarResult($columnAlias, $resultAlias); $this->_rsm->addScalarResult($columnAlias, $resultAlias);
} }
} else if ($expr instanceof AST\Subselect) { break;
if ( ! $selectExpression->fieldIdentificationVariable) {
$resultAlias = $this->_scalarResultCounter++;
} else {
$resultAlias = $selectExpression->fieldIdentificationVariable;
}
case ($expr instanceof AST\Subselect):
$columnAlias = $this->getSQLColumnAlias('sclr'); $columnAlias = $this->getSQLColumnAlias('sclr');
$resultAlias = $selectExpression->fieldIdentificationVariable ?: $this->_scalarResultCounter++;
$sql .= '(' . $this->walkSubselect($expr) . ') AS '.$columnAlias; $sql .= '(' . $this->walkSubselect($expr) . ') AS '.$columnAlias;
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
if ( ! $hidden) {
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
}
} else if ($expr instanceof AST\Functions\FunctionNode) {
if ( ! $selectExpression->fieldIdentificationVariable) {
$resultAlias = $this->_scalarResultCounter++;
} else {
$resultAlias = $selectExpression->fieldIdentificationVariable;
}
$columnAlias = $this->getSQLColumnAlias('sclr');
$sql .= $this->walkFunction($expr) . ' AS ' . $columnAlias;
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
if ( ! $hidden) {
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
}
} else if (
$expr instanceof AST\SimpleArithmeticExpression ||
$expr instanceof AST\ArithmeticTerm ||
$expr instanceof AST\ArithmeticFactor ||
$expr instanceof AST\ArithmeticPrimary ||
$expr instanceof AST\Literal
) {
if ( ! $selectExpression->fieldIdentificationVariable) {
$resultAlias = $this->_scalarResultCounter++;
} else {
$resultAlias = $selectExpression->fieldIdentificationVariable;
}
$columnAlias = $this->getSQLColumnAlias('sclr');
if ($expr instanceof AST\Literal) {
$sql .= $this->walkLiteral($expr) . ' AS ' .$columnAlias;
} else {
$sql .= $this->walkSimpleArithmeticExpression($expr) . ' AS ' . $columnAlias;
}
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias; $this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
if ( ! $hidden) { if ( ! $hidden) {
$this->_rsm->addScalarResult($columnAlias, $resultAlias); $this->_rsm->addScalarResult($columnAlias, $resultAlias);
} }
} else if ( break;
$expr instanceof AST\NullIfExpression ||
$expr instanceof AST\CoalesceExpression ||
$expr instanceof AST\GeneralCaseExpression ||
$expr instanceof AST\SimpleCaseExpression
) {
if ( ! $selectExpression->fieldIdentificationVariable) {
$resultAlias = $this->_scalarResultCounter++;
} else {
$resultAlias = $selectExpression->fieldIdentificationVariable;
}
$columnAlias = $this->getSQLColumnAlias('sclr'); default:
$sql .= $this->walkCaseExpression($expr) . ' AS ' . $columnAlias;
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
if ( ! $hidden) {
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
}
} else {
// IdentificationVariable or PartialObjectExpression // IdentificationVariable or PartialObjectExpression
if ($expr instanceof AST\PartialObjectExpression) { if ($expr instanceof AST\PartialObjectExpression) {
$dqlAlias = $expr->identificationVariable; $dqlAlias = $expr->identificationVariable;
@ -1160,21 +1093,6 @@ class SqlWalker implements TreeWalker
$this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $subClassName); $this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $subClassName);
} }
// Add join columns (foreign keys) of the subclass
//TODO: Probably better do this in walkSelectClause to honor the INCLUDE_META_COLUMNS hint
foreach ($subClass->associationMappings as $fieldName => $assoc) {
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE && ! isset($assoc['inherited'])) {
foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
if ($beginning) $beginning = false; else $sql .= ', ';
$columnAlias = $this->getSQLColumnAlias($srcColumn);
$sql .= $sqlTableAlias . '.' . $srcColumn . ' AS ' . $columnAlias;
$this->_rsm->addMetaResult($dqlAlias, $columnAlias, $srcColumn);
}
}
}
} }
} }
} }
@ -1302,27 +1220,11 @@ class SqlWalker implements TreeWalker
break; break;
case ($expr instanceof AST\Functions\FunctionNode): case ($expr instanceof AST\Functions\FunctionNode):
$alias = $simpleSelectExpression->fieldIdentificationVariable ?: $this->_scalarResultCounter++;
$columnAlias = $this->getSQLColumnAlias('sclr');
$this->_scalarResultAliasMap[$alias] = $columnAlias;
$sql .= $this->walkFunction($expr) . ' AS ' . $columnAlias;
break;
case ($expr instanceof AST\SimpleArithmeticExpression): case ($expr instanceof AST\SimpleArithmeticExpression):
case ($expr instanceof AST\ArithmeticTerm): case ($expr instanceof AST\ArithmeticTerm):
case ($expr instanceof AST\ArithmeticFactor): case ($expr instanceof AST\ArithmeticFactor):
case ($expr instanceof AST\ArithmeticPrimary): case ($expr instanceof AST\ArithmeticPrimary):
case ($expr instanceof AST\Literal): case ($expr instanceof AST\Literal):
$alias = $simpleSelectExpression->fieldIdentificationVariable ?: $this->_scalarResultCounter++;
$columnAlias = $this->getSQLColumnAlias('sclr');
$this->_scalarResultAliasMap[$alias] = $columnAlias;
$sql .= $this->walkSimpleArithmeticExpression($expr) . ' AS ' . $columnAlias;
break;
case ($expr instanceof AST\NullIfExpression): case ($expr instanceof AST\NullIfExpression):
case ($expr instanceof AST\CoalesceExpression): case ($expr instanceof AST\CoalesceExpression):
case ($expr instanceof AST\GeneralCaseExpression): case ($expr instanceof AST\GeneralCaseExpression):
@ -1332,7 +1234,7 @@ class SqlWalker implements TreeWalker
$columnAlias = $this->getSQLColumnAlias('sclr'); $columnAlias = $this->getSQLColumnAlias('sclr');
$this->_scalarResultAliasMap[$alias] = $columnAlias; $this->_scalarResultAliasMap[$alias] = $columnAlias;
$sql .= $this->walkCaseExpression($expr) . ' AS ' . $columnAlias; $sql .= $expr->dispatch($this) . ' AS ' . $columnAlias;
break; break;
default: // IdentificationVariable default: // IdentificationVariable

View File

@ -563,7 +563,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
$this->_em->getClassMetadata(get_class($person))->setIdentifierValues($person, array('id' => 101)); $this->_em->getClassMetadata(get_class($person))->setIdentifierValues($person, array('id' => 101));
$q3->setParameter('param', $person); $q3->setParameter('param', $person);
$this->assertEquals( $this->assertEquals(
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.title AS title2, c1_.car_id AS car_id3, c2_.salary AS salary4, c2_.department AS department5, c2_.startDate AS startDate6, c0_.discr AS discr7, c0_.spouse_id AS spouse_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 = ?)', '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() $q3->getSql()
); );
} }
@ -1120,7 +1120,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
{ {
$this->assertSqlGeneration( $this->assertSqlGeneration(
'SELECT p FROM Doctrine\Tests\Models\Company\CompanyPerson p', 'SELECT p FROM Doctrine\Tests\Models\Company\CompanyPerson p',
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.title AS title2, c1_.car_id AS car_id3, c2_.salary AS salary4, c2_.department AS department5, c2_.startDate AS startDate6, c0_.discr AS discr7, c0_.spouse_id AS spouse_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', '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',
array(Query::HINT_FORCE_PARTIAL_LOAD => false) array(Query::HINT_FORCE_PARTIAL_LOAD => false)
); );
} }
@ -1144,7 +1144,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
{ {
$this->assertSqlGeneration( $this->assertSqlGeneration(
'SELECT e FROM Doctrine\Tests\Models\Company\CompanyEmployee e', 'SELECT e FROM Doctrine\Tests\Models\Company\CompanyEmployee e',
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c1_.startDate AS startDate4, c2_.title AS title5, c2_.car_id AS car_id6, c0_.discr AS discr7, c0_.spouse_id AS spouse_id8 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id LEFT JOIN company_managers c2_ ON c1_.id = c2_.id', 'SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c1_.startDate AS startDate4, c2_.title AS title5, c0_.discr AS discr6, c0_.spouse_id AS spouse_id7, c2_.car_id AS car_id8 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id LEFT JOIN company_managers c2_ ON c1_.id = c2_.id',
array(Query::HINT_FORCE_PARTIAL_LOAD => false) array(Query::HINT_FORCE_PARTIAL_LOAD => false)
); );
} }
@ -1264,7 +1264,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
{ {
$this->assertSqlGeneration( $this->assertSqlGeneration(
'SELECT p, pp FROM Doctrine\Tests\Models\Company\CompanyPerson p JOIN p.spouse pp', 'SELECT p, pp FROM Doctrine\Tests\Models\Company\CompanyPerson p JOIN p.spouse pp',
"SELECT c0_.id AS id0, c0_.name AS name1, c1_.title AS title2, c1_.car_id AS car_id3, c2_.salary AS salary4, c2_.department AS department5, c2_.startDate AS startDate6, c3_.id AS id7, c3_.name AS name8, c4_.title AS title9, c4_.car_id AS car_id10, c5_.salary AS salary11, c5_.department AS department12, c5_.startDate AS startDate13, c0_.discr AS discr14, c0_.spouse_id AS spouse_id15, c3_.discr AS discr16, c3_.spouse_id AS spouse_id17 FROM company_persons c0_ LEFT JOIN company_managers c1_ ON c0_.id = c1_.id LEFT JOIN company_employees c2_ ON c0_.id = c2_.id INNER JOIN company_persons c3_ ON c0_.spouse_id = c3_.id LEFT JOIN company_managers c4_ ON c3_.id = c4_.id LEFT JOIN company_employees c5_ ON c3_.id = c5_.id", "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, c3_.id AS id6, c3_.name AS name7, c4_.title AS title8, c5_.salary AS salary9, c5_.department AS department10, c5_.startDate AS startDate11, c0_.discr AS discr12, c0_.spouse_id AS spouse_id13, c1_.car_id AS car_id14, c3_.discr AS discr15, c3_.spouse_id AS spouse_id16, c4_.car_id AS car_id17 FROM company_persons c0_ LEFT JOIN company_managers c1_ ON c0_.id = c1_.id LEFT JOIN company_employees c2_ ON c0_.id = c2_.id INNER JOIN company_persons c3_ ON c0_.spouse_id = c3_.id LEFT JOIN company_managers c4_ ON c3_.id = c4_.id LEFT JOIN company_employees c5_ ON c3_.id = c5_.id",
array(Query::HINT_FORCE_PARTIAL_LOAD => false) array(Query::HINT_FORCE_PARTIAL_LOAD => false)
); );
} }