diff --git a/lib/Doctrine/Query.php b/lib/Doctrine/Query.php index a5cbaf41f..32f0d18f3 100644 --- a/lib/Doctrine/Query.php +++ b/lib/Doctrine/Query.php @@ -27,6 +27,11 @@ * @license LGPL */ class Doctrine_Query extends Doctrine_Hydrate implements Countable { + const SELECT = 0; + + const DELETE = 1; + + const UPDATE = 2; /** * @param array $subqueryAliases the table aliases needed in some LIMIT subqueries */ @@ -48,6 +53,8 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable { private $pendingFields = array(); + protected $type = self::SELECT; + /** * create * returns a new Doctrine_Query object @@ -270,46 +277,65 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable { public function __call($name, $args) { $name = strtolower($name); - if(isset($this->parts[$name])) { - $method = "parse".ucwords($name); - switch($name): - case "from": - $this->parts['from'] = array(); - $this->parts['select'] = array(); - $this->parts['join'] = array(); - $this->joins = array(); - $this->tables = array(); - $this->fetchModes = array(); - $this->tableIndexes = array(); - $this->tableAliases = array(); + if($name == 'select') + + + + $method = "parse".ucwords($name); + + switch($name) { + case 'select': + $this->type = self::SELECT; + + if( ! isset($args[0])) + throw new Doctrine_Query_Exception('Empty select part'); + + $this->parseSelect($args[0]); + break; + case 'delete': + $this->type = self::DELETE; + break; + case 'update': + $this->type = self::UPDATE; + break; + case 'from': + $this->parts['from'] = array(); + $this->parts['select'] = array(); + $this->parts['join'] = array(); + $this->joins = array(); + $this->tables = array(); + $this->fetchModes = array(); + $this->tableIndexes = array(); + $this->tableAliases = array(); + + $class = "Doctrine_Query_".ucwords($name); + $parser = new $class($this); + + $parser->parse($args[0]); + break; + case 'where': + case 'having': + case 'orderby': + case 'groupby': + $class = "Doctrine_Query_".ucwords($name); + $parser = new $class($this); + + $this->parts[$name] = array($parser->parse($args[0])); + break; + case 'limit': + case 'offset': + if($args[0] == null) + $args[0] = false; + + $this->parts[$name] = $args[0]; + break; + default: + $this->parts[$name] = array(); + $this->$method($args[0]); - $class = "Doctrine_Query_".ucwords($name); - $parser = new $class($this); - - $parser->parse($args[0]); - break; - case "where": - case "having": - case "orderby": - case "groupby": - $class = "Doctrine_Query_".ucwords($name); - $parser = new $class($this); - - $this->parts[$name] = array($parser->parse($args[0])); - break; - case "limit": - case "offset": - if($args[0] == null) - $args[0] = false; - - $this->parts[$name] = $args[0]; - break; - default: - $this->parts[$name] = array(); - $this->$method($args[0]); - endswitch; - } else throw new Doctrine_Query_Exception("Unknown overload method"); + } + return $this; } @@ -371,6 +397,23 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable { public function isLimitSubqueryUsed() { return $this->limitSubqueryUsed; } + + public function getQueryBase() { + switch($this->type) { + case self::DELETE: + $q = 'DELETE FROM '; + break; + case self::UPDATE: + $q = 'UPDATE '; + break; + case self::SELECT: + $distinct = ($this->isDistinct()) ? 'DISTINCT ' : ''; + + $q = 'SELECT '.$distinct.implode(', ', $this->parts['select']).' FROM '; + break; + } + return $q; + } /** * returns the built sql query * @@ -391,13 +434,16 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable { } // build the basic query - + $str = ''; if($this->isDistinct()) $str = 'DISTINCT '; + + $q = "SELECT ".$str.implode(", ",$this->parts["select"]). " FROM "; + $q = $this->getQueryBase(); foreach($this->parts["from"] as $tname => $bool) { $a[] = $tname; @@ -523,17 +569,18 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable { foreach($e as $k=>$part) { $part = trim($part); switch(strtolower($part)) { - case "select": - case "from": - case "where": - case "limit": - case "offset": - case "having": + case 'delete': + case 'select': + case 'from': + case 'where': + case 'limit': + case 'offset': + case 'having': $p = $part; $parts[$part] = array(); break; - case "order": - case "group": + case 'order': + case 'group': $i = ($k + 1); if(isset($e[$i]) && strtolower($e[$i]) === "by") { $p = $part; @@ -554,29 +601,36 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable { foreach($parts as $k => $part) { $part = implode(" ",$part); switch(strtoupper($k)) { - case "SELECT": + case 'DELETE': + $this->type = self::DELETE; + break; + case 'UPDATE': + $this->type = self::UPDATE; + break; + case 'SELECT': + $this->type = self::SELECT; $this->parseSelect($part); break; - case "FROM": + case 'FROM': $class = "Doctrine_Query_".ucwords(strtolower($k)); $parser = new $class($this); $parser->parse($part); break; - case "GROUP": - case "ORDER": + case 'GROUP': + case 'ORDER': $k .= "by"; - case "WHERE": - case "HAVING": + case 'WHERE': + case 'HAVING': $class = "Doctrine_Query_".ucwords(strtolower($k)); $parser = new $class($this); $name = strtolower($k); $this->parts[$name][] = $parser->parse($part); break; - case "LIMIT": + case 'LIMIT': $this->parts["limit"] = trim($part); break; - case "OFFSET": + case 'OFFSET': $this->parts["offset"] = trim($part); break; } diff --git a/tests/QueryDeleteTestCase.php b/tests/QueryDeleteTestCase.php new file mode 100644 index 000000000..afda319d0 --- /dev/null +++ b/tests/QueryDeleteTestCase.php @@ -0,0 +1,69 @@ +parseQuery('DELETE FROM User'); + + $this->assertEqual($q->getQuery(), 'DELETE FROM entity WHERE (entity.type = 0)'); + + $q = new Doctrine_Query(); + + $q->delete()->from('User'); + + $this->assertEqual($q->getQuery(), 'DELETE FROM entity WHERE (entity.type = 0)'); + } + public function testDeleteAll() { + $q = new Doctrine_Query(); + + $q->parseQuery('DELETE FROM Entity'); + + $this->assertEqual($q->getQuery(), 'DELETE FROM entity'); + + $q = new Doctrine_Query(); + + $q->delete()->from('Entity'); + + $this->assertEqual($q->getQuery(), 'DELETE FROM entity'); + } + public function testDeleteWithCondition() { + $q = new Doctrine_Query(); + + $q->parseQuery('DELETE FROM Entity WHERE id = 3'); + + $this->assertEqual($q->getQuery(), 'DELETE FROM entity WHERE id = 3'); + + $q = new Doctrine_Query(); + + $q->delete()->from('Entity')->where('id = 3'); + + $this->assertEqual($q->getQuery(), 'DELETE FROM entity WHERE id = 3'); + } + public function testDeleteWithLimit() { + $q = new Doctrine_Query(); + + $q->parseQuery('DELETE FROM Entity LIMIT 20'); + + $this->assertEqual($q->getQuery(), 'DELETE FROM entity LIMIT 20'); + + $q = new Doctrine_Query(); + + $q->delete()->from('Entity')->limit(20); + + $this->assertEqual($q->getQuery(), 'DELETE FROM entity LIMIT 20'); + } + public function testDeleteWithLimitAndOffset() { + $q = new Doctrine_Query(); + + $q->parseQuery('DELETE FROM Entity LIMIT 10 OFFSET 20'); + + $this->assertEqual($q->getQuery(), 'DELETE FROM entity LIMIT 10 OFFSET 20'); + + $q = new Doctrine_Query(); + + $q->delete()->from('Entity')->limit(10)->offset(20); + + $this->assertEqual($q->getQuery(), 'DELETE FROM entity LIMIT 10 OFFSET 20'); + } +} +?> diff --git a/tests/QuerySelectTestCase.php b/tests/QuerySelectTestCase.php index 736f8c188..90b1150f2 100644 --- a/tests/QuerySelectTestCase.php +++ b/tests/QuerySelectTestCase.php @@ -23,6 +23,17 @@ class Doctrine_Query_Select_TestCase extends Doctrine_UnitTestCase { $this->assertEqual($q->getQuery(), 'SELECT MAX(entity.id) AS entity__0, MIN(entity.name) AS entity__1, COUNT(phonenumber.id) AS phonenumber__2 FROM entity LEFT JOIN phonenumber ON entity.id = phonenumber.entity_id WHERE (entity.type = 0)'); } + public function testEmptySelectPart() { + $q = new Doctrine_Query(); + + try { + $q->select(); + + $this->fail(); + } catch(Doctrine_Query_Exception $e) { + $this->pass(); + } + } public function testUnknownAggregateFunction() { $q = new Doctrine_Query(); diff --git a/tests/QueryTestCase.php b/tests/QueryTestCase.php index bbe45fccd..f1083b1d2 100644 --- a/tests/QueryTestCase.php +++ b/tests/QueryTestCase.php @@ -1,5 +1,5 @@ tables[] = "Forum_Category"; $this->tables[] = "Forum_Entry"; diff --git a/tests/run.php b/tests/run.php index 190902ac6..2e250af73 100644 --- a/tests/run.php +++ b/tests/run.php @@ -38,6 +38,7 @@ require_once("QueryConditionTestCase.php"); require_once("QueryComponentAliasTestCase.php"); require_once("QuerySubqueryTestCase.php"); require_once("QuerySelectTestCase.php"); +require_once("QueryDeleteTestCase.php"); require_once("DBTestCase.php"); require_once("SchemaTestCase.php"); @@ -49,9 +50,6 @@ require_once("RelationTestCase.php"); require_once("DataDictSqliteTestCase.php"); require_once("CustomResultSetOrderTestCase.php"); -// unsorted tests are here, these should be moved somewhere sensible -require_once("UnsortedTestCase.php"); - error_reporting(E_ALL); print "
"; @@ -127,7 +125,7 @@ $test->addTestCase(new Doctrine_Query_ComponentAlias_TestCase()); $test->addTestCase(new Doctrine_Query_Subquery_TestCase()); -$test->addTestCase(new Doctrine_QueryTestCase()); +$test->addTestCase(new Doctrine_Query_TestCase()); $test->addTestCase(new Doctrine_Query_Where_TestCase()); @@ -135,7 +133,8 @@ $test->addTestCase(new Doctrine_Query_From_TestCase()); $test->addTestCase(new Doctrine_Query_Select_TestCase()); -$test->addTestCase(new Doctrine_UnsortedTestCase()); +$test->addTestCase(new Doctrine_Query_Delete_TestCase()); + //$test->addTestCase(new Doctrine_Cache_FileTestCase()); //$test->addTestCase(new Doctrine_Cache_SqliteTestCase());