Commit 5471e9e2 authored by doctrine's avatar doctrine

DQL: Condition parsing with nested conditions bug fixed

parent 143b2749
...@@ -3,7 +3,7 @@ class Doctrine_Module implements IteratorAggregate, Countable { ...@@ -3,7 +3,7 @@ class Doctrine_Module implements IteratorAggregate, Countable {
/** /**
* @var array $components an array containing all the components in this module * @var array $components an array containing all the components in this module
*/ */
private $components = array(); protected $components = array();
/** /**
* @var string $name the name of this module * @var string $name the name of this module
*/ */
......
...@@ -181,7 +181,27 @@ class Doctrine_Query extends Doctrine_Access { ...@@ -181,7 +181,27 @@ class Doctrine_Query extends Doctrine_Access {
} }
} }
} }
/** /**
* addFrom
*
* @param strint $from
*/
public function addFrom($from) {
$class = "Doctrine_Query_From";
$parser = new $class($this);
$parser->parse($from);
}
/**
* addWhere
*
* @param string $where
*/
public function addWhere($where) {
$class = "Doctrine_Query_Where";
$parser = new $class($this);
$this->parts['where'][] = $parser->parse($where);
}
/**
* sets a query part * sets a query part
* *
* @param string $name * @param string $name
...@@ -190,6 +210,7 @@ class Doctrine_Query extends Doctrine_Access { ...@@ -190,6 +210,7 @@ class Doctrine_Query extends Doctrine_Access {
*/ */
public function __call($name, $args) { public function __call($name, $args) {
$name = strtolower($name); $name = strtolower($name);
if(isset($this->parts[$name])) { if(isset($this->parts[$name])) {
$method = "parse".ucwords($name); $method = "parse".ucwords($name);
switch($name): switch($name):
...@@ -423,8 +444,6 @@ class Doctrine_Query extends Doctrine_Access { ...@@ -423,8 +444,6 @@ class Doctrine_Query extends Doctrine_Access {
return $this->getCollection($keys[0]); return $this->getCollection($keys[0]);
break; break;
default: default:
$query = $this->getQuery();
$keys = array_keys($this->tables); $keys = array_keys($this->tables);
$root = $keys[0]; $root = $keys[0];
...@@ -437,6 +456,7 @@ class Doctrine_Query extends Doctrine_Access { ...@@ -437,6 +456,7 @@ class Doctrine_Query extends Doctrine_Access {
$array = $this->parseData($stmt); $array = $this->parseData($stmt);
$colls = array(); $colls = array();
foreach($array as $data) { foreach($array as $data) {
...@@ -664,7 +684,8 @@ class Doctrine_Query extends Doctrine_Access { ...@@ -664,7 +684,8 @@ class Doctrine_Query extends Doctrine_Access {
final public function parseQuery($query) { final public function parseQuery($query) {
$this->clear(); $this->clear();
$e = self::bracketExplode($query," ","(",")"); $e = self::bracketExplode($query," ","(",")");
$parts = array(); $parts = array();
foreach($e as $k=>$part): foreach($e as $k=>$part):
switch(strtolower($part)): switch(strtolower($part)):
...@@ -939,35 +960,15 @@ class Doctrine_Query extends Doctrine_Access { ...@@ -939,35 +960,15 @@ class Doctrine_Query extends Doctrine_Access {
$tableName = $tname2; $tableName = $tname2;
} }
// parse the fetchmode and load table fields
if( ! isset($this->tables[$tableName])) { if( ! isset($this->tables[$tableName])) {
$this->tables[$tableName] = $table; $this->tables[$tableName] = $table;
if($loadFields && ! $this->aggregate) { if($loadFields && ! $this->aggregate) {
$fields = array(); $this->parseFields($fullname, $tableName, $e2, $currPath);
if(strpos($fullname, "-") === false) {
$fetchmode = $table->getAttribute(Doctrine::ATTR_FETCHMODE);
if(isset($e2[1]))
$fields = explode(",",substr($e2[1],0,-1));
} else {
if(isset($e2[1])) {
$fetchmode = $this->parseFetchMode($e2[1]);
} else
$fetchmode = $table->getAttribute(Doctrine::ATTR_FETCHMODE);
if(isset($e2[2]))
$fields = explode(",",substr($e2[2],0,-1));
}
$this->loadFields($table, $fetchmode, $fields, $currPath);
} }
} }
$prevPath = $currPath; $prevPath = $currPath;
$prevTable = $tableName; $prevTable = $tableName;
} catch(Exception $e) { } catch(Exception $e) {
...@@ -976,6 +977,38 @@ class Doctrine_Query extends Doctrine_Access { ...@@ -976,6 +977,38 @@ class Doctrine_Query extends Doctrine_Access {
} }
return $table; return $table;
} }
/**
* parseFields
*
* @param string $fullName
* @param string $tableName
* @param array $exploded
* @param string $currPath
* @return void
*/
final public function parseFields($fullName, $tableName, $exploded, $currPath) {
$table = $this->tables[$tableName];
$fields = array();
if(strpos($fullName, "-") === false) {
$fetchmode = $table->getAttribute(Doctrine::ATTR_FETCHMODE);
if(isset($exploded[1]))
$fields = explode(",",substr($exploded[1],0,-1));
} else {
if(isset($exploded[1])) {
$fetchmode = $this->parseFetchMode($exploded[1]);
} else
$fetchmode = $table->getAttribute(Doctrine::ATTR_FETCHMODE);
if(isset($exploded[2]))
$fields = explode(",",substr($exploded[2],0,-1));
}
$this->loadFields($table, $fetchmode, $fields, $currPath);
}
} }
?> ?>
...@@ -11,41 +11,35 @@ abstract class Doctrine_Query_Condition extends Doctrine_Query_Part { ...@@ -11,41 +11,35 @@ abstract class Doctrine_Query_Condition extends Doctrine_Query_Part {
* @return string * @return string
*/ */
final public function parse($str) { final public function parse($str) {
$tmp = trim($str); $tmp = trim($str);
$str = Doctrine_Query::bracketTrim($tmp,"(",")");
$brackets = false;
while($tmp != $str) {
$brackets = true;
$tmp = $str;
$str = Doctrine_Query::bracketTrim($str,"(",")");
}
$parts = Doctrine_Query::bracketExplode($str," && ","(",")"); $parts = Doctrine_Query::bracketExplode($str," && ","(",")");
if(count($parts) > 1) { if(count($parts) > 1) {
$ret = array(); $ret = array();
foreach($parts as $part) { foreach($parts as $part) {
$ret[] = $this->parse($part, $type); $part = Doctrine_Query::bracketTrim($part, "(", ")");
$ret[] = $this->parse($part);
} }
$r = implode(" AND ",$ret); $r = implode(" AND ",$ret);
} else { } else {
$parts = Doctrine_Query::bracketExplode($str," || ","(",")"); $parts = Doctrine_Query::bracketExplode($str," || ","(",")");
if(count($parts) > 1) { if(count($parts) > 1) {
$ret = array(); $ret = array();
foreach($parts as $part) { foreach($parts as $part) {
$part = Doctrine_Query::bracketTrim($part, "(", ")");
$ret[] = $this->parse($part); $ret[] = $this->parse($part);
} }
$r = implode(" OR ",$ret); $r = implode(" OR ",$ret);
} else { } else {
return $this->load($parts[0]); if(substr($parts[0],0,1) == "(" && substr($parts[0],-1) == ")")
return $this->parse(substr($parts[0],1,-1));
else
return $this->load($parts[0]);
} }
} }
if($brackets)
return "(".$r.")"; return "(".$r.")";
else
return $r;
} }
} }
?> ?>
...@@ -3,13 +3,14 @@ require_once("Condition.php"); ...@@ -3,13 +3,14 @@ require_once("Condition.php");
class Doctrine_Query_Where extends Doctrine_Query_Condition { class Doctrine_Query_Where extends Doctrine_Query_Condition {
/** /**
* loadWhere * load
* returns the parsed query part * returns the parsed query part
* *
* @param string $where * @param string $where
* @return string * @return string
*/ */
final public function load($where) { final public function load($where) {
$e = explode(" ",$where); $e = explode(" ",$where);
$r = array_shift($e); $r = array_shift($e);
$a = explode(".",$r); $a = explode(".",$r);
...@@ -17,11 +18,17 @@ class Doctrine_Query_Where extends Doctrine_Query_Condition { ...@@ -17,11 +18,17 @@ class Doctrine_Query_Where extends Doctrine_Query_Condition {
if(count($a) > 1) { if(count($a) > 1) {
$field = array_pop($a); $field = array_pop($a);
$operator = array_shift($e); $count = count($e);
$value = implode(" ",$e); $slice = array_slice($e, 0, ($count - 1));
$operator = implode(' ', $slice);
$slice = array_slice($e, -1, 1);
$value = implode('', $slice);
$reference = implode(".",$a); $reference = implode(".",$a);
$count = count($a); $count = count($a);
$table = $this->query->load($reference, false); $table = $this->query->load($reference, false);
$where = $this->query->getTableAlias($reference).".".$field." ".$operator." ".$value; $where = $this->query->getTableAlias($reference).".".$field." ".$operator." ".$value;
} }
......
...@@ -34,6 +34,41 @@ class Doctrine_QueryTestCase extends Doctrine_UnitTestCase { ...@@ -34,6 +34,41 @@ class Doctrine_QueryTestCase extends Doctrine_UnitTestCase {
$this->assertEqual($users->count(), 8); $this->assertEqual($users->count(), 8);
} }
*/ */
public function testConditionParser() {
$query = new Doctrine_Query($this->session);
$query->from("User(id)")->where("User.name LIKE 'z%' || User.name LIKE 's%'");
$sql = "SELECT entity.id AS entity__id FROM entity WHERE (entity.name LIKE 'z%' OR entity.name LIKE 's%') AND (entity.type = 0)";
$this->assertEqual($query->getQuery(), $sql);
$query->where("(User.name LIKE 'z%') || (User.name LIKE 's%')");
$this->assertEqual($query->getQuery(), $sql);
$query->where("((User.name LIKE 'z%') || (User.name LIKE 's%'))");
$this->assertEqual($query->getQuery(), $sql);
$query->where("(((User.name LIKE 'z%') || (User.name LIKE 's%')))");
$this->assertEqual($query->getQuery(), $sql);
$query->where("(((User.name LIKE 'z%') || User.name LIKE 's%'))");
$this->assertEqual($query->getQuery(), $sql);
$query->where("(User.name LIKE 'z%') || User.name LIKE 's%' && User.name LIKE 'a%'");
$sql = "SELECT entity.id AS entity__id FROM entity WHERE ((entity.name LIKE 'z%' OR entity.name LIKE 's%') AND entity.name LIKE 'a%') AND (entity.type = 0)";
$this->assertEqual($query->getQuery(), $sql);
$query->where("(((User.name LIKE 'z%') || User.name LIKE 's%')) && User.name LIKE 'a%'");
$this->assertEqual($query->getQuery(), $sql);
$query->where("((((User.name LIKE 'z%') || User.name LIKE 's%')) && User.name LIKE 'a%')");
$this->assertEqual($query->getQuery(), $sql);
$query->where("(((((User.name LIKE 'z%') || User.name LIKE 's%')) && User.name LIKE 'a%'))");
$this->assertEqual($query->getQuery(), $sql);
}
public function testSelfReferencing() { public function testSelfReferencing() {
$query = new Doctrine_Query($this->session); $query = new Doctrine_Query($this->session);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment