From bce726d66c1cd0d1240e89a4167454b478ae2bbe Mon Sep 17 00:00:00 2001 From: zYne Date: Fri, 8 Sep 2006 23:20:51 +0000 Subject: [PATCH] Doctrine_Collection::loadRelated() bug fixed --- Doctrine/Association.php | 13 ++-- Doctrine/Collection.php | 5 +- Doctrine/Query.php | 12 ++- Doctrine/Record.php | 1 + Doctrine/Table.php | 10 ++- tests/CollectionTestCase.php | 92 ++++++++++++----------- tests/ConnectionTestCase.php | 13 +++- tests/RecordTestCase.php | 141 ++++++++++++++++++++++------------- tests/run.php | 13 ++-- 9 files changed, 186 insertions(+), 114 deletions(-) diff --git a/Doctrine/Association.php b/Doctrine/Association.php index f2728dc8e..130a5ab40 100644 --- a/Doctrine/Association.php +++ b/Doctrine/Association.php @@ -39,19 +39,20 @@ class Doctrine_Association extends Doctrine_Relation { * @param integer $count * @return string */ - public function getRelationDql($count, $context = 'record') { - $sub = "SELECT ".$this->foreign. - " FROM ".$this->associationTable->getTableName(). - " WHERE ".$this->local. - " IN (".substr(str_repeat("?, ", $count),0,-2).")"; - + public function getRelationDql($count, $context = 'record') { switch($context): case "record": + $sub = "SELECT ".$this->foreign. + " FROM ".$this->associationTable->getTableName(). + " WHERE ".$this->local. + " IN (".substr(str_repeat("?, ", $count),0,-2).")"; + $dql = "FROM ".$this->table->getComponentName(); $dql .= ":".$this->associationTable->getComponentName(); $dql .= " WHERE ".$this->table->getComponentName().".".$this->table->getIdentifier()." IN ($sub)"; break; case "collection": + $sub = substr(str_repeat("?, ", $count),0,-2); $dql = "FROM ".$this->associationTable->getComponentName().".".$this->table->getComponentName(); $dql .= " WHERE ".$this->associationTable->getComponentName().".".$this->local." IN ($sub)"; endswitch; diff --git a/Doctrine/Collection.php b/Doctrine/Collection.php index a3edf8520..f99bf1c33 100644 --- a/Doctrine/Collection.php +++ b/Doctrine/Collection.php @@ -624,10 +624,11 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator $list[] = $value; endforeach; } - $rel = $this->table->getRelation($name); + $this->table->getRelation($name); $dql = $rel->getRelationDql(count($list), 'collection'); $coll = $query->query($dql, $list); + $this->populateRelated($name, $coll); } /** @@ -671,6 +672,7 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator } elseif($rel instanceof Doctrine_Association) { $identifier = $this->table->getIdentifier(); $asf = $rel->getAssociationFactory(); + $name = $table->getComponentName(); foreach($this->data as $key => $record) { if($record->getState() == Doctrine_Record::STATE_TCLEAN || @@ -680,6 +682,7 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator $sub = new Doctrine_Collection($table); foreach($coll as $k => $related) { if($related->get($local) == $record[$identifier]) { + $sub->add($related->get($name)); } } diff --git a/Doctrine/Query.php b/Doctrine/Query.php index 2d43f62e2..4a49a5d08 100644 --- a/Doctrine/Query.php +++ b/Doctrine/Query.php @@ -331,7 +331,12 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable { if($needsSubQuery) { $subquery = $this->connection->modifyLimitQuery($subquery,$this->parts["limit"],$this->parts["offset"]); - + $dbh = $this->connection->getDBH(); + + // mysql doesn't support LIMIT in subqueries + if($dbh->getAttribute(PDO::ATTR_DRIVER_NAME) == 'mysql') { } + //$dbh->query(); + $field = $table->getTableName().'.'.$table->getIdentifier(); array_unshift($this->parts['where'], $field.' IN ('.$subquery.')'); $modifyLimit = false; @@ -804,6 +809,7 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable { return $func; } else { + return $func; } } @@ -816,7 +822,9 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable { $exploded = Doctrine_Query::bracketExplode($string, ','); foreach($exploded as $k => $value) { - $exploded[$k] = $this->parseAggregateFunction($value, $currPath); + $func = $this->parseAggregateFunction($value, $currPath); + $exploded[$k] = $func; + $this->parts["select"][] = $exploded[$k]; } } diff --git a/Doctrine/Record.php b/Doctrine/Record.php index 828589c99..8760af8e9 100644 --- a/Doctrine/Record.php +++ b/Doctrine/Record.php @@ -1302,6 +1302,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite } /** * merge + * merges this record with an array of values * * @param array $values */ diff --git a/Doctrine/Table.php b/Doctrine/Table.php index 232ec319c..1b68490bd 100644 --- a/Doctrine/Table.php +++ b/Doctrine/Table.php @@ -52,7 +52,8 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable { */ private $identifier; /** - * @var integer $identifierType + * @see Doctrine_Identifier constants + * @var integer $identifierType the type of identifier this table uses */ private $identifierType; /** @@ -623,6 +624,11 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable { $relation = new Doctrine_Association($table,$associationTable,$fields[0],$fields[1], $type, $alias); } else { + + // auto initialize a new one-to-one relationship for association table + $associationTable->bind($this->getComponentName(), $associationTable->getComponentName().'.'.$e2[1], Doctrine_Relation::ONE_AGGREGATE, 'id'); + $associationTable->bind($table->getComponentName(), $associationTable->getComponentName().'.'.$foreign, Doctrine_Relation::ONE_AGGREGATE, 'id'); + // NORMAL MANY-TO-MANY RELATIONSHIP $this->relations[$e2[0]] = new Doctrine_ForeignKey($associationTable,$local,$e2[1],Doctrine_Relation::MANY_COMPOSITE, $e2[0]); @@ -633,7 +639,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable { $this->relations[$alias] = $relation; return $this->relations[$alias]; } - throw new Doctrine_Table_Exception('Unknown relation '.$original); + throw new Doctrine_Table_Exception($this->name . " doesn't have a relation to " . $original); } /** * returns an array containing all foreign key objects diff --git a/tests/CollectionTestCase.php b/tests/CollectionTestCase.php index 4b61daf88..72c67ec5f 100644 --- a/tests/CollectionTestCase.php +++ b/tests/CollectionTestCase.php @@ -1,49 +1,5 @@ name = 'resource 1'; - $resource[0]->Type[0]->type = 'type 1'; - $resource[0]->Type[1]->type = 'type 2'; - $resource[1]->name = 'resource 2'; - $resource[1]->Type[0]->type = 'type 3'; - $resource[1]->Type[1]->type = 'type 4'; - - $resource->save(); - - $this->connection->clear(); - - $resources = $this->connection->query('FROM Resource'); - - $count = $this->dbh->count(); - $resources->loadRelated('Type'); - - $this->assertEqual(($count + 1), $this->dbh->count()); - $this->assertEqual($resources[0]->name, 'resource 1'); - $this->assertEqual($resource[0]->Type[0]->type, 'type 1'); - $this->assertEqual($resource[0]->Type[1]->type, 'type 2'); - $this->assertEqual(($count + 1), $this->dbh->count()); - - $this->assertEqual($resource[1]->name, 'resource 2'); - $this->assertEqual($resource[1]->Type[0]->type, 'type 3'); - $this->assertEqual($resource[1]->Type[1]->type, 'type 4'); - $this->assertEqual(($count + 1), $this->dbh->count()); - } - public function testAdd() { - $coll = new Doctrine_Collection($this->objTable); - $coll->add(new User()); - $this->assertEqual($coll->count(),1); - $coll->add(new User()); - $this->assertTrue($coll->count(),2); - - $this->assertEqual($coll->getKeys(), array(0,1)); - - $coll[2] = new User(); - - $this->assertTrue($coll->count(),3); - $this->assertEqual($coll->getKeys(), array(0,1,2)); - } - public function testLoadRelatedForAssociation() { $coll = $this->connection->query("FROM User"); @@ -98,6 +54,53 @@ class Doctrine_CollectionTestCase extends Doctrine_UnitTestCase { $this->connection->clear(); } + + public function testLoadRelatedForNormalAssociation() { + $resource = new Doctrine_Collection('Resource'); + $resource[0]->name = 'resource 1'; + $resource[0]->Type[0]->type = 'type 1'; + $resource[0]->Type[1]->type = 'type 2'; + $resource[1]->name = 'resource 2'; + $resource[1]->Type[0]->type = 'type 3'; + $resource[1]->Type[1]->type = 'type 4'; + + $resource->save(); + + $this->connection->clear(); + + $resources = $this->connection->query('FROM Resource'); + + $count = $this->dbh->count(); + $resources->loadRelated('Type'); + + $this->assertEqual(($count + 1), $this->dbh->count()); + $this->assertEqual($resources[0]->name, 'resource 1'); + $this->assertEqual($resource[0]->Type[0]->type, 'type 1'); + $this->assertEqual($resource[0]->Type[1]->type, 'type 2'); + $this->assertEqual(($count + 1), $this->dbh->count()); + + $this->assertEqual($resource[1]->name, 'resource 2'); + $this->assertEqual($resource[1]->Type[0]->type, 'type 3'); + $this->assertEqual($resource[1]->Type[1]->type, 'type 4'); + $this->assertEqual(($count + 1), $this->dbh->count()); + } + + public function testAdd() { + $coll = new Doctrine_Collection($this->objTable); + $coll->add(new User()); + $this->assertEqual($coll->count(),1); + $coll->add(new User()); + $this->assertTrue($coll->count(),2); + + $this->assertEqual($coll->getKeys(), array(0,1)); + + $coll[2] = new User(); + + $this->assertTrue($coll->count(),3); + $this->assertEqual($coll->getKeys(), array(0,1,2)); + } + + public function testLoadRelated() { $coll = $this->connection->query("FROM User(id)"); @@ -269,5 +272,6 @@ class Doctrine_CollectionTestCase extends Doctrine_UnitTestCase { $this->assertEqual($users[4]->Phonenumber[1]->exists(), false); $this->assertEqual($users[4]->Phonenumber[2]->getState(), Doctrine_Record::STATE_CLEAN); } + } ?> diff --git a/tests/ConnectionTestCase.php b/tests/ConnectionTestCase.php index 7881c6a14..480945a8d 100644 --- a/tests/ConnectionTestCase.php +++ b/tests/ConnectionTestCase.php @@ -5,6 +5,16 @@ class Doctrine_ConnectionTestCase extends Doctrine_UnitTestCase { public function testBuildFlushTree() { $correct = array("Task","ResourceType","Resource","Assignment","ResourceReference"); + // new model might switch some many-to-many components (NO HARM!) + + $correct2 = array ( + 0 => 'Resource', + 1 => 'Task', + 2 => 'ResourceType', + 3 => 'Assignment', + 4 => 'ResourceReference', + ); + $task = new Task(); $tree = $this->connection->buildFlushTree(array("Task")); @@ -17,7 +27,8 @@ class Doctrine_ConnectionTestCase extends Doctrine_UnitTestCase { $this->assertEqual($tree,$correct); $tree = $this->connection->buildFlushTree(array("Assignment","Task","Resource")); - $this->assertEqual($tree,$correct); + + $this->assertEqual($tree,$correct2); $correct = array("Forum_Category","Forum_Board","Forum_Thread"); diff --git a/tests/RecordTestCase.php b/tests/RecordTestCase.php index 1f3d294c5..537e60d1f 100644 --- a/tests/RecordTestCase.php +++ b/tests/RecordTestCase.php @@ -7,57 +7,7 @@ class Doctrine_RecordTestCase extends Doctrine_UnitTestCase { $this->tables[] = "enumTest"; parent::prepareTables(); } - public function testToArray() { - $user = new User(); - - $a = $user->toArray(); - - $this->assertTrue(is_array($a)); - $this->assertTrue(array_key_exists('name', $a)); - $this->assertEqual($a['name'], null); - $this->assertTrue(array_key_exists('id', $a)); - $this->assertEqual($a['id'], null); - - $user->name = 'Someone'; - - $user->save(); - - $a = $user->toArray(); - - $this->assertTrue(is_array($a)); - $this->assertTrue(array_key_exists('name', $a)); - $this->assertEqual($a['name'], 'Someone'); - $this->assertTrue(array_key_exists('id', $a)); - $this->assertEqual($a['id'], 12); - - $user->refresh(); - - $a = $user->toArray(); - - $this->assertTrue(is_array($a)); - $this->assertTrue(array_key_exists('name', $a)); - $this->assertEqual($a['name'], 'Someone'); - $this->assertTrue(array_key_exists('id', $a)); - $this->assertEqual($a['id'], 12); - $this->connection->clear(); - $user = $user->getTable()->find($user->id); - - $a = $user->toArray(); - - $this->assertTrue(is_array($a)); - $this->assertTrue(array_key_exists('name', $a)); - $this->assertEqual($a['name'], 'Someone'); - $this->assertTrue(array_key_exists('id', $a)); - $this->assertEqual($a['id'], 12); - } - - public function testReferences2() { - $user = new User(); - $user->Phonenumber[0]->phonenumber = '123 123'; - $this->assertEqual($user->Phonenumber[0]->entity_id, $user); - } - - public function testJoinTableSelfReferencing() { + public function testJoinTableSelfReferencingInsertingData() { $e = new Entity(); $e->name = "Entity test"; $this->assertTrue($e->Entity[0] instanceof Entity); @@ -109,15 +59,44 @@ class Doctrine_RecordTestCase extends Doctrine_UnitTestCase { $this->assertEqual($e->Entity[0]->getState(), Doctrine_Record::STATE_CLEAN); $this->assertEqual($e->Entity[1]->getState(), Doctrine_Record::STATE_CLEAN); - + $this->assertTrue(is_numeric($e->id)); + $result = $this->dbh->query("SELECT * FROM entity_reference")->fetchAll(PDO::FETCH_ASSOC); + + $this->assertEqual(count($result), 6); + + $q = "SELECT entity.id AS entity__id, + entity.name AS entity__name, + entity.loginname AS entity__loginname, + entity.password AS entity__password, + entity.type AS entity__type, + entity.created AS entity__created, + entity.updated AS entity__updated, + entity.email_id AS entity__email_id, + entity_reference.entity1 AS entity_reference__entity1, + entity_reference.entity2 AS entity_reference__entity2 + FROM entity + INNER JOIN entity_reference + ON entity.id = entity_reference.entity1 + WHERE entity.id IN (SELECT entity2 FROM entity_reference WHERE entity1 IN (?))"; + $stmt = $this->dbh->prepare($q); + + $stmt->execute(array(18)); + $result = $stmt->fetchAll(PDO::FETCH_ASSOC); + + $this->connection->clear(); + $e = $e->getTable()->find($e->id); + $count = count($this->dbh); + $this->assertTrue($e instanceof Entity); $this->assertTrue($e->Entity[0] instanceof Entity); $this->assertTrue($e->Entity[1] instanceof Entity); + + $this->assertEqual(count($this->dbh), ($count + 1)); $this->assertEqual($e->Entity[0]->name, "Friend 1"); $this->assertEqual($e->Entity[1]->name, "Friend 2"); @@ -125,9 +104,13 @@ class Doctrine_RecordTestCase extends Doctrine_UnitTestCase { $this->assertEqual($e->Entity[0]->Entity[0]->name, "Friend 1 1"); $this->assertEqual($e->Entity[0]->Entity[1]->name, "Friend 1 2"); + $this->assertEqual(count($this->dbh), ($count + 2)); + $this->assertEqual($e->Entity[1]->Entity[0]->name, "Friend 2 1"); $this->assertEqual($e->Entity[1]->Entity[1]->name, "Friend 2 2"); + $this->assertEqual(count($this->dbh), ($count + 3)); + $this->assertEqual($e->Entity[0]->getState(), Doctrine_Record::STATE_CLEAN); $this->assertEqual($e->Entity[1]->getState(), Doctrine_Record::STATE_CLEAN); @@ -145,6 +128,58 @@ class Doctrine_RecordTestCase extends Doctrine_UnitTestCase { $this->assertEqual($coll->count(), 1); } +/** + public function testToArray() { + $user = new User(); + + $a = $user->toArray(); + + $this->assertTrue(is_array($a)); + $this->assertTrue(array_key_exists('name', $a)); + $this->assertEqual($a['name'], null); + $this->assertTrue(array_key_exists('id', $a)); + $this->assertEqual($a['id'], null); + + $user->name = 'Someone'; + + $user->save(); + + $a = $user->toArray(); + + $this->assertTrue(is_array($a)); + $this->assertTrue(array_key_exists('name', $a)); + $this->assertEqual($a['name'], 'Someone'); + $this->assertTrue(array_key_exists('id', $a)); + $this->assertTrue(is_numeric($a['id'])); + + $user->refresh(); + + $a = $user->toArray(); + + $this->assertTrue(is_array($a)); + $this->assertTrue(array_key_exists('name', $a)); + $this->assertEqual($a['name'], 'Someone'); + $this->assertTrue(array_key_exists('id', $a)); + $this->assertTrue(is_numeric($a['id'])); + $this->connection->clear(); + $user = $user->getTable()->find($user->id); + + $a = $user->toArray(); + + $this->assertTrue(is_array($a)); + $this->assertTrue(array_key_exists('name', $a)); + $this->assertEqual($a['name'], 'Someone'); + $this->assertTrue(array_key_exists('id', $a)); + $this->assertTrue(is_numeric($a['id'])); + } + + public function testReferences2() { + $user = new User(); + $user->Phonenumber[0]->phonenumber = '123 123'; + $this->assertEqual($user->Phonenumber[0]->entity_id, $user); + } + + public function testCountRelated() { $user = $this->connection->getTable('Entity')->find(5); $c = $user->countRelated('Phonenumber'); @@ -888,6 +923,6 @@ class Doctrine_RecordTestCase extends Doctrine_UnitTestCase { $user = $this->connection->getTable("User")->find(4); $this->assertTrue($user->getIterator() instanceof ArrayIterator); } - + */ } ?> diff --git a/tests/run.php b/tests/run.php index 9cf5c444b..bb498be25 100644 --- a/tests/run.php +++ b/tests/run.php @@ -32,10 +32,10 @@ error_reporting(E_ALL); $test = new GroupTest("Doctrine Framework Unit Tests"); -$test->addTestCase(new Doctrine_TableTestCase()); - $test->addTestCase(new Doctrine_RecordTestCase()); +$test->addTestCase(new Doctrine_TableTestCase()); + $test->addTestCase(new Doctrine_ConnectionTestCase()); $test->addTestCase(new Doctrine_ManagerTestCase()); @@ -62,8 +62,6 @@ $test->addTestCase(new Doctrine_Filter_TestCase()); $test->addTestCase(new Doctrine_ValueHolder_TestCase()); -$test->addTestCase(new Doctrine_QueryTestCase()); - $test->addTestCase(new Doctrine_RawSql_TestCase()); $test->addTestCase(new Doctrine_Query_Limit_TestCase()); @@ -72,9 +70,14 @@ $test->addTestCase(new Doctrine_SchemaTestCase()); $test->addTestCase(new Doctrine_ImportTestCase()); +$test->addTestCase(new Doctrine_ValidatorTestCase()); + +$test->addTestCase(new Doctrine_QueryTestCase()); + $test->addTestCase(new Doctrine_CollectionTestCase()); -$test->addTestCase(new Doctrine_ValidatorTestCase()); + + //$test->addTestCase(new Doctrine_Cache_FileTestCase()); //$test->addTestCase(new Doctrine_Cache_SqliteTestCase());