DQL: Condition parsing with nested conditions bug fixed
This commit is contained in:
parent
143b274964
commit
5471e9e2ad
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user