1
0
mirror of synced 2025-01-31 12:32:59 +03:00

Made SimpleSelectExpression (Literal) be included as a scalar result. More general SQL Walker optimizations.

This commit is contained in:
Guilherme Blanco 2011-10-28 14:25:12 -02:00
parent 1f06e9fca5
commit 3745e948c6
2 changed files with 114 additions and 126 deletions

View File

@ -157,33 +157,25 @@ class SqlWalker implements TreeWalker
*/ */
public function getExecutor($AST) public function getExecutor($AST)
{ {
$isDeleteStatement = $AST instanceof AST\DeleteStatement; switch (true) {
$isUpdateStatement = $AST instanceof AST\UpdateStatement; case ($AST instanceof AST\DeleteStatement):
$primaryClass = $this->_em->getClassMetadata($AST->deleteClause->abstractSchemaName);
if ($isDeleteStatement) { return ($primaryClass->isInheritanceTypeJoined())
$primaryClass = $this->_em->getClassMetadata( ? new Exec\MultiTableDeleteExecutor($AST, $this)
$AST->deleteClause->abstractSchemaName : new Exec\SingleTableDeleteUpdateExecutor($AST, $this);
);
if ($primaryClass->isInheritanceTypeJoined()) { case ($AST instanceof AST\UpdateStatement):
return new Exec\MultiTableDeleteExecutor($AST, $this); $primaryClass = $this->_em->getClassMetadata($AST->updateClause->abstractSchemaName);
} else {
return new Exec\SingleTableDeleteUpdateExecutor($AST, $this);
}
} else if ($isUpdateStatement) {
$primaryClass = $this->_em->getClassMetadata(
$AST->updateClause->abstractSchemaName
);
if ($primaryClass->isInheritanceTypeJoined()) { return ($primaryClass->isInheritanceTypeJoined())
return new Exec\MultiTableUpdateExecutor($AST, $this); ? new Exec\MultiTableUpdateExecutor($AST, $this)
} else { : new Exec\SingleTableDeleteUpdateExecutor($AST, $this);
return new Exec\SingleTableDeleteUpdateExecutor($AST, $this);
}
}
default:
return new Exec\SingleSelectExecutor($AST, $this); return new Exec\SingleSelectExecutor($AST, $this);
} }
}
/** /**
* Generates a unique, short SQL table alias. * Generates a unique, short SQL table alias.
@ -1324,14 +1316,11 @@ class SqlWalker implements TreeWalker
$sql .= $this->walkFunction($expr) . ' AS ' . $columnAlias; $sql .= $this->walkFunction($expr) . ' AS ' . $columnAlias;
break; break;
case ($expr instanceof AST\Literal):
$sql .= $this->walkLiteral($expr);
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):
$alias = $simpleSelectExpression->fieldIdentificationVariable ?: $this->_scalarResultCounter++; $alias = $simpleSelectExpression->fieldIdentificationVariable ?: $this->_scalarResultCounter++;
$columnAlias = 'sclr' . $this->_aliasCounter++; $columnAlias = 'sclr' . $this->_aliasCounter++;
@ -1388,25 +1377,24 @@ class SqlWalker implements TreeWalker
*/ */
public function walkGroupByClause($groupByClause) public function walkGroupByClause($groupByClause)
{ {
$sql = ''; $sqlParts = array();
foreach ($groupByClause->groupByItems AS $groupByItem) { foreach ($groupByClause->groupByItems AS $groupByItem) {
if (is_string($groupByItem)) { if ( ! is_string($groupByItem)) {
foreach ($this->_queryComponents[$groupByItem]['metadata']->identifier AS $idField) { $sqlParts[] = $this->walkGroupByItem($groupByItem);
if ($sql != '') {
$sql .= ', '; continue;
} }
foreach ($this->_queryComponents[$groupByItem]['metadata']->identifier AS $idField) {
$groupByItem = new AST\PathExpression(AST\PathExpression::TYPE_STATE_FIELD, $groupByItem, $idField); $groupByItem = new AST\PathExpression(AST\PathExpression::TYPE_STATE_FIELD, $groupByItem, $idField);
$groupByItem->type = AST\PathExpression::TYPE_STATE_FIELD; $groupByItem->type = AST\PathExpression::TYPE_STATE_FIELD;
$sql .= $this->walkGroupByItem($groupByItem);
} $sqlParts[] = $this->walkGroupByItem($groupByItem);
} else {
if ($sql != '') {
$sql .= ', ';
}
$sql .= $this->walkGroupByItem($groupByItem);
} }
} }
return ' GROUP BY ' . $sql;
return ' GROUP BY ' . implode(', ', $sqlParts);
} }
/** /**
@ -1428,12 +1416,11 @@ class SqlWalker implements TreeWalker
*/ */
public function walkDeleteClause(AST\DeleteClause $deleteClause) public function walkDeleteClause(AST\DeleteClause $deleteClause)
{ {
$sql = 'DELETE FROM ';
$class = $this->_em->getClassMetadata($deleteClause->abstractSchemaName); $class = $this->_em->getClassMetadata($deleteClause->abstractSchemaName);
$sql .= $class->getQuotedTableName($this->_platform); $tableName = $class->getTableName();
$sql = 'DELETE FROM ' . $class->getQuotedTableName($this->_platform);
$this->setSQLTableAlias($class->getTableName(), $class->getTableName(), $deleteClause->aliasIdentificationVariable);
$this->setSQLTableAlias($tableName, $tableName, $deleteClause->aliasIdentificationVariable);
$this->_rootAliases[] = $deleteClause->aliasIdentificationVariable; $this->_rootAliases[] = $deleteClause->aliasIdentificationVariable;
return $sql; return $sql;
@ -1447,17 +1434,14 @@ class SqlWalker implements TreeWalker
*/ */
public function walkUpdateClause($updateClause) public function walkUpdateClause($updateClause)
{ {
$sql = 'UPDATE ';
$class = $this->_em->getClassMetadata($updateClause->abstractSchemaName); $class = $this->_em->getClassMetadata($updateClause->abstractSchemaName);
$sql .= $class->getQuotedTableName($this->_platform); $tableName = $class->getTableName();
$sql = 'UPDATE ' . $class->getQuotedTableName($this->_platform);
$this->setSQLTableAlias($class->getTableName(), $class->getTableName(), $updateClause->aliasIdentificationVariable);
$this->setSQLTableAlias($tableName, $tableName, $updateClause->aliasIdentificationVariable);
$this->_rootAliases[] = $updateClause->aliasIdentificationVariable; $this->_rootAliases[] = $updateClause->aliasIdentificationVariable;
$sql .= ' SET ' . implode( $sql .= ' SET ' . implode(', ', array_map(array($this, 'walkUpdateItem'), $updateClause->updateItems));
', ', array_map(array($this, 'walkUpdateItem'), $updateClause->updateItems)
);
return $sql; return $sql;
} }
@ -1474,15 +1458,20 @@ class SqlWalker implements TreeWalker
$this->_useSqlTableAliases = false; $this->_useSqlTableAliases = false;
$sql = $this->walkPathExpression($updateItem->pathExpression) . ' = '; $sql = $this->walkPathExpression($updateItem->pathExpression) . ' = ';
$newValue = $updateItem->newValue; $newValue = $updateItem->newValue;
if ($newValue === null) { switch (true) {
$sql .= 'NULL'; case ($newValue instanceof AST\Node):
} else if ($newValue instanceof AST\Node) {
$sql .= $newValue->dispatch($this); $sql .= $newValue->dispatch($this);
} else { break;
case ($newValue === null):
$sql .= 'NULL';
break;
default:
$sql .= $this->_conn->quote($newValue); $sql .= $this->_conn->quote($newValue);
break;
} }
$this->_useSqlTableAliases = $useTableAliasesBefore; $this->_useSqlTableAliases = $useTableAliasesBefore;
@ -1504,7 +1493,9 @@ class SqlWalker implements TreeWalker
if ($condSql) { if ($condSql) {
return ' WHERE ' . (( ! $discrSql) ? $condSql : '(' . $condSql . ') AND ' . $discrSql); return ' WHERE ' . (( ! $discrSql) ? $condSql : '(' . $condSql . ') AND ' . $discrSql);
} else if ($discrSql) { }
if ($discrSql) {
return ' WHERE ' . $discrSql; return ' WHERE ' . $discrSql;
} }
@ -1521,11 +1512,11 @@ class SqlWalker implements TreeWalker
{ {
// Phase 2 AST optimization: Skip processment of ConditionalExpression // Phase 2 AST optimization: Skip processment of ConditionalExpression
// if only one ConditionalTerm is defined // if only one ConditionalTerm is defined
return ( ! ($condExpr instanceof AST\ConditionalExpression)) if ( ! ($condExpr instanceof AST\ConditionalExpression)) {
? $this->walkConditionalTerm($condExpr) return $this->walkConditionalTerm($condExpr);
: implode( }
' OR ', array_map(array($this, 'walkConditionalTerm'), $condExpr->conditionalTerms)
); return implode(' OR ', array_map(array($this, 'walkConditionalTerm'), $condExpr->conditionalTerms));
} }
/** /**
@ -1538,11 +1529,11 @@ class SqlWalker implements TreeWalker
{ {
// Phase 2 AST optimization: Skip processment of ConditionalTerm // Phase 2 AST optimization: Skip processment of ConditionalTerm
// if only one ConditionalFactor is defined // if only one ConditionalFactor is defined
return ( ! ($condTerm instanceof AST\ConditionalTerm)) if ( ! ($condTerm instanceof AST\ConditionalTerm)) {
? $this->walkConditionalFactor($condTerm) return $this->walkConditionalFactor($condTerm);
: implode( }
' AND ', array_map(array($this, 'walkConditionalFactor'), $condTerm->conditionalFactors)
); return implode(' AND ', array_map(array($this, 'walkConditionalFactor'), $condTerm->conditionalFactors));
} }
/** /**
@ -1570,7 +1561,9 @@ class SqlWalker implements TreeWalker
{ {
if ($primary->isSimpleConditionalExpression()) { if ($primary->isSimpleConditionalExpression()) {
return $primary->simpleConditionalExpression->dispatch($this); return $primary->simpleConditionalExpression->dispatch($this);
} else if ($primary->isConditionalExpression()) { }
if ($primary->isConditionalExpression()) {
$condExpr = $primary->conditionalExpression; $condExpr = $primary->conditionalExpression;
return '(' . $this->walkConditionalExpression($condExpr) . ')'; return '(' . $this->walkConditionalExpression($condExpr) . ')';
@ -1752,11 +1745,9 @@ class SqlWalker implements TreeWalker
$sql = $this->walkPathExpression($inExpr->pathExpression) $sql = $this->walkPathExpression($inExpr->pathExpression)
. ($inExpr->not ? ' NOT' : '') . ' IN ('; . ($inExpr->not ? ' NOT' : '') . ' IN (';
if ($inExpr->subselect) { $sql .= ($inExpr->subselect)
$sql .= $this->walkSubselect($inExpr->subselect); ? $this->walkSubselect($inExpr->subselect)
} else { : implode(', ', array_map(array($this, 'walkInParameter'), $inExpr->literals));
$sql .= implode(', ', array_map(array($this, 'walkInParameter'), $inExpr->literals));
}
$sql .= ')'; $sql .= ')';
@ -1831,9 +1822,9 @@ class SqlWalker implements TreeWalker
*/ */
public function walkInParameter($inParam) public function walkInParameter($inParam)
{ {
return $inParam instanceof AST\InputParameter ? return $inParam instanceof AST\InputParameter
$this->walkInputParameter($inParam) : ? $this->walkInputParameter($inParam)
$this->walkLiteral($inParam); : $this->walkLiteral($inParam);
} }
/** /**
@ -1926,23 +1917,19 @@ class SqlWalker implements TreeWalker
*/ */
public function walkComparisonExpression($compExpr) public function walkComparisonExpression($compExpr)
{ {
$sql = '';
$leftExpr = $compExpr->leftExpression; $leftExpr = $compExpr->leftExpression;
$rightExpr = $compExpr->rightExpression; $rightExpr = $compExpr->rightExpression;
$sql = '';
if ($leftExpr instanceof AST\Node) { $sql .= ($leftExpr instanceof AST\Node)
$sql .= $leftExpr->dispatch($this); ? $leftExpr->dispatch($this)
} else { : (is_numeric($leftExpr) ? $leftExpr : $this->_conn->quote($leftExpr));
$sql .= is_numeric($leftExpr) ? $leftExpr : $this->_conn->quote($leftExpr);
}
$sql .= ' ' . $compExpr->operator . ' '; $sql .= ' ' . $compExpr->operator . ' ';
if ($rightExpr instanceof AST\Node) { $sql .= ($rightExpr instanceof AST\Node)
$sql .= $rightExpr->dispatch($this); ? $rightExpr->dispatch($this)
} else { : (is_numeric($rightExpr) ? $rightExpr : $this->_conn->quote($rightExpr));
$sql .= is_numeric($rightExpr) ? $rightExpr : $this->_conn->quote($rightExpr);
}
return $sql; return $sql;
} }
@ -1981,11 +1968,11 @@ class SqlWalker implements TreeWalker
*/ */
public function walkSimpleArithmeticExpression($simpleArithmeticExpr) public function walkSimpleArithmeticExpression($simpleArithmeticExpr)
{ {
return ( ! ($simpleArithmeticExpr instanceof AST\SimpleArithmeticExpression)) if ( ! ($simpleArithmeticExpr instanceof AST\SimpleArithmeticExpression)) {
? $this->walkArithmeticTerm($simpleArithmeticExpr) return $this->walkArithmeticTerm($simpleArithmeticExpr);
: implode( }
' ', array_map(array($this, 'walkArithmeticTerm'), $simpleArithmeticExpr->arithmeticTerms)
); return implode(' ', array_map(array($this, 'walkArithmeticTerm'), $simpleArithmeticExpr->arithmeticTerms));
} }
/** /**
@ -1997,22 +1984,18 @@ class SqlWalker implements TreeWalker
public function walkArithmeticTerm($term) public function walkArithmeticTerm($term)
{ {
if (is_string($term)) { if (is_string($term)) {
if (isset($this->_queryComponents[$term])) { return (isset($this->_queryComponents[$term]))
$columnName = $this->_queryComponents[$term]['token']['value']; ? $this->_scalarResultAliasMap[$this->_queryComponents[$term]['token']['value']]
: $term;
return $this->_scalarResultAliasMap[$columnName];
}
return $term;
} }
// Phase 2 AST optimization: Skip processment of ArithmeticTerm // Phase 2 AST optimization: Skip processment of ArithmeticTerm
// if only one ArithmeticFactor is defined // if only one ArithmeticFactor is defined
return ( ! ($term instanceof AST\ArithmeticTerm)) if ( ! ($term instanceof AST\ArithmeticTerm)) {
? $this->walkArithmeticFactor($term) return $this->walkArithmeticFactor($term);
: implode( }
' ', array_map(array($this, 'walkArithmeticFactor'), $term->arithmeticFactors)
); return implode(' ', array_map(array($this, 'walkArithmeticFactor'), $term->arithmeticFactors));
} }
/** /**
@ -2029,10 +2012,13 @@ class SqlWalker implements TreeWalker
// Phase 2 AST optimization: Skip processment of ArithmeticFactor // Phase 2 AST optimization: Skip processment of ArithmeticFactor
// if only one ArithmeticPrimary is defined // if only one ArithmeticPrimary is defined
return ( ! ($factor instanceof AST\ArithmeticFactor)) if ( ! ($factor instanceof AST\ArithmeticFactor)) {
? $this->walkArithmeticPrimary($factor) return $this->walkArithmeticPrimary($factor);
: ($factor->isNegativeSigned() ? '-' : ($factor->isPositiveSigned() ? '+' : '')) }
. $this->walkArithmeticPrimary($factor->arithmeticPrimary);
$sign = $factor->isNegativeSigned() ? '-' : ($factor->isPositiveSigned() ? '+' : '');
return $sign . $this->walkArithmeticPrimary($factor->arithmeticPrimary);
} }
/** /**
@ -2045,7 +2031,9 @@ class SqlWalker implements TreeWalker
{ {
if ($primary instanceof AST\SimpleArithmeticExpression) { if ($primary instanceof AST\SimpleArithmeticExpression) {
return '(' . $this->walkSimpleArithmeticExpression($primary) . ')'; return '(' . $this->walkSimpleArithmeticExpression($primary) . ')';
} else if ($primary instanceof AST\Node) { }
if ($primary instanceof AST\Node) {
return $primary->dispatch($this); return $primary->dispatch($this);
} }

View File

@ -620,7 +620,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
// SQL // SQL
'SELECT DISTINCT c0_.id AS id0, c0_.name AS name1 FROM cms_employees c0_' 'SELECT DISTINCT c0_.id AS id0, c0_.name AS name1 FROM cms_employees c0_'
. ' WHERE EXISTS (' . ' WHERE EXISTS ('
. 'SELECT 1 FROM cms_employees c1_ WHERE c1_.id = c0_.spouse_id' . 'SELECT 1 AS sclr2 FROM cms_employees c1_ WHERE c1_.id = c0_.spouse_id'
. ')' . ')'
); );
} }