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 {
/**
* @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
*/
......
......@@ -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
*
* @param string $name
......@@ -190,6 +210,7 @@ class Doctrine_Query extends Doctrine_Access {
*/
public function __call($name, $args) {
$name = strtolower($name);
if(isset($this->parts[$name])) {
$method = "parse".ucwords($name);
switch($name):
......@@ -423,8 +444,6 @@ class Doctrine_Query extends Doctrine_Access {
return $this->getCollection($keys[0]);
break;
default:
$query = $this->getQuery();
$keys = array_keys($this->tables);
$root = $keys[0];
......@@ -437,6 +456,7 @@ class Doctrine_Query extends Doctrine_Access {
$array = $this->parseData($stmt);
$colls = array();
foreach($array as $data) {
......@@ -664,7 +684,8 @@ class Doctrine_Query extends Doctrine_Access {
final public function parseQuery($query) {
$this->clear();
$e = self::bracketExplode($query," ","(",")");
$parts = array();
foreach($e as $k=>$part):
switch(strtolower($part)):
......@@ -939,35 +960,15 @@ class Doctrine_Query extends Doctrine_Access {
$tableName = $tname2;
}
// parse the fetchmode and load table fields
if( ! isset($this->tables[$tableName])) {
$this->tables[$tableName] = $table;
if($loadFields && ! $this->aggregate) {
$fields = array();
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);
$this->parseFields($fullname, $tableName, $e2, $currPath);
}
}
$prevPath = $currPath;
$prevTable = $tableName;
} catch(Exception $e) {
......@@ -976,6 +977,38 @@ class Doctrine_Query extends Doctrine_Access {
}
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 {
* @return string
*/
final public function parse($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," && ","(",")");
if(count($parts) > 1) {
$ret = array();
foreach($parts as $part) {
$ret[] = $this->parse($part, $type);
$part = Doctrine_Query::bracketTrim($part, "(", ")");
$ret[] = $this->parse($part);
}
$r = implode(" AND ",$ret);
} else {
$parts = Doctrine_Query::bracketExplode($str," || ","(",")");
if(count($parts) > 1) {
$ret = array();
foreach($parts as $part) {
$part = Doctrine_Query::bracketTrim($part, "(", ")");
$ret[] = $this->parse($part);
}
$r = implode(" OR ",$ret);
} 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.")";
else
return $r;
return "(".$r.")";
}
}
?>
......@@ -3,13 +3,14 @@ require_once("Condition.php");
class Doctrine_Query_Where extends Doctrine_Query_Condition {
/**
* loadWhere
* load
* returns the parsed query part
*
* @param string $where
* @return string
*/
final public function load($where) {
$e = explode(" ",$where);
$r = array_shift($e);
$a = explode(".",$r);
......@@ -17,11 +18,17 @@ class Doctrine_Query_Where extends Doctrine_Query_Condition {
if(count($a) > 1) {
$field = array_pop($a);
$operator = array_shift($e);
$value = implode(" ",$e);
$count = count($e);
$slice = array_slice($e, 0, ($count - 1));
$operator = implode(' ', $slice);
$slice = array_slice($e, -1, 1);
$value = implode('', $slice);
$reference = implode(".",$a);
$count = count($a);
$table = $this->query->load($reference, false);
$where = $this->query->getTableAlias($reference).".".$field." ".$operator." ".$value;
}
......
......@@ -34,6 +34,41 @@ class Doctrine_QueryTestCase extends Doctrine_UnitTestCase {
$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() {
$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