Skip to content

Commit

Permalink
Made SimpleSelectExpression (Literal) be included as a scalar result.…
Browse files Browse the repository at this point in the history
… More general SQL Walker optimizations.
  • Loading branch information
guilhermeblanco committed Oct 28, 2011
1 parent 1f06e9f commit 3745e94
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 126 deletions.
238 changes: 113 additions & 125 deletions lib/Doctrine/ORM/Query/SqlWalker.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,32 +157,24 @@ public function getQueryComponent($dqlAlias)
*/
public function getExecutor($AST)
{
$isDeleteStatement = $AST instanceof AST\DeleteStatement;
$isUpdateStatement = $AST instanceof AST\UpdateStatement;

if ($isDeleteStatement) {
$primaryClass = $this->_em->getClassMetadata(
$AST->deleteClause->abstractSchemaName
);

if ($primaryClass->isInheritanceTypeJoined()) {
return new Exec\MultiTableDeleteExecutor($AST, $this);
} else {
return new Exec\SingleTableDeleteUpdateExecutor($AST, $this);
}
} else if ($isUpdateStatement) {
$primaryClass = $this->_em->getClassMetadata(
$AST->updateClause->abstractSchemaName
);

if ($primaryClass->isInheritanceTypeJoined()) {
return new Exec\MultiTableUpdateExecutor($AST, $this);
} else {
return new Exec\SingleTableDeleteUpdateExecutor($AST, $this);
}
switch (true) {
case ($AST instanceof AST\DeleteStatement):
$primaryClass = $this->_em->getClassMetadata($AST->deleteClause->abstractSchemaName);

return ($primaryClass->isInheritanceTypeJoined())
? new Exec\MultiTableDeleteExecutor($AST, $this)
: new Exec\SingleTableDeleteUpdateExecutor($AST, $this);

case ($AST instanceof AST\UpdateStatement):
$primaryClass = $this->_em->getClassMetadata($AST->updateClause->abstractSchemaName);

return ($primaryClass->isInheritanceTypeJoined())
? new Exec\MultiTableUpdateExecutor($AST, $this)
: new Exec\SingleTableDeleteUpdateExecutor($AST, $this);

default:
return new Exec\SingleSelectExecutor($AST, $this);
}

return new Exec\SingleSelectExecutor($AST, $this);
}

/**
Expand Down Expand Up @@ -1324,14 +1316,11 @@ public function walkSimpleSelectExpression($simpleSelectExpression)
$sql .= $this->walkFunction($expr) . ' AS ' . $columnAlias;
break;

case ($expr instanceof AST\Literal):
$sql .= $this->walkLiteral($expr);
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 = 'sclr' . $this->_aliasCounter++;
Expand Down Expand Up @@ -1388,25 +1377,24 @@ public function walkAggregateExpression($aggExpression)
*/
public function walkGroupByClause($groupByClause)
{
$sql = '';
$sqlParts = array();

foreach ($groupByClause->groupByItems AS $groupByItem) {
if (is_string($groupByItem)) {
foreach ($this->_queryComponents[$groupByItem]['metadata']->identifier AS $idField) {
if ($sql != '') {
$sql .= ', ';
}
$groupByItem = new AST\PathExpression(AST\PathExpression::TYPE_STATE_FIELD, $groupByItem, $idField);
$groupByItem->type = AST\PathExpression::TYPE_STATE_FIELD;
$sql .= $this->walkGroupByItem($groupByItem);
}
} else {
if ($sql != '') {
$sql .= ', ';
}
$sql .= $this->walkGroupByItem($groupByItem);
if ( ! is_string($groupByItem)) {
$sqlParts[] = $this->walkGroupByItem($groupByItem);

continue;
}

foreach ($this->_queryComponents[$groupByItem]['metadata']->identifier AS $idField) {
$groupByItem = new AST\PathExpression(AST\PathExpression::TYPE_STATE_FIELD, $groupByItem, $idField);
$groupByItem->type = AST\PathExpression::TYPE_STATE_FIELD;

$sqlParts[] = $this->walkGroupByItem($groupByItem);
}
}
return ' GROUP BY ' . $sql;

return ' GROUP BY ' . implode(', ', $sqlParts);
}

/**
Expand All @@ -1428,12 +1416,11 @@ public function walkGroupByItem(AST\PathExpression $pathExpr)
*/
public function walkDeleteClause(AST\DeleteClause $deleteClause)
{
$sql = 'DELETE FROM ';
$class = $this->_em->getClassMetadata($deleteClause->abstractSchemaName);
$sql .= $class->getQuotedTableName($this->_platform);

$this->setSQLTableAlias($class->getTableName(), $class->getTableName(), $deleteClause->aliasIdentificationVariable);

$class = $this->_em->getClassMetadata($deleteClause->abstractSchemaName);
$tableName = $class->getTableName();
$sql = 'DELETE FROM ' . $class->getQuotedTableName($this->_platform);

$this->setSQLTableAlias($tableName, $tableName, $deleteClause->aliasIdentificationVariable);
$this->_rootAliases[] = $deleteClause->aliasIdentificationVariable;

return $sql;
Expand All @@ -1447,17 +1434,14 @@ public function walkDeleteClause(AST\DeleteClause $deleteClause)
*/
public function walkUpdateClause($updateClause)
{
$sql = 'UPDATE ';
$class = $this->_em->getClassMetadata($updateClause->abstractSchemaName);
$sql .= $class->getQuotedTableName($this->_platform);

$this->setSQLTableAlias($class->getTableName(), $class->getTableName(), $updateClause->aliasIdentificationVariable);

$class = $this->_em->getClassMetadata($updateClause->abstractSchemaName);
$tableName = $class->getTableName();
$sql = 'UPDATE ' . $class->getQuotedTableName($this->_platform);

$this->setSQLTableAlias($tableName, $tableName, $updateClause->aliasIdentificationVariable);
$this->_rootAliases[] = $updateClause->aliasIdentificationVariable;

$sql .= ' SET ' . implode(
', ', array_map(array($this, 'walkUpdateItem'), $updateClause->updateItems)
);
$sql .= ' SET ' . implode(', ', array_map(array($this, 'walkUpdateItem'), $updateClause->updateItems));

return $sql;
}
Expand All @@ -1473,16 +1457,21 @@ public function walkUpdateItem($updateItem)
$useTableAliasesBefore = $this->_useSqlTableAliases;
$this->_useSqlTableAliases = false;

$sql = $this->walkPathExpression($updateItem->pathExpression) . ' = ';

$sql = $this->walkPathExpression($updateItem->pathExpression) . ' = ';
$newValue = $updateItem->newValue;

if ($newValue === null) {
$sql .= 'NULL';
} else if ($newValue instanceof AST\Node) {
$sql .= $newValue->dispatch($this);
} else {
$sql .= $this->_conn->quote($newValue);
switch (true) {
case ($newValue instanceof AST\Node):
$sql .= $newValue->dispatch($this);
break;

case ($newValue === null):
$sql .= 'NULL';
break;

default:
$sql .= $this->_conn->quote($newValue);
break;
}

$this->_useSqlTableAliases = $useTableAliasesBefore;
Expand All @@ -1499,12 +1488,14 @@ public function walkUpdateItem($updateItem)
*/
public function walkWhereClause($whereClause)
{
$condSql = null !== $whereClause ? $this->walkConditionalExpression($whereClause->conditionalExpression) : '';
$condSql = null !== $whereClause ? $this->walkConditionalExpression($whereClause->conditionalExpression) : '';
$discrSql = $this->_generateDiscriminatorColumnConditionSql($this->_rootAliases);

if ($condSql) {
return ' WHERE ' . (( ! $discrSql) ? $condSql : '(' . $condSql . ') AND ' . $discrSql);
} else if ($discrSql) {
}

if ($discrSql) {
return ' WHERE ' . $discrSql;
}

Expand All @@ -1521,11 +1512,11 @@ public function walkConditionalExpression($condExpr)
{
// Phase 2 AST optimization: Skip processment of ConditionalExpression
// if only one ConditionalTerm is defined
return ( ! ($condExpr instanceof AST\ConditionalExpression))
? $this->walkConditionalTerm($condExpr)
: implode(
' OR ', array_map(array($this, 'walkConditionalTerm'), $condExpr->conditionalTerms)
);
if ( ! ($condExpr instanceof AST\ConditionalExpression)) {
return $this->walkConditionalTerm($condExpr);
}

return implode(' OR ', array_map(array($this, 'walkConditionalTerm'), $condExpr->conditionalTerms));
}

/**
Expand All @@ -1538,11 +1529,11 @@ public function walkConditionalTerm($condTerm)
{
// Phase 2 AST optimization: Skip processment of ConditionalTerm
// if only one ConditionalFactor is defined
return ( ! ($condTerm instanceof AST\ConditionalTerm))
? $this->walkConditionalFactor($condTerm)
: implode(
' AND ', array_map(array($this, 'walkConditionalFactor'), $condTerm->conditionalFactors)
);
if ( ! ($condTerm instanceof AST\ConditionalTerm)) {
return $this->walkConditionalFactor($condTerm);
}

return implode(' AND ', array_map(array($this, 'walkConditionalFactor'), $condTerm->conditionalFactors));
}

/**
Expand Down Expand Up @@ -1570,7 +1561,9 @@ public function walkConditionalPrimary($primary)
{
if ($primary->isSimpleConditionalExpression()) {
return $primary->simpleConditionalExpression->dispatch($this);
} else if ($primary->isConditionalExpression()) {
}

if ($primary->isConditionalExpression()) {
$condExpr = $primary->conditionalExpression;

return '(' . $this->walkConditionalExpression($condExpr) . ')';
Expand Down Expand Up @@ -1749,14 +1742,12 @@ public function walkNullComparisonExpression($nullCompExpr)
*/
public function walkInExpression($inExpr)
{
$sql = $this->walkPathExpression($inExpr->pathExpression)
$sql = $this->walkPathExpression($inExpr->pathExpression)
. ($inExpr->not ? ' NOT' : '') . ' IN (';

if ($inExpr->subselect) {
$sql .= $this->walkSubselect($inExpr->subselect);
} else {
$sql .= implode(', ', array_map(array($this, 'walkInParameter'), $inExpr->literals));
}
$sql .= ($inExpr->subselect)
? $this->walkSubselect($inExpr->subselect)
: implode(', ', array_map(array($this, 'walkInParameter'), $inExpr->literals));

$sql .= ')';

Expand Down Expand Up @@ -1831,9 +1822,9 @@ public function walkInstanceOfExpression($instanceOfExpr)
*/
public function walkInParameter($inParam)
{
return $inParam instanceof AST\InputParameter ?
$this->walkInputParameter($inParam) :
$this->walkLiteral($inParam);
return $inParam instanceof AST\InputParameter
? $this->walkInputParameter($inParam)
: $this->walkLiteral($inParam);
}

/**
Expand Down Expand Up @@ -1926,23 +1917,19 @@ public function walkStateFieldPathExpression($stateFieldPathExpression)
*/
public function walkComparisonExpression($compExpr)
{
$sql = '';
$leftExpr = $compExpr->leftExpression;
$leftExpr = $compExpr->leftExpression;
$rightExpr = $compExpr->rightExpression;

if ($leftExpr instanceof AST\Node) {
$sql .= $leftExpr->dispatch($this);
} else {
$sql .= is_numeric($leftExpr) ? $leftExpr : $this->_conn->quote($leftExpr);
}
$sql = '';

$sql .= ($leftExpr instanceof AST\Node)
? $leftExpr->dispatch($this)
: (is_numeric($leftExpr) ? $leftExpr : $this->_conn->quote($leftExpr));

$sql .= ' ' . $compExpr->operator . ' ';

if ($rightExpr instanceof AST\Node) {
$sql .= $rightExpr->dispatch($this);
} else {
$sql .= is_numeric($rightExpr) ? $rightExpr : $this->_conn->quote($rightExpr);
}
$sql .= ($rightExpr instanceof AST\Node)
? $rightExpr->dispatch($this)
: (is_numeric($rightExpr) ? $rightExpr : $this->_conn->quote($rightExpr));

return $sql;
}
Expand Down Expand Up @@ -1981,11 +1968,11 @@ public function walkArithmeticExpression($arithmeticExpr)
*/
public function walkSimpleArithmeticExpression($simpleArithmeticExpr)
{
return ( ! ($simpleArithmeticExpr instanceof AST\SimpleArithmeticExpression))
? $this->walkArithmeticTerm($simpleArithmeticExpr)
: implode(
' ', array_map(array($this, 'walkArithmeticTerm'), $simpleArithmeticExpr->arithmeticTerms)
);
if ( ! ($simpleArithmeticExpr instanceof AST\SimpleArithmeticExpression)) {
return $this->walkArithmeticTerm($simpleArithmeticExpr);
}

return implode(' ', array_map(array($this, 'walkArithmeticTerm'), $simpleArithmeticExpr->arithmeticTerms));
}

/**
Expand All @@ -1997,22 +1984,18 @@ public function walkSimpleArithmeticExpression($simpleArithmeticExpr)
public function walkArithmeticTerm($term)
{
if (is_string($term)) {
if (isset($this->_queryComponents[$term])) {
$columnName = $this->_queryComponents[$term]['token']['value'];

return $this->_scalarResultAliasMap[$columnName];
}

return $term;
return (isset($this->_queryComponents[$term]))
? $this->_scalarResultAliasMap[$this->_queryComponents[$term]['token']['value']]
: $term;
}

// Phase 2 AST optimization: Skip processment of ArithmeticTerm
// if only one ArithmeticFactor is defined
return ( ! ($term instanceof AST\ArithmeticTerm))
? $this->walkArithmeticFactor($term)
: implode(
' ', array_map(array($this, 'walkArithmeticFactor'), $term->arithmeticFactors)
);
if ( ! ($term instanceof AST\ArithmeticTerm)) {
return $this->walkArithmeticFactor($term);
}

return implode(' ', array_map(array($this, 'walkArithmeticFactor'), $term->arithmeticFactors));
}

/**
Expand All @@ -2029,10 +2012,13 @@ public function walkArithmeticFactor($factor)

// Phase 2 AST optimization: Skip processment of ArithmeticFactor
// if only one ArithmeticPrimary is defined
return ( ! ($factor instanceof AST\ArithmeticFactor))
? $this->walkArithmeticPrimary($factor)
: ($factor->isNegativeSigned() ? '-' : ($factor->isPositiveSigned() ? '+' : ''))
. $this->walkArithmeticPrimary($factor->arithmeticPrimary);
if ( ! ($factor instanceof AST\ArithmeticFactor)) {
return $this->walkArithmeticPrimary($factor);
}

$sign = $factor->isNegativeSigned() ? '-' : ($factor->isPositiveSigned() ? '+' : '');

return $sign . $this->walkArithmeticPrimary($factor->arithmeticPrimary);
}

/**
Expand All @@ -2045,7 +2031,9 @@ public function walkArithmeticPrimary($primary)
{
if ($primary instanceof AST\SimpleArithmeticExpression) {
return '(' . $this->walkSimpleArithmeticExpression($primary) . ')';
} else if ($primary instanceof AST\Node) {
}

if ($primary instanceof AST\Node) {
return $primary->dispatch($this);
}

Expand Down
2 changes: 1 addition & 1 deletion tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,7 @@ public function testExistsExpressionWithSimpleSelectReturningScalar()
// SQL
'SELECT DISTINCT c0_.id AS id0, c0_.name AS name1 FROM cms_employees c0_'
. ' 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'
. ')'
);
}
Expand Down

0 comments on commit 3745e94

Please sign in to comment.