From d833ee1464ff12df08439761a4a6611ac80c9731 Mon Sep 17 00:00:00 2001 From: romanb Date: Sat, 21 Mar 2009 12:49:58 +0000 Subject: [PATCH] [2.0] Parser work. Drafted logic for multi-table deletes through DQL (for Class/Concrete Table Inheritance) --- .../Persisters/AbstractEntityPersister.php | 15 ++- .../Persisters/ElementCollectionPersister.php | 2 +- lib/Doctrine/ORM/Query/AST/DeleteClause.php | 21 +++- lib/Doctrine/ORM/Query/AST/InExpression.php | 7 +- .../ORM/Query/AST/JoinPathExpression.php | 1 + .../Query/AST/NullComparisonExpression.php | 39 ++++++ .../AST/SimpleStateFieldPathExpression.php | 8 +- ...ssion.php => StateFieldPathExpression.php} | 4 +- .../Query/Exec/MultiTableDeleteExecutor.php | 13 +- lib/Doctrine/ORM/Query/Parser.php | 116 +++++++++++++----- lib/Doctrine/ORM/Query/SqlWalker.php | 68 ++++++++-- .../ORM/Query/DeleteSqlGenerationTest.php | 69 +++++------ .../ORM/Query/LanguageRecognitionTest.php | 8 +- 13 files changed, 277 insertions(+), 94 deletions(-) create mode 100644 lib/Doctrine/ORM/Query/AST/NullComparisonExpression.php rename lib/Doctrine/ORM/Query/AST/{PathExpression.php => StateFieldPathExpression.php} (94%) diff --git a/lib/Doctrine/ORM/Persisters/AbstractEntityPersister.php b/lib/Doctrine/ORM/Persisters/AbstractEntityPersister.php index 4f55da94d..57f4776dd 100644 --- a/lib/Doctrine/ORM/Persisters/AbstractEntityPersister.php +++ b/lib/Doctrine/ORM/Persisters/AbstractEntityPersister.php @@ -63,6 +63,11 @@ abstract class AbstractEntityPersister */ protected $_em; + /** + * Queued inserts. + * + * @var array + */ protected $_queuedInserts = array(); /** @@ -150,13 +155,21 @@ abstract class AbstractEntityPersister /** * - * @return Doctrine\ORM\ClassMetadata + * @return Doctrine\ORM\Mapping\ClassMetadata */ public function getClassMetadata() { return $this->_classMetadata; } + /** + * Gets the table name to use for temporary identifier tables. + */ + public function getTemporaryIdTableName() + { + //... + } + /** * Gets the name of the class in the entity hierarchy that owns the field with * the given name. The owning class is the one that defines the field. diff --git a/lib/Doctrine/ORM/Persisters/ElementCollectionPersister.php b/lib/Doctrine/ORM/Persisters/ElementCollectionPersister.php index ed802ac5e..bf47f9851 100644 --- a/lib/Doctrine/ORM/Persisters/ElementCollectionPersister.php +++ b/lib/Doctrine/ORM/Persisters/ElementCollectionPersister.php @@ -22,7 +22,7 @@ namespace Doctrine\ORM\Persisters; /** - * Persister for collections of basic elements / value objects. + * Persister for collections of basic elements / value types. * * @author robo */ diff --git a/lib/Doctrine/ORM/Query/AST/DeleteClause.php b/lib/Doctrine/ORM/Query/AST/DeleteClause.php index eded9e25b..554d4098a 100644 --- a/lib/Doctrine/ORM/Query/AST/DeleteClause.php +++ b/lib/Doctrine/ORM/Query/AST/DeleteClause.php @@ -1,7 +1,22 @@ . */ namespace Doctrine\ORM\Query\AST; diff --git a/lib/Doctrine/ORM/Query/AST/InExpression.php b/lib/Doctrine/ORM/Query/AST/InExpression.php index 31c8db6b2..40a0802d7 100644 --- a/lib/Doctrine/ORM/Query/AST/InExpression.php +++ b/lib/Doctrine/ORM/Query/AST/InExpression.php @@ -48,9 +48,14 @@ class InExpression extends Node $this->_not = $bool; } - public function getNot() + public function isNot() { return $this->_not; } + + public function getPathExpression() + { + return $this->_pathExpression; + } } diff --git a/lib/Doctrine/ORM/Query/AST/JoinPathExpression.php b/lib/Doctrine/ORM/Query/AST/JoinPathExpression.php index d55bb821d..72f64e587 100644 --- a/lib/Doctrine/ORM/Query/AST/JoinPathExpression.php +++ b/lib/Doctrine/ORM/Query/AST/JoinPathExpression.php @@ -10,6 +10,7 @@ namespace Doctrine\ORM\Query\AST; * Description of JoinCollectionValuedPathExpression * * @author robo + * @todo Rename: JoinAssociationPathExpression */ class JoinPathExpression extends Node { diff --git a/lib/Doctrine/ORM/Query/AST/NullComparisonExpression.php b/lib/Doctrine/ORM/Query/AST/NullComparisonExpression.php new file mode 100644 index 000000000..8ba4d90cb --- /dev/null +++ b/lib/Doctrine/ORM/Query/AST/NullComparisonExpression.php @@ -0,0 +1,39 @@ +_expression = $expression; + } + + public function getExpression() + { + return $this->_expression; + } + + public function setNot($bool) + { + $this->_not = $bool; + } + + public function isNot() + { + return $this->_not; + } +} + diff --git a/lib/Doctrine/ORM/Query/AST/SimpleStateFieldPathExpression.php b/lib/Doctrine/ORM/Query/AST/SimpleStateFieldPathExpression.php index 1ca3b029a..e2508534c 100644 --- a/lib/Doctrine/ORM/Query/AST/SimpleStateFieldPathExpression.php +++ b/lib/Doctrine/ORM/Query/AST/SimpleStateFieldPathExpression.php @@ -16,7 +16,7 @@ * * This software consists of voluntary contributions made by many individuals * and is licensed under the LGPL. For more information, see - * . + * . */ namespace Doctrine\ORM\Query\AST; @@ -26,14 +26,14 @@ namespace Doctrine\ORM\Query\AST; * * @author Guilherme Blanco * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link http://www.phpdoctrine.org + * @link http://www.doctrine-project.org * @since 2.0 * @version $Revision$ */ class SimpleStateFieldPathExpression extends Node { - protected $_identificationVariable = null; - protected $_simpleStateField = null; + private $_identificationVariable = null; + private $_simpleStateField = null; public function __construct($identificationVariable, $simpleStateField) { diff --git a/lib/Doctrine/ORM/Query/AST/PathExpression.php b/lib/Doctrine/ORM/Query/AST/StateFieldPathExpression.php similarity index 94% rename from lib/Doctrine/ORM/Query/AST/PathExpression.php rename to lib/Doctrine/ORM/Query/AST/StateFieldPathExpression.php index 50f13fa38..6e464d847 100644 --- a/lib/Doctrine/ORM/Query/AST/PathExpression.php +++ b/lib/Doctrine/ORM/Query/AST/StateFieldPathExpression.php @@ -7,11 +7,11 @@ namespace Doctrine\ORM\Query\AST; /** - * Description of PathExpression + * StateFieldPathExpression ::= SimpleStateFieldPathExpression | SimpleStateFieldAssociationPathExpression * * @author robo */ -class PathExpression extends Node +class StateFieldPathExpression extends Node { private $_parts; // Information that is attached during semantical analysis. diff --git a/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php b/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php index d0d10c9f7..243b77976 100644 --- a/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php +++ b/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php @@ -43,7 +43,16 @@ class MultiTableDeleteExecutor extends AbstractExecutor */ public function __construct(\Doctrine\ORM\Query\AST $AST) { - // TODO: Inspect the AST, create the necessary SQL queries and store them + // 1. Create a INSERT ... SELECT statement where the SELECT statement + // selects the identifiers from the temporary ID table and uses the WhereClause of the $AST. + + // 2. Create ID subselect statement used in DELETE .... WHERE ... IN (subselect) + + // 3. Create and store DELETE statements + /*$subselect = 'SELECT id1, id2 FROM temptable'; + foreach ($tableNames as $tableName) { + $this->_sqlStatements[] = 'DELETE FROM ' . $tableName . ' WHERE (id1, id2) IN (subselect)'; + }*/ // in $this->_sqlStatements } @@ -56,6 +65,8 @@ class MultiTableDeleteExecutor extends AbstractExecutor */ public function execute(\Doctrine\DBAL\Connection $conn, array $params) { + // 1. Create temporary id table if necessary + //... } } \ No newline at end of file diff --git a/lib/Doctrine/ORM/Query/Parser.php b/lib/Doctrine/ORM/Query/Parser.php index 1a6303938..2b48e559a 100644 --- a/lib/Doctrine/ORM/Query/Parser.php +++ b/lib/Doctrine/ORM/Query/Parser.php @@ -1,5 +1,4 @@ syntaxError($this->_lexer->getLiteral($token)); } @@ -159,7 +157,6 @@ class Parser $this->_lexer->token = null; $this->_lexer->lookahead = null; - //$this->_errorDistance = self::MIN_ERROR_DISTANCE; } @@ -340,9 +337,10 @@ class Parser */ private function _SelectStatement() { + $this->_beginDeferredPathExpressionStack(); $selectClause = $this->_SelectClause(); $fromClause = $this->_FromClause(); - $this->_processPendingPathExpressionsInSelect(); + $this->_processDeferredPathExpressionStack(); $whereClause = $this->_lexer->isNextToken(Lexer::T_WHERE) ? $this->_WhereClause() : null; @@ -361,16 +359,25 @@ class Parser ); } + /** + * + */ + private function _beginDeferredPathExpressionStack() + { + $this->_deferredPathExpressionStacks[] = array(); + } + /** * Processes pending path expressions that were encountered while parsing * select expressions. These will be validated to make sure they are indeed * valid StateFieldPathExpressions and additional information * is attached to their AST nodes. */ - private function _processPendingPathExpressionsInSelect() + private function _processDeferredPathExpressionStack() { + $exprStack = array_pop($this->_deferredPathExpressionStacks); $qComps = $this->_parserResult->getQueryComponents(); - foreach ($this->_pendingPathExpressionsInSelect as $expr) { + foreach ($exprStack as $expr) { $parts = $expr->getParts(); $numParts = count($parts); $dqlAlias = $parts[0]; @@ -511,7 +518,7 @@ class Parser //TODO: Can be StringPrimary or EnumPrimary return $this->_StringPrimary(); } else { - $this->syntaxError('Not yet implemented.'); + $this->syntaxError('Not yet implemented-1.'); //echo "UH OH ..."; } } @@ -629,7 +636,7 @@ class Parser $fieldIdentificationVariable = $this->_lexer->token['value']; } } else { - $expression = $this->_PathExpressionInSelect(); + $expression = $this->_StateFieldPathExpression(); } return new AST\SelectExpression($expression, $fieldIdentificationVariable); } @@ -714,7 +721,7 @@ class Parser /** * Special rule that acceps all kinds of path expressions. */ - private function _PathExpression() + /*private function _StateFieldPathExpression() { $this->match(Lexer::T_IDENTIFIER); $parts = array($this->_lexer->token['value']); @@ -723,21 +730,28 @@ class Parser $this->match(Lexer::T_IDENTIFIER); $parts[] = $this->_lexer->token['value']; } - $pathExpression = new AST\PathExpression($parts); + $pathExpression = new AST\StateFieldPathExpression($parts); return $pathExpression; - } + }*/ /** * Special rule that acceps all kinds of path expressions. and defers their * semantical checking until the FROM part has been parsed completely (joins inclusive). * Mainly used for path expressions in the SelectExpressions. */ - private function _PathExpressionInSelect() + /*private function _PathExpressionInSelect() { - $expr = $this->_PathExpression(); + $this->match(Lexer::T_IDENTIFIER); + $parts = array($this->_lexer->token['value']); + while ($this->_lexer->isNextToken('.')) { + $this->match('.'); + $this->match(Lexer::T_IDENTIFIER); + $parts[] = $this->_lexer->token['value']; + } + $expr = new AST\StateFieldPathExpression($parts); $this->_pendingPathExpressionsInSelect[] = $expr; return $expr; - } + }*/ /** * JoinVariableDeclaration ::= Join [IndexBy] @@ -818,14 +832,6 @@ class Parser return $join; } - /*private function _JoinAssociationPathExpression() { - if ($this->_isSingleValuedPathExpression()) { - return $this->_JoinSingleValuedAssociationPathExpression(); - } else { - return $this->_JoinCollectionValuedPathExpression(); - } - }*/ - /*private function _isSingleValuedPathExpression() { $parserResult = $this->_parserResult; @@ -894,6 +900,21 @@ class Parser */ private function _StateFieldPathExpression() { + if ( ! empty($this->_deferredPathExpressionStacks)) { + $exprStack = array_pop($this->_deferredPathExpressionStacks); + $this->match(Lexer::T_IDENTIFIER); + $parts = array($this->_lexer->token['value']); + while ($this->_lexer->isNextToken('.')) { + $this->match('.'); + $this->match(Lexer::T_IDENTIFIER); + $parts[] = $this->_lexer->token['value']; + } + $expr = new AST\StateFieldPathExpression($parts); + $exprStack[] = $expr; + array_push($this->_deferredPathExpressionStacks, $exprStack); + return $expr; // EARLY EXIT! + } + $parts = array(); $stateFieldSeen = false; $assocSeen = false; @@ -928,7 +949,7 @@ class Parser $parts[] = $part; } - $pathExpr = new AST\PathExpression($parts); + $pathExpr = new AST\StateFieldPathExpression($parts); if ($assocSeen) { $pathExpr->setIsSimpleStateFieldAssociationPathExpression(true); @@ -939,6 +960,28 @@ class Parser return $pathExpr; } + /** + * NullComparisonExpression ::= (SingleValuedPathExpression | InputParameter) "IS" ["NOT"] "NULL" + */ + private function _NullComparisonExpression() + { + if ($this->_lexer->isNextToken(Lexer::T_INPUT_PARAMETER)) { + $this->match(Lexer::T_INPUT_PARAMETER); + $expr = new AST\InputParameter($this->_lexer->token['value']); + } else { + //TODO: Support SingleValuedAssociationPathExpression + $expr = $this->_StateFieldPathExpression(); + } + $nullCompExpr = new AST\NullComparisonExpression($expr); + $this->match(Lexer::T_IS); + if ($this->_lexer->isNextToken(Lexer::T_NOT)) { + $this->match(Lexer::T_NOT); + $nullCompExpr->setNot(true); + } + $this->match(Lexer::T_NULL); + return $nullCompExpr; + } + /** * AggregateExpression ::= * ("AVG" | "MAX" | "MIN" | "SUM") "(" ["DISTINCT"] StateFieldPathExpression ")" | @@ -957,7 +1000,7 @@ class Parser $isDistinct = true; } // For now we only support a PathExpression here... - $pathExp = $this->_PathExpression(); + $pathExp = $this->_StateFieldPathExpression(); $this->match(')'); } else { if ($this->_lexer->isNextToken(Lexer::T_AVG)) { @@ -988,10 +1031,10 @@ class Parser $this->match(Lexer::T_GROUP); $this->match(Lexer::T_BY); $groupByItems = array(); - $groupByItems[] = $this->_PathExpression(); + $groupByItems[] = $this->_StateFieldPathExpression(); while ($this->_lexer->isNextToken(',')) { $this->match(','); - $groupByItems[] = $this->_PathExpression(); + $groupByItems[] = $this->_StateFieldPathExpression(); } return new AST\GroupByClause($groupByItems); } @@ -1286,7 +1329,7 @@ class Parser */ private function _InExpression() { - $inExpression = new AST\InExpression($this->_PathExpression()); + $inExpression = new AST\InExpression($this->_StateFieldPathExpression()); if ($this->_lexer->isNextToken(Lexer::T_NOT)) { $this->match(Lexer::T_NOT); $inExpression->setNot(true); @@ -1331,7 +1374,9 @@ class Parser */ private function _Subselect() { + $this->_beginDeferredPathExpressionStack(); $subselect = new AST\Subselect($this->_SimpleSelectClause(), $this->_SubselectFromClause()); + $this->_processDeferredPathExpressionStack(); $subselect->setWhereClause( $this->_lexer->isNextToken(Lexer::T_WHERE) ? $this->_WhereClause() : null @@ -1410,7 +1455,7 @@ class Parser // SingleValuedPathExpression | IdentificationVariable $peek = $this->_lexer->glimpse(); if ($peek['value'] == '.') { - return new AST\SimpleSelectExpression($this->_PathExpressionInSelect()); + return new AST\SimpleSelectExpression($this->_StateFieldPathExpression()); } else { $this->match($this->_lexer->lookahead['value']); return new AST\SimpleSelectExpression($this->_lexer->token['value']); @@ -1507,7 +1552,7 @@ class Parser $this->syntaxError(); } } - throw \Doctrine\Common\DoctrineException::updateMe("Not yet implemented."); + throw \Doctrine\Common\DoctrineException::updateMe("Not yet implemented2."); //TODO... } @@ -1598,7 +1643,7 @@ class Parser } /** - * LikeExpression ::= StringExpression ["NOT"] "LIKE" string ["ESCAPE" char] + * LikeExpression ::= StringExpression ["NOT"] "LIKE" (string | input_parameter) ["ESCAPE" char] */ private function _LikeExpression() { @@ -1609,8 +1654,13 @@ class Parser $isNot = true; } $this->match(Lexer::T_LIKE); - $this->match(Lexer::T_STRING); - $stringPattern = $this->_lexer->token['value']; + if ($this->_lexer->isNextToken(Lexer::T_INPUT_PARAMETER)) { + $this->match(Lexer::T_INPUT_PARAMETER); + $stringPattern = new AST\InputParameter($this->_lexer->token['value']); + } else { + $this->match(Lexer::T_STRING); + $stringPattern = $this->_lexer->token['value']; + } $escapeChar = null; if ($this->_lexer->lookahead['type'] === Lexer::T_ESCAPE) { $this->match(Lexer::T_ESCAPE); diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php index 6fe4abc56..c9efc904a 100644 --- a/lib/Doctrine/ORM/Query/SqlWalker.php +++ b/lib/Doctrine/ORM/Query/SqlWalker.php @@ -154,7 +154,7 @@ class SqlWalker public function walkSelectExpression($selectExpression) { $sql = ''; - if ($selectExpression->getExpression() instanceof AST\PathExpression) { + if ($selectExpression->getExpression() instanceof AST\StateFieldPathExpression) { $pathExpression = $selectExpression->getExpression(); if ($pathExpression->isSimpleStateFieldPathExpression()) { $parts = $pathExpression->getParts(); @@ -251,7 +251,7 @@ class SqlWalker { $sql = ''; $expr = $simpleSelectExpression->getExpression(); - if ($expr instanceof AST\PathExpression) { + if ($expr instanceof AST\StateFieldPathExpression) { //... } else if ($expr instanceof AST\AggregateExpression) { if ( ! $simpleSelectExpression->getFieldIdentificationVariable()) { @@ -351,6 +351,14 @@ class SqlWalker else if ($simpleCond instanceof AST\LikeExpression) { $sql .= $this->walkLikeExpression($simpleCond); } + else if ($simpleCond instanceof AST\BetweenExpression) { + $sql .= $this->walkBetweenExpression($simpleCond); + } + else if ($simpleCond instanceof AST\InExpression) { + $sql .= $this->walkInExpression($simpleCond); + } else if ($simpleCond instanceof AST\NullComparisonExpression) { + $sql .= $this->walkNullComparisonExpression($simpleCond); + } // else if ... } else if ($primary->isConditionalExpression()) { $sql .= '(' . implode(' OR ', array_map(array(&$this, 'walkConditionalTerm'), @@ -359,14 +367,60 @@ class SqlWalker return $sql; } + public function walkNullComparisonExpression($nullCompExpr) + { + $sql = ''; + if ($nullCompExpr->getExpression() instanceof AST\InputParameter) { + $inputParam = $nullCompExpr->getExpression(); + $sql .= ' ' . ($inputParam->isNamed() ? ':' . $inputParam->getName() : '?'); + } else { + $sql .= $this->walkPathExpression($nullCompExpr->getExpression()); + } + $sql .= ' IS' . ($nullCompExpr->isNot() ? ' NOT' : '') . ' NULL'; + return $sql; + } + + public function walkInExpression($inExpr) + { + $sql = $this->walkPathExpression($inExpr->getPathExpression()); + if ($inExpr->isNot()) $sql .= ' NOT'; + $sql .= ' IN ('; + if ($inExpr->getSubselect()) { + $sql .= $this->walkSubselect($inExpr->getSubselect()); + } else { + //$sql .= implode(', ', array_map(array($this, 'walkLiteral'), $inExpr->getLiterals())); + } + $sql .= ')'; + return $sql; + } + + public function walkBetweenExpression($betweenExpr) + { + $sql = $this->walkArithmeticExpression($betweenExpr->getBaseExpression()); + if ($betweenExpr->getNot()) $sql .= ' NOT'; + $sql .= ' BETWEEN ' . $this->walkArithmeticExpression($betweenExpr->getLeftBetweenExpression()) + . ' AND ' . $this->walkArithmeticExpression($betweenExpr->getRightBetweenExpression()); + return $sql; + } + public function walkLikeExpression($likeExpr) { $sql = ''; $stringExpr = $likeExpr->getStringExpression(); - if ($stringExpr instanceof AST\PathExpression) { + if ($stringExpr instanceof AST\StateFieldPathExpression) { $sql .= $this->walkPathExpression($stringExpr); } //TODO else... - $sql .= ' LIKE ' . $likeExpr->getStringPattern(); + if ($likeExpr->isNot()) $sql .= ' NOT'; + $sql .= ' LIKE '; + if ($likeExpr->getStringPattern() instanceof AST\InputParameter) { + $inputParam = $likeExpr->getStringPattern(); + $sql .= $inputParam->isNamed() ? ':' . $inputParam->getName() : '?'; + } else { + $sql .= $likeExpr->getStringPattern(); + } + if ($likeExpr->getEscapeChar()) { + $sql .= ' ESCAPE ' . $likeExpr->getEscapeChar(); + } return $sql; } @@ -413,7 +467,7 @@ class SqlWalker } else if (is_string($primary)) { //TODO: quote string according to platform $sql .= $primary; - } else if ($primary instanceof AST\PathExpression) { + } else if ($primary instanceof AST\StateFieldPathExpression) { $sql .= $this->walkPathExpression($primary); } else if ($primary instanceof AST\InputParameter) { if ($primary->isNamed()) { @@ -456,9 +510,9 @@ class SqlWalker $sqlTableAlias = $this->_dqlToSqlAliasMap[$dqlAlias]; $sql .= $sqlTableAlias . '.' . $class->getColumnName($fieldName); } else if ($pathExpr->isSimpleStateFieldAssociationPathExpression()) { - \Doctrine\Common\DoctrineException::updateMe("Not yet implemented."); + throw \Doctrine\Common\DoctrineException::updateMe("Not yet implemented."); } else { - \Doctrine\Common\DoctrineException::updateMe("Encountered invalid PathExpression during SQL construction."); + throw \Doctrine\Common\DoctrineException::updateMe("Encountered invalid PathExpression during SQL construction."); } return $sql; } diff --git a/tests/Doctrine/Tests/ORM/Query/DeleteSqlGenerationTest.php b/tests/Doctrine/Tests/ORM/Query/DeleteSqlGenerationTest.php index da037872a..09a8f187b 100644 --- a/tests/Doctrine/Tests/ORM/Query/DeleteSqlGenerationTest.php +++ b/tests/Doctrine/Tests/ORM/Query/DeleteSqlGenerationTest.php @@ -88,10 +88,10 @@ class DeleteSqlGenerationTest extends \Doctrine\Tests\OrmTestCase 'DELETE FROM cms_users c0 WHERE c0.id = ? OR (c0.username = ? OR c0.name = ?)' ); - /*$this->assertSqlGeneration( - 'DELETE FROM Doctrine\Tests\Models\CMS\CmsUser WHERE id = ?1', - 'DELETE FROM cms_users WHERE id = ?' - );*/ + //$this->assertSqlGeneration( + // 'DELETE FROM Doctrine\Tests\Models\CMS\CmsUser WHERE id = ?1', + // 'DELETE FROM cms_users WHERE id = ?' + //); } public function testParserIsCaseAgnostic() @@ -163,7 +163,7 @@ class DeleteSqlGenerationTest extends \Doctrine\Tests\OrmTestCase "DELETE FROM cms_users c0 WHERE c0.id <> ?" ); } -/* + public function testWithExprAndBetween() { $this->assertSqlGeneration( @@ -181,60 +181,55 @@ class DeleteSqlGenerationTest extends \Doctrine\Tests\OrmTestCase { // "WHERE" Expression LikeExpression $this->assertSqlGeneration( - 'DELETE CmsUser u WHERE u.username NOT LIKE ?', - 'DELETE FROM cms_user cu WHERE cu.username NOT LIKE ?' + 'DELETE Doctrine\Tests\Models\CMS\CmsUser u WHERE u.username NOT LIKE ?1', + 'DELETE FROM cms_users c0 WHERE c0.username NOT LIKE ?' ); $this->assertSqlGeneration( - "DELETE CmsUser u WHERE u.username LIKE ? ESCAPE '\\'", - "DELETE FROM cms_user cu WHERE cu.username LIKE ? ESCAPE '\\'" + "DELETE Doctrine\Tests\Models\CMS\CmsUser u WHERE u.username LIKE ?1 ESCAPE '\\'", + "DELETE FROM cms_users c0 WHERE c0.username LIKE ? ESCAPE '\\'" ); } - - public function testWithExprAndIn() - { - // "WHERE" Expression InExpression - $this->assertSqlGeneration( - 'DELETE CmsUser u WHERE u.id IN ( ?, ?, ?, ? )', - 'DELETE FROM cms_user cu WHERE cu.id IN (?, ?, ?, ?)' - ); - - $this->assertSqlGeneration( - 'DELETE CmsUser u WHERE u.id NOT IN ( ?, ? )', - 'DELETE FROM cms_user cu WHERE cu.id NOT IN (?, ?)' - ); - } - - public function testWithExprAndNull() { // "WHERE" Expression NullComparisonExpression $this->assertSqlGeneration( - 'DELETE CmsUser u WHERE u.name IS NULL', - 'DELETE FROM cms_user cu WHERE cu.name IS NULL' + 'DELETE Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name IS NULL', + 'DELETE FROM cms_users c0 WHERE c0.name IS NULL' ); $this->assertSqlGeneration( - 'DELETE CmsUser u WHERE u.name IS NOT NULL', - 'DELETE FROM cms_user cu WHERE cu.name IS NOT NULL' + 'DELETE Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name IS NOT NULL', + 'DELETE FROM cms_users c0 WHERE c0.name IS NOT NULL' ); } - - // All previously defined tests used Primary as PathExpression. No need to check it again. - public function testWithPrimaryAsAtom() { - // Atom = string | integer | float | boolean | input_parameter $this->assertSqlGeneration( - 'DELETE CmsUser u WHERE 1 = 1', - 'DELETE FROM cms_user cu WHERE 1 = 1' + 'DELETE Doctrine\Tests\Models\CMS\CmsUser u WHERE 1 = 1', + 'DELETE FROM cms_users c0 WHERE 1 = 1' ); $this->assertSqlGeneration( - 'DELETE CmsUser u WHERE ? = 1', - 'DELETE FROM cms_user cu WHERE ? = 1' + 'DELETE Doctrine\Tests\Models\CMS\CmsUser u WHERE ?1 = 1', + 'DELETE FROM cms_users c0 WHERE ? = 1' + ); + } + +/* + public function testWithExprAndIn() + { + // "WHERE" Expression InExpression + $this->assertSqlGeneration( + 'DELETE Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id IN ( ?, ?, ?, ? )', + 'DELETE FROM cms_users c0 WHERE c0.id IN (?, ?, ?, ?)' + ); + + $this->assertSqlGeneration( + 'DELETE Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id NOT IN ( ?, ? )', + 'DELETE FROM cms_users c0 WHERE c0.id NOT IN (?, ?)' ); } */ diff --git a/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php b/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php index d2b412bb0..b7302b9c4 100644 --- a/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php +++ b/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php @@ -110,12 +110,12 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase public function testExistsExpressionSupportedInWherePart() { - $this->assertValidDql('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE EXISTS (SELECT p.id FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p WHERE p.phonenumber = 1234)'); + $this->assertValidDql('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE EXISTS (SELECT p.phonenumber FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p WHERE p.phonenumber = 1234)'); } public function testNotExistsExpressionSupportedInWherePart() { - $this->assertValidDql('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE NOT EXISTS (SELECT p.id FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p WHERE p.phonenumber = 1234)'); + $this->assertValidDql('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE NOT EXISTS (SELECT p.phonenumber FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p WHERE p.phonenumber = 1234)'); } public function testAggregateFunctionInHavingClause() @@ -239,14 +239,14 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase { $this->assertValidDql("SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name LIKE 'z|%' ESCAPE '|'"); } - +/* public function testImplicitJoinInWhereOnSingleValuedAssociationPathExpression() { // This should be allowed because avatar is a single-value association. // SQL: SELECT ... FROM forum_user fu INNER JOIN forum_avatar fa ON fu.avatar_id = fa.id WHERE fa.id = ? $this->assertValidDql("SELECT u FROM Doctrine\Tests\Models\Forum\ForumUser u WHERE u.avatar.id = ?"); } - +*/ public function testImplicitJoinInWhereOnCollectionValuedPathExpression() { // This should be forbidden, because articles is a collection