From e15cfd70b20a87641e2978a5af4b0a200b3d20a2 Mon Sep 17 00:00:00 2001 From: doctrine Date: Fri, 26 May 2006 20:15:27 +0000 Subject: [PATCH] DQL: Lazy property fetching --- classes/Query.class.php | 37 +++++++++++++------ classes/Record.class.php | 6 +++- classes/Table.class.php | 6 ++++ classes/Validator/Notnull.class.php | 2 +- tests/QueryTestCase.class.php | 56 +++++++++++++++++++++++++---- 5 files changed, 88 insertions(+), 19 deletions(-) diff --git a/classes/Query.class.php b/classes/Query.class.php index 00509481b..e3e283b25 100644 --- a/classes/Query.class.php +++ b/classes/Query.class.php @@ -116,22 +116,26 @@ class Doctrine_Query extends Doctrine_Access { * @access private * @param object Doctrine_Table $table a Doctrine_Table object * @param integer $fetchmode fetchmode the table is using eg. Doctrine::FETCH_LAZY + * @param array $names fields to be loaded (only used in lazy property loading) * @return void */ - private function loadFields(Doctrine_Table $table,$fetchmode) { + private function loadFields(Doctrine_Table $table, $fetchmode, array $names) { $name = $table->getComponentName(); switch($fetchmode): case Doctrine::FETCH_OFFSET: $this->limit = $table->getAttribute(Doctrine::ATTR_COLL_LIMIT); case Doctrine::FETCH_IMMEDIATE: + if( ! empty($names)) + throw new Doctrine_Exception("Lazy property loading can only be used with fetching strategies lazy, batch and lazyoffset."); + $names = $table->getColumnNames(); break; case Doctrine::FETCH_LAZY_OFFSET: $this->limit = $table->getAttribute(Doctrine::ATTR_COLL_LIMIT); case Doctrine::FETCH_LAZY: case Doctrine::FETCH_BATCH: - $names = $table->getPrimaryKeys(); + $names = array_merge($table->getPrimaryKeys(), $names); break; default: throw new Doctrine_Exception("Unknown fetchmode."); @@ -879,9 +883,9 @@ class Doctrine_Query extends Doctrine_Access { $e = preg_split("/[.:]/",$path); $index = 0; - foreach($e as $key => $name) { + foreach($e as $key => $fullname) { try { - $e2 = explode("-",$name); + $e2 = preg_split("/[-(]/",$fullname); $name = $e2[0]; if($key == 0) { @@ -943,15 +947,28 @@ class Doctrine_Query extends Doctrine_Access { } if( ! isset($this->tables[$name])) { + $this->tables[$name] = $table; - $this->tables[$name] = $table; if($loadFields && ! $this->aggregate) { - if(isset($e2[1])) { - $fetchmode = $this->parseFetchMode($e2[1]); - } else + $fields = array(); + + if(strpos($fullname, "-") === false) { $fetchmode = $table->getAttribute(Doctrine::ATTR_FETCHMODE); - - $this->loadFields($table, $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); } } diff --git a/classes/Record.class.php b/classes/Record.class.php index fcae59dd9..aab162589 100644 --- a/classes/Record.class.php +++ b/classes/Record.class.php @@ -125,6 +125,9 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite // get the data array $this->data = $this->table->getData(); + // get the column count + $count = count($this->data); + // clean data array $cols = $this->cleanData(); @@ -143,8 +146,9 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite } else { $this->state = Doctrine_Record::STATE_CLEAN; - if($cols <= 1) + if($count < $this->table->getColumnCount()) { $this->state = Doctrine_Record::STATE_PROXY; + } // listen the onLoad event diff --git a/classes/Table.class.php b/classes/Table.class.php index 22076fb66..7ba886b1c 100644 --- a/classes/Table.class.php +++ b/classes/Table.class.php @@ -780,6 +780,12 @@ class Doctrine_Table extends Doctrine_Configurable { } return $coll; } + /** + * @return integer + */ + final public function getColumnCount() { + return count($this->columns); + } /** * returns all columns and their definitions * diff --git a/classes/Validator/Notnull.class.php b/classes/Validator/Notnull.class.php index f1d89ef86..f30122f8c 100644 --- a/classes/Validator/Notnull.class.php +++ b/classes/Validator/Notnull.class.php @@ -7,7 +7,7 @@ class Doctrine_Validator_Notnull { * @return boolean */ public function validate(Doctrine_Record $record, $key, $value) { - if ($value === null) + if ($value === null || $value === '') return false; return true; diff --git a/tests/QueryTestCase.class.php b/tests/QueryTestCase.class.php index 114ab8840..77982091a 100644 --- a/tests/QueryTestCase.class.php +++ b/tests/QueryTestCase.class.php @@ -7,6 +7,48 @@ class Doctrine_QueryTestCase extends Doctrine_UnitTestCase { $this->tables[] = "Forum_Thread"; parent::prepareTables(); } + public function testNotValidLazyPropertyFetching() { + $q = new Doctrine_Query($this->session); + + $f = false; + try { + $q->from("User(name)"); + } catch(Doctrine_Exception $e) { + $f = true; + } + $this->assertTrue($f); + } + public function testValidLazyPropertyFetching() { + $q = new Doctrine_Query($this->session); + $q->from("User-l(name)"); + $users = $q->execute(); + $this->assertEqual($users->count(), 8); + $this->assertTrue($users instanceof Doctrine_Collection_Lazy); + $count = count($this->dbh); + $this->assertTrue(is_string($users[0]->name)); + $this->assertEqual($count, count($this->dbh)); + $count = count($this->dbh); + $this->assertTrue(is_numeric($users[0]->email_id)); + $this->assertEqual($count + 1, count($this->dbh)); + + $users[0]->getTable()->clear(); + + $q->from("User-b(name)"); + $users = $q->execute(); + $this->assertEqual($users->count(), 8); + $this->assertTrue($users instanceof Doctrine_Collection_Batch); + $count = count($this->dbh); + $this->assertTrue(is_string($users[0]->name)); + $this->assertEqual($count, count($this->dbh)); + $count = count($this->dbh); + $this->assertTrue(is_numeric($users[0]->email_id)); + $this->assertEqual($count + 1, count($this->dbh)); + $this->assertTrue(is_numeric($users[1]->email_id)); + $this->assertEqual($count + 1, count($this->dbh)); + $this->assertTrue(is_numeric($users[2]->email_id)); + $this->assertEqual($count + 1, count($this->dbh)); + } + public function testQueryWithComplexAliases() { $q = new Doctrine_Query($this->session); @@ -353,13 +395,13 @@ class Doctrine_QueryTestCase extends Doctrine_UnitTestCase { "SELECT entity.id AS User__id FROM entity WHERE (entity.id IN (SELECT user_id FROM groupuser WHERE group_id IN (SELECT entity.id AS Group__id FROM entity, phonenumber WHERE (phonenumber.phonenumber LIKE '123 123') AND (entity.type = 1)))) AND (entity.type = 0)"); $this->assertTrue($users instanceof Doctrine_Collection); $this->assertEqual($users->count(),1); - /** - $values = $query->query("SELECT COUNT(User.name) AS users, MAX(User.name) AS max FROM User"); - $this->assertEqual(trim($query->getQuery()),"SELECT COUNT(entity.name) AS users, MAX(entity.name) AS max FROM entity WHERE (entity.type = 0)"); - $this->assertTrue(is_array($values)); - $this->assertTrue(isset($values['users'])); - $this->assertTrue(isset($values['max'])); - */ + + //$values = $query->query("SELECT COUNT(User.name) AS users, MAX(User.name) AS max FROM User"); + //$this->assertEqual(trim($query->getQuery()),"SELECT COUNT(entity.name) AS users, MAX(entity.name) AS max FROM entity WHERE (entity.type = 0)"); + //$this->assertTrue(is_array($values)); + //$this->assertTrue(isset($values['users'])); + //$this->assertTrue(isset($values['max'])); + } } ?>