Major optimizations in SqlWalker code, reducing overhead, reducing lookahead checks.
This commit is contained in:
parent
058242fa27
commit
3c31d88810
@ -47,6 +47,11 @@ class QueryException extends \Doctrine\ORM\ORMException
|
||||
return new self('[Semantical Error] ' . $message);
|
||||
}
|
||||
|
||||
public static function invalidLockMode()
|
||||
{
|
||||
return new self('Invalid lock mode hint provided.');
|
||||
}
|
||||
|
||||
public static function invalidParameterType($expected, $received)
|
||||
{
|
||||
return new self('Invalid parameter type, ' . $received . ' given, but ' . $expected . ' expected.');
|
||||
|
@ -252,34 +252,40 @@ class SqlWalker implements TreeWalker
|
||||
// INNER JOIN parent class tables
|
||||
foreach ($class->parentClasses as $parentClassName) {
|
||||
$parentClass = $this->_em->getClassMetadata($parentClassName);
|
||||
$tableAlias = $this->getSQLTableAlias($parentClass->getTableName(), $dqlAlias);
|
||||
$tableAlias = $this->getSQLTableAlias($parentClass->getTableName(), $dqlAlias);
|
||||
|
||||
// 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 .= 'JOIN ' . $parentClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
|
||||
$first = true;
|
||||
|
||||
$sqlParts = array();
|
||||
|
||||
foreach ($class->getQuotedIdentifierColumnNames($this->_platform) as $columnName) {
|
||||
if ($first) $first = false; else $sql .= ' AND ';
|
||||
|
||||
$sql .= $baseTableAlias . '.' . $columnName . ' = ' . $tableAlias . '.' . $columnName;
|
||||
$sqlParts[] = $baseTableAlias . '.' . $columnName . ' = ' . $tableAlias . '.' . $columnName;
|
||||
}
|
||||
|
||||
$sql .= implode(' AND ', $sqlParts);
|
||||
}
|
||||
|
||||
// LEFT JOIN subclass tables, if partial objects disallowed.
|
||||
if ( ! $this->_query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) {
|
||||
foreach ($class->subClasses as $subClassName) {
|
||||
$subClass = $this->_em->getClassMetadata($subClassName);
|
||||
$tableAlias = $this->getSQLTableAlias($subClass->getTableName(), $dqlAlias);
|
||||
$sql .= ' LEFT JOIN ' . $subClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
|
||||
$first = true;
|
||||
// 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) {
|
||||
$subClass = $this->_em->getClassMetadata($subClassName);
|
||||
$tableAlias = $this->getSQLTableAlias($subClass->getTableName(), $dqlAlias);
|
||||
|
||||
foreach ($class->getQuotedIdentifierColumnNames($this->_platform) as $columnName) {
|
||||
if ($first) $first = false; else $sql .= ' AND ';
|
||||
$sql .= ' LEFT JOIN ' . $subClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
|
||||
|
||||
$sql .= $baseTableAlias . '.' . $columnName . ' = ' . $tableAlias . '.' . $columnName;
|
||||
}
|
||||
$sqlParts = array();
|
||||
|
||||
foreach ($subClass->getQuotedIdentifierColumnNames($this->_platform) as $columnName) {
|
||||
$sqlParts[] = $baseTableAlias . '.' . $columnName . ' = ' . $tableAlias . '.' . $columnName;
|
||||
}
|
||||
|
||||
$sql .= implode(' AND ', $sqlParts);
|
||||
}
|
||||
|
||||
return $sql;
|
||||
@ -287,28 +293,24 @@ class SqlWalker implements TreeWalker
|
||||
|
||||
private function _generateOrderedCollectionOrderByItems()
|
||||
{
|
||||
$sql = '';
|
||||
|
||||
$sqlParts = array();
|
||||
|
||||
foreach ($this->_selectedClasses AS $dqlAlias => $class) {
|
||||
$qComp = $this->_queryComponents[$dqlAlias];
|
||||
|
||||
if (isset($qComp['relation']['orderBy'])) {
|
||||
foreach ($qComp['relation']['orderBy'] AS $fieldName => $orientation) {
|
||||
$tableName = ($qComp['metadata']->isInheritanceTypeJoined())
|
||||
? $this->_em->getUnitOfWork()->getEntityPersister($class->name)->getOwningTable($fieldName)
|
||||
: $qComp['metadata']->getTableName();
|
||||
|
||||
if ($sql != '') {
|
||||
$sql .= ', ';
|
||||
}
|
||||
|
||||
$sql .= $this->getSQLTableAlias($tableName, $dqlAlias) . '.'
|
||||
. $qComp['metadata']->getQuotedColumnName($fieldName, $this->_platform) . ' ' . $orientation;
|
||||
}
|
||||
if ( ! isset($qComp['relation']['orderBy'])) continue;
|
||||
|
||||
foreach ($qComp['relation']['orderBy'] AS $fieldName => $orientation) {
|
||||
$columnName = $qComp['metadata']->getQuotedColumnName($fieldName, $this->_platform);
|
||||
$tableName = ($qComp['metadata']->isInheritanceTypeJoined())
|
||||
? $this->_em->getUnitOfWork()->getEntityPersister($class->name)->getOwningTable($fieldName)
|
||||
: $qComp['metadata']->getTableName();
|
||||
|
||||
$sqlParts[] = $this->getSQLTableAlias($tableName, $dqlAlias) . '.' . $columnName . ' ' . $orientation;
|
||||
}
|
||||
}
|
||||
|
||||
return $sql;
|
||||
return implode(', ', $sqlParts);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -319,36 +321,31 @@ class SqlWalker implements TreeWalker
|
||||
*/
|
||||
private function _generateDiscriminatorColumnConditionSQL(array $dqlAliases)
|
||||
{
|
||||
$encapsulate = false;
|
||||
$sql = '';
|
||||
$sqlParts = array();
|
||||
|
||||
foreach ($dqlAliases as $dqlAlias) {
|
||||
$class = $this->_queryComponents[$dqlAlias]['metadata'];
|
||||
|
||||
if ($class->isInheritanceTypeSingleTable()) {
|
||||
$conn = $this->_em->getConnection();
|
||||
$values = array();
|
||||
if ( ! $class->isInheritanceTypeSingleTable()) continue;
|
||||
|
||||
$conn = $this->_em->getConnection();
|
||||
$values = array();
|
||||
|
||||
if ($class->discriminatorValue !== null) { // discrimnators can be 0
|
||||
$values[] = $conn->quote($class->discriminatorValue);
|
||||
}
|
||||
|
||||
foreach ($class->subClasses as $subclassName) {
|
||||
$values[] = $conn->quote($this->_em->getClassMetadata($subclassName)->discriminatorValue);
|
||||
}
|
||||
|
||||
if ($sql != '') {
|
||||
$sql .= ' AND ';
|
||||
$encapsulate = true;
|
||||
}
|
||||
|
||||
$sql .= ($sql != '' ? ' AND ' : '')
|
||||
. (($this->_useSqlTableAliases) ? $this->getSQLTableAlias($class->getTableName(), $dqlAlias) . '.' : '')
|
||||
. $class->discriminatorColumn['name'] . ' IN (' . implode(', ', $values) . ')';
|
||||
if ($class->discriminatorValue !== null) { // discrimnators can be 0
|
||||
$values[] = $conn->quote($class->discriminatorValue);
|
||||
}
|
||||
|
||||
foreach ($class->subClasses as $subclassName) {
|
||||
$values[] = $conn->quote($this->_em->getClassMetadata($subclassName)->discriminatorValue);
|
||||
}
|
||||
|
||||
$sqlParts[] = (($this->_useSqlTableAliases) ? $this->getSQLTableAlias($class->getTableName(), $dqlAlias) . '.' : '')
|
||||
. $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 == LockMode::PESSIMISTIC_READ) {
|
||||
$sql .= ' ' . $this->_platform->getReadLockSQL();
|
||||
} else if ($lockMode == LockMode::PESSIMISTIC_WRITE) {
|
||||
$sql .= ' ' . $this->_platform->getWriteLockSQL();
|
||||
} else if ($lockMode == LockMode::OPTIMISTIC) {
|
||||
foreach ($this->_selectedClasses AS $class) {
|
||||
if ( ! $class->isVersioned) {
|
||||
throw \Doctrine\ORM\OptimisticLockException::lockFailed($class->name);
|
||||
switch ($lockMode) {
|
||||
case LockMode::PESSIMISTIC_READ:
|
||||
$sql .= ' ' . $this->_platform->getReadLockSQL();
|
||||
break;
|
||||
|
||||
case LockMode::PESSIMISTIC_WRITE:
|
||||
$sql .= ' ' . $this->_platform->getWriteLockSQL();
|
||||
break;
|
||||
|
||||
case LockMode::PESSIMISTIC_OPTIMISTIC:
|
||||
foreach ($this->_selectedClasses AS $class) {
|
||||
if ( ! $class->isVersioned) {
|
||||
throw \Doctrine\ORM\OptimisticLockException::lockFailed($class->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw \Doctrine\ORM\Query\QueryException::invalidLockMode();
|
||||
}
|
||||
}
|
||||
|
||||
@ -529,8 +535,8 @@ class SqlWalker implements TreeWalker
|
||||
|
||||
if ($class->isInheritanceTypeSingleTable() || $class->isInheritanceTypeJoined()) {
|
||||
// Add discriminator columns to SQL
|
||||
$rootClass = $this->_em->getClassMetadata($class->rootEntityName);
|
||||
$tblAlias = $this->getSQLTableAlias($rootClass->getTableName(), $dqlAlias);
|
||||
$rootClass = $this->_em->getClassMetadata($class->rootEntityName);
|
||||
$tblAlias = $this->getSQLTableAlias($rootClass->getTableName(), $dqlAlias);
|
||||
$discrColumn = $rootClass->discriminatorColumn;
|
||||
$columnAlias = $this->getSQLColumnAlias($discrColumn['name']);
|
||||
|
||||
@ -538,44 +544,44 @@ class SqlWalker implements TreeWalker
|
||||
|
||||
$this->_rsm->setDiscriminatorColumn($dqlAlias, $columnAlias);
|
||||
$this->_rsm->addMetaResult($dqlAlias, $columnAlias, $discrColumn['fieldName']);
|
||||
}
|
||||
|
||||
// Add foreign key columns to SQL, if necessary
|
||||
if ( ! $addMetaColumns) continue;
|
||||
|
||||
// Add foreign key columns of class and also parent classes
|
||||
foreach ($class->associationMappings as $assoc) {
|
||||
if ( ! ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE)) continue;
|
||||
|
||||
// Add foreign key columns to SQL, if necessary
|
||||
if ($addMetaColumns) {
|
||||
//FIXME: Include foreign key columns of child classes also!!??
|
||||
foreach ($class->associationMappings as $assoc) {
|
||||
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
|
||||
if (isset($assoc['inherited'])) {
|
||||
$owningClass = $this->_em->getClassMetadata($assoc['inherited']);
|
||||
$sqlTableAlias = $this->getSQLTableAlias($owningClass->getTableName(), $dqlAlias);
|
||||
} else {
|
||||
$sqlTableAlias = $this->getSQLTableAlias($class->getTableName(), $dqlAlias);
|
||||
}
|
||||
$owningClass = (isset($assoc['inherited'])) ? $this->_em->getClassMetadata($assoc['inherited']) : $class;
|
||||
$sqlTableAlias = $this->getSQLTableAlias($owningClass->getTableName(), $dqlAlias);
|
||||
|
||||
foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
|
||||
$columnAlias = $this->getSQLColumnAlias($srcColumn);
|
||||
foreach ($assoc['targetToSourceKeyColumns'] as $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, (isset($assoc['id']) && $assoc['id'] === true));
|
||||
}
|
||||
} else {
|
||||
// Add foreign key columns to SQL, if necessary
|
||||
if ($addMetaColumns) {
|
||||
$sqlTableAlias = $this->getSQLTableAlias($class->getTableName(), $dqlAlias);
|
||||
}
|
||||
|
||||
// Add foreign key columns of subclasses
|
||||
foreach ($class->subClasses as $subClassName) {
|
||||
$subClass = $this->_em->getClassMetadata($subClassName);
|
||||
$sqlTableAlias = $this->getSQLTableAlias($subClass->getTableName(), $dqlAlias);
|
||||
|
||||
foreach ($class->associationMappings as $assoc) {
|
||||
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
|
||||
foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
|
||||
$columnAlias = $this->getSQLColumnAlias($srcColumn);
|
||||
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) {
|
||||
$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)
|
||||
{
|
||||
$colSql = $this->_generateOrderedCollectionOrderByItems();
|
||||
if ($colSql != '') {
|
||||
$colSql = ", ".$colSql;
|
||||
$orderByItems = array_map(array($this, 'walkOrderByItem'), $orderByClause->orderByItems);
|
||||
|
||||
if (($collectionOrderByItems = $this->_generateOrderedCollectionOrderByItems()) !== '') {
|
||||
$orderByItems = array_merge($orderByItems, (array) $collectionOrderByItems);
|
||||
}
|
||||
|
||||
// OrderByClause ::= "ORDER" "BY" OrderByItem {"," OrderByItem}*
|
||||
return ' ORDER BY ' . implode(
|
||||
', ', array_map(array($this, 'walkOrderByItem'), $orderByClause->orderByItems)
|
||||
) . $colSql;
|
||||
|
||||
return ' ORDER BY ' . implode(', ', $orderByItems);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -673,16 +677,10 @@ class SqlWalker implements TreeWalker
|
||||
*/
|
||||
public function walkOrderByItem($orderByItem)
|
||||
{
|
||||
$sql = '';
|
||||
$expr = $orderByItem->expression;
|
||||
|
||||
if ($expr instanceof AST\PathExpression) {
|
||||
$sql = $this->walkPathExpression($expr);
|
||||
} else {
|
||||
$columnName = $this->_queryComponents[$expr]['token']['value'];
|
||||
|
||||
$sql = $this->_scalarResultAliasMap[$columnName];
|
||||
}
|
||||
$sql = ($expr instanceof AST\PathExpression)
|
||||
? $this->walkPathExpression($expr)
|
||||
: $this->_scalarResultAliasMap[$this->_queryComponents[$expr]['token']['value']];
|
||||
|
||||
return $sql . ' ' . strtoupper($orderByItem->type);
|
||||
}
|
||||
@ -706,22 +704,11 @@ class SqlWalker implements TreeWalker
|
||||
*/
|
||||
public function walkJoinVariableDeclaration($joinVarDecl)
|
||||
{
|
||||
$join = $joinVarDecl->join;
|
||||
$join = $joinVarDecl->join;
|
||||
$joinType = $join->joinType;
|
||||
|
||||
if ($joinVarDecl->indexBy) {
|
||||
// For Many-To-One or One-To-One associations this obviously makes no sense, but is ignored silently.
|
||||
$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 ';
|
||||
}
|
||||
$sql = ($joinType == AST\Join::JOIN_TYPE_LEFT || $joinType == AST\Join::JOIN_TYPE_LEFTOUTER)
|
||||
? ' LEFT JOIN '
|
||||
: ' INNER JOIN ';
|
||||
|
||||
$joinAssocPathExpr = $join->joinAssociationPathExpression;
|
||||
$joinedDqlAlias = $join->aliasIdentificationVariable;
|
||||
@ -737,10 +724,8 @@ class SqlWalker implements TreeWalker
|
||||
// Ensure we got the owning side, since it has all mapping info
|
||||
$assoc = ( ! $relation['isOwningSide']) ? $targetClass->associationMappings[$relation['mappedBy']] : $relation;
|
||||
|
||||
if ($this->_query->getHint(Query::HINT_INTERNAL_ITERATION) == true) {
|
||||
if ($relation['type'] == ClassMetadata::ONE_TO_MANY || $relation['type'] == ClassMetadata::MANY_TO_MANY) {
|
||||
throw QueryException::iterateWithFetchJoinNotAllowed($assoc);
|
||||
}
|
||||
if ($this->_query->getHint(Query::HINT_INTERNAL_ITERATION) == true && $relation['type'] & ClassMetadata::TO_MANY) {
|
||||
throw QueryException::iterateWithFetchJoinNotAllowed($assoc);
|
||||
}
|
||||
|
||||
if ($joinVarDecl->indexBy) {
|
||||
@ -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.
|
||||
// The owning side is necessary at this point because only it contains the JoinColumn information.
|
||||
if ($assoc['type'] & ClassMetadata::TO_ONE) {
|
||||
|
||||
$sql .= $targetTableName . ' ' . $targetTableAlias . ' ON ';
|
||||
$first = true;
|
||||
|
||||
@ -984,199 +968,133 @@ class SqlWalker implements TreeWalker
|
||||
$expr = $selectExpression->expression;
|
||||
$hidden = $selectExpression->hiddenAliasResultVariable;
|
||||
|
||||
if ($expr instanceof AST\PathExpression) {
|
||||
if ($expr->type !== AST\PathExpression::TYPE_STATE_FIELD) {
|
||||
throw QueryException::invalidPathExpression($expr->type);
|
||||
}
|
||||
|
||||
$fieldName = $expr->field;
|
||||
$dqlAlias = $expr->identificationVariable;
|
||||
$qComp = $this->_queryComponents[$dqlAlias];
|
||||
$class = $qComp['metadata'];
|
||||
|
||||
$resultAlias = ( ! $selectExpression->fieldIdentificationVariable)
|
||||
? $fieldName
|
||||
: $selectExpression->fieldIdentificationVariable;
|
||||
|
||||
$tableName = ($class->isInheritanceTypeJoined())
|
||||
? $this->_em->getUnitOfWork()->getEntityPersister($class->name)->getOwningTable($fieldName)
|
||||
: $class->getTableName();
|
||||
|
||||
$sqlTableAlias = $this->getSQLTableAlias($tableName, $dqlAlias);
|
||||
$columnName = $class->getQuotedColumnName($fieldName, $this->_platform);
|
||||
|
||||
$columnAlias = $this->getSQLColumnAlias($columnName);
|
||||
$sql .= $sqlTableAlias . '.' . $columnName . ' AS ' . $columnAlias;
|
||||
|
||||
if ( ! $hidden) {
|
||||
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
||||
$this->_scalarFields[$dqlAlias][$fieldName] = $columnAlias;
|
||||
}
|
||||
} else if ($expr instanceof AST\AggregateExpression) {
|
||||
if ( ! $selectExpression->fieldIdentificationVariable) {
|
||||
$resultAlias = $this->_scalarResultCounter++;
|
||||
} else {
|
||||
$resultAlias = $selectExpression->fieldIdentificationVariable;
|
||||
}
|
||||
|
||||
$columnAlias = $this->getSQLColumnAlias('sclr');
|
||||
$sql .= $this->walkAggregateExpression($expr) . ' AS ' . $columnAlias;
|
||||
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
|
||||
|
||||
if ( ! $hidden) {
|
||||
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
||||
}
|
||||
} else if ($expr instanceof AST\Subselect) {
|
||||
if ( ! $selectExpression->fieldIdentificationVariable) {
|
||||
$resultAlias = $this->_scalarResultCounter++;
|
||||
} else {
|
||||
$resultAlias = $selectExpression->fieldIdentificationVariable;
|
||||
}
|
||||
|
||||
$columnAlias = $this->getSQLColumnAlias('sclr');
|
||||
$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;
|
||||
|
||||
if ( ! $hidden) {
|
||||
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
||||
}
|
||||
} else if (
|
||||
$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');
|
||||
$sql .= $this->walkCaseExpression($expr) . ' AS ' . $columnAlias;
|
||||
|
||||
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
|
||||
|
||||
if ( ! $hidden) {
|
||||
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
||||
}
|
||||
} else {
|
||||
// IdentificationVariable or PartialObjectExpression
|
||||
if ($expr instanceof AST\PartialObjectExpression) {
|
||||
$dqlAlias = $expr->identificationVariable;
|
||||
$partialFieldSet = $expr->partialFieldSet;
|
||||
} else {
|
||||
$dqlAlias = $expr;
|
||||
$partialFieldSet = array();
|
||||
}
|
||||
|
||||
$queryComp = $this->_queryComponents[$dqlAlias];
|
||||
$class = $queryComp['metadata'];
|
||||
|
||||
if ( ! isset($this->_selectedClasses[$dqlAlias])) {
|
||||
$this->_selectedClasses[$dqlAlias] = $class;
|
||||
}
|
||||
|
||||
$beginning = true;
|
||||
|
||||
// Select all fields from the queried class
|
||||
foreach ($class->fieldMappings as $fieldName => $mapping) {
|
||||
if ($partialFieldSet && !in_array($fieldName, $partialFieldSet)) {
|
||||
continue;
|
||||
switch (true) {
|
||||
case ($expr instanceof AST\PathExpression):
|
||||
if ($expr->type !== AST\PathExpression::TYPE_STATE_FIELD) {
|
||||
throw QueryException::invalidPathExpression($expr->type);
|
||||
}
|
||||
|
||||
$tableName = (isset($mapping['inherited']))
|
||||
? $this->_em->getClassMetadata($mapping['inherited'])->getTableName()
|
||||
$fieldName = $expr->field;
|
||||
$dqlAlias = $expr->identificationVariable;
|
||||
$qComp = $this->_queryComponents[$dqlAlias];
|
||||
$class = $qComp['metadata'];
|
||||
|
||||
$resultAlias = $selectExpression->fieldIdentificationVariable ?: $fieldName;
|
||||
$tableName = ($class->isInheritanceTypeJoined())
|
||||
? $this->_em->getUnitOfWork()->getEntityPersister($class->name)->getOwningTable($fieldName)
|
||||
: $class->getTableName();
|
||||
|
||||
if ($beginning) $beginning = false; else $sql .= ', ';
|
||||
|
||||
$sqlTableAlias = $this->getSQLTableAlias($tableName, $dqlAlias);
|
||||
$columnAlias = $this->getSQLColumnAlias($mapping['columnName']);
|
||||
$sql .= $sqlTableAlias . '.' . $class->getQuotedColumnName($fieldName, $this->_platform)
|
||||
. ' AS ' . $columnAlias;
|
||||
$columnName = $class->getQuotedColumnName($fieldName, $this->_platform);
|
||||
$columnAlias = $this->getSQLColumnAlias($columnName);
|
||||
|
||||
$sql .= $sqlTableAlias . '.' . $columnName . ' AS ' . $columnAlias;
|
||||
|
||||
$this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $class->name);
|
||||
}
|
||||
if ( ! $hidden) {
|
||||
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
||||
$this->_scalarFields[$dqlAlias][$fieldName] = $columnAlias;
|
||||
}
|
||||
break;
|
||||
|
||||
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');
|
||||
$resultAlias = $selectExpression->fieldIdentificationVariable ?: $this->_scalarResultCounter++;
|
||||
|
||||
$sql .= $expr->dispatch($this) . ' AS ' . $columnAlias;
|
||||
|
||||
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
|
||||
|
||||
// Add any additional fields of subclasses (excluding inherited fields)
|
||||
// 1) on Single Table Inheritance: always, since its marginal overhead
|
||||
// 2) on Class Table Inheritance only if partial objects are disallowed,
|
||||
// since it requires outer joining subtables.
|
||||
if ($class->isInheritanceTypeSingleTable() || ! $this->_query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) {
|
||||
foreach ($class->subClasses as $subClassName) {
|
||||
$subClass = $this->_em->getClassMetadata($subClassName);
|
||||
$sqlTableAlias = $this->getSQLTableAlias($subClass->getTableName(), $dqlAlias);
|
||||
if ( ! $hidden) {
|
||||
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
||||
}
|
||||
break;
|
||||
|
||||
case ($expr instanceof AST\Subselect):
|
||||
$columnAlias = $this->getSQLColumnAlias('sclr');
|
||||
$resultAlias = $selectExpression->fieldIdentificationVariable ?: $this->_scalarResultCounter++;
|
||||
|
||||
$sql .= '(' . $this->walkSubselect($expr) . ') AS '.$columnAlias;
|
||||
|
||||
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
|
||||
|
||||
foreach ($subClass->fieldMappings as $fieldName => $mapping) {
|
||||
if (isset($mapping['inherited']) || $partialFieldSet && !in_array($fieldName, $partialFieldSet)) {
|
||||
continue;
|
||||
}
|
||||
if ( ! $hidden) {
|
||||
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// IdentificationVariable or PartialObjectExpression
|
||||
if ($expr instanceof AST\PartialObjectExpression) {
|
||||
$dqlAlias = $expr->identificationVariable;
|
||||
$partialFieldSet = $expr->partialFieldSet;
|
||||
} else {
|
||||
$dqlAlias = $expr;
|
||||
$partialFieldSet = array();
|
||||
}
|
||||
|
||||
if ($beginning) $beginning = false; else $sql .= ', ';
|
||||
$queryComp = $this->_queryComponents[$dqlAlias];
|
||||
$class = $queryComp['metadata'];
|
||||
|
||||
$columnAlias = $this->getSQLColumnAlias($mapping['columnName']);
|
||||
$sql .= $sqlTableAlias . '.' . $subClass->getQuotedColumnName($fieldName, $this->_platform)
|
||||
. ' AS ' . $columnAlias;
|
||||
if ( ! isset($this->_selectedClasses[$dqlAlias])) {
|
||||
$this->_selectedClasses[$dqlAlias] = $class;
|
||||
}
|
||||
|
||||
$this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $subClassName);
|
||||
$beginning = true;
|
||||
|
||||
// Select all fields from the queried class
|
||||
foreach ($class->fieldMappings as $fieldName => $mapping) {
|
||||
if ($partialFieldSet && !in_array($fieldName, $partialFieldSet)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 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 .= ', ';
|
||||
$tableName = (isset($mapping['inherited']))
|
||||
? $this->_em->getClassMetadata($mapping['inherited'])->getTableName()
|
||||
: $class->getTableName();
|
||||
|
||||
$columnAlias = $this->getSQLColumnAlias($srcColumn);
|
||||
$sql .= $sqlTableAlias . '.' . $srcColumn . ' AS ' . $columnAlias;
|
||||
if ($beginning) $beginning = false; else $sql .= ', ';
|
||||
|
||||
$this->_rsm->addMetaResult($dqlAlias, $columnAlias, $srcColumn);
|
||||
$sqlTableAlias = $this->getSQLTableAlias($tableName, $dqlAlias);
|
||||
$columnAlias = $this->getSQLColumnAlias($mapping['columnName']);
|
||||
$sql .= $sqlTableAlias . '.' . $class->getQuotedColumnName($fieldName, $this->_platform)
|
||||
. ' AS ' . $columnAlias;
|
||||
|
||||
$this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $class->name);
|
||||
}
|
||||
|
||||
// Add any additional fields of subclasses (excluding inherited fields)
|
||||
// 1) on Single Table Inheritance: always, since its marginal overhead
|
||||
// 2) on Class Table Inheritance only if partial objects are disallowed,
|
||||
// since it requires outer joining subtables.
|
||||
if ($class->isInheritanceTypeSingleTable() || ! $this->_query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) {
|
||||
foreach ($class->subClasses as $subClassName) {
|
||||
$subClass = $this->_em->getClassMetadata($subClassName);
|
||||
$sqlTableAlias = $this->getSQLTableAlias($subClass->getTableName(), $dqlAlias);
|
||||
|
||||
foreach ($subClass->fieldMappings as $fieldName => $mapping) {
|
||||
if (isset($mapping['inherited']) || $partialFieldSet && !in_array($fieldName, $partialFieldSet)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($beginning) $beginning = false; else $sql .= ', ';
|
||||
|
||||
$columnAlias = $this->getSQLColumnAlias($mapping['columnName']);
|
||||
$sql .= $sqlTableAlias . '.' . $subClass->getQuotedColumnName($fieldName, $this->_platform)
|
||||
. ' AS ' . $columnAlias;
|
||||
|
||||
$this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $subClassName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $sql;
|
||||
@ -1302,27 +1220,11 @@ class SqlWalker implements TreeWalker
|
||||
break;
|
||||
|
||||
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\ArithmeticTerm):
|
||||
case ($expr instanceof AST\ArithmeticFactor):
|
||||
case ($expr instanceof AST\ArithmeticPrimary):
|
||||
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\CoalesceExpression):
|
||||
case ($expr instanceof AST\GeneralCaseExpression):
|
||||
@ -1332,7 +1234,7 @@ class SqlWalker implements TreeWalker
|
||||
$columnAlias = $this->getSQLColumnAlias('sclr');
|
||||
$this->_scalarResultAliasMap[$alias] = $columnAlias;
|
||||
|
||||
$sql .= $this->walkCaseExpression($expr) . ' AS ' . $columnAlias;
|
||||
$sql .= $expr->dispatch($this) . ' AS ' . $columnAlias;
|
||||
break;
|
||||
|
||||
default: // IdentificationVariable
|
||||
|
@ -563,7 +563,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
$this->_em->getClassMetadata(get_class($person))->setIdentifierValues($person, array('id' => 101));
|
||||
$q3->setParameter('param', $person);
|
||||
$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()
|
||||
);
|
||||
}
|
||||
@ -1120,7 +1120,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'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)
|
||||
);
|
||||
}
|
||||
@ -1144,7 +1144,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'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)
|
||||
);
|
||||
}
|
||||
@ -1264,7 +1264,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'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)
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user