DQL: direct one-to-one relation fetching bug fixed
This commit is contained in:
parent
e15cfd70b2
commit
20990ed204
@ -28,6 +28,7 @@ class Doctrine_Collection_Batch extends Doctrine_Collection {
|
||||
|
||||
/**
|
||||
* @param integer $batchSize batch size
|
||||
* @return boolean
|
||||
*/
|
||||
public function setBatchSize($batchSize) {
|
||||
$batchSize = (int) $batchSize;
|
||||
@ -38,15 +39,19 @@ class Doctrine_Collection_Batch extends Doctrine_Collection {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* returns the batch size of this collection
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getBatchSize() {
|
||||
return $this->batchSize;
|
||||
}
|
||||
/**
|
||||
* load load a specified element, by loading the batch the element is part of
|
||||
* @param Doctrine_Record $record data access object
|
||||
* @return boolean whether or not the load operation was successful
|
||||
* load
|
||||
* loads a specified element, by loading the batch the element is part of
|
||||
*
|
||||
* @param Doctrine_Record $record record to be loaded
|
||||
* @return boolean whether or not the load operation was successful
|
||||
*/
|
||||
public function load(Doctrine_Record $record) {
|
||||
if(empty($this->data))
|
||||
|
@ -22,4 +22,4 @@ class Doctrine_IndexGenerator {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
?>
|
||||
?>
|
||||
|
@ -419,8 +419,7 @@ class Doctrine_Query extends Doctrine_Access {
|
||||
|
||||
$array = $this->parseData($stmt);
|
||||
|
||||
$colls = array();
|
||||
|
||||
$colls = array();
|
||||
|
||||
foreach($array as $data) {
|
||||
/**
|
||||
@ -465,14 +464,30 @@ class Doctrine_Query extends Doctrine_Access {
|
||||
$coll->add($record);
|
||||
} else {
|
||||
$pointer = $this->joins[$name];
|
||||
|
||||
$last = $prev[$pointer]->getLast();
|
||||
|
||||
if( ! $last->hasReference($name)) {
|
||||
$prev[$name] = $this->getCollection($name);
|
||||
$last->initReference($prev[$name],$this->connectors[$name]);
|
||||
}
|
||||
$last->addReference($record);
|
||||
$fk = $this->tables[$pointer]->getForeignKey($this->tables[$pointer]->getAlias($name));
|
||||
|
||||
switch($fk->getType()):
|
||||
case Doctrine_Relation::ONE_COMPOSITE:
|
||||
case Doctrine_Relation::ONE_AGGREGATE:
|
||||
$last = $prev[$pointer]->getLast();
|
||||
|
||||
$last->rawSet($this->connectors[$name]->getLocal(), $record->getID());
|
||||
|
||||
$last->initSingleReference($record);
|
||||
|
||||
$prev[$name] = $record;
|
||||
break;
|
||||
default:
|
||||
// one-to-many relation or many-to-many relation
|
||||
$last = $prev[$pointer]->getLast();
|
||||
|
||||
if( ! $last->hasReference($name)) {
|
||||
$prev[$name] = $this->getCollection($name);
|
||||
$last->initReference($prev[$name],$this->connectors[$name]);
|
||||
}
|
||||
$last->addReference($record);
|
||||
endswitch;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,6 +83,10 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
|
||||
* @var integer $index this index is used for creating object identifiers
|
||||
*/
|
||||
private static $index = 1;
|
||||
/**
|
||||
* @var Doctrine_Null $nullObject a Doctrine_Null object used for SQL null value testing
|
||||
*/
|
||||
private static $nullObject;
|
||||
/**
|
||||
* @var integer $oid object identifier
|
||||
*/
|
||||
@ -157,6 +161,12 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
|
||||
$this->table->getRepository()->add($this);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* initNullObject
|
||||
*/
|
||||
public static function initNullObject() {
|
||||
self::$nullObject = new Doctrine_Null;
|
||||
}
|
||||
/**
|
||||
* setUp
|
||||
* implemented by child classes
|
||||
@ -402,7 +412,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
|
||||
if(is_array($this->data[$name])) {
|
||||
|
||||
// no use trying to load the data from database if the Doctrine_Record is not a proxy
|
||||
if($this->state == Doctrine_Record::STATE_PROXY) {
|
||||
if($this->state == Doctrine_Record::STATE_PROXY) {
|
||||
if( ! empty($this->collections)) {
|
||||
foreach($this->collections as $collection) {
|
||||
$collection->load($this);
|
||||
@ -582,11 +592,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
|
||||
$this->table->getSession()->save($this);
|
||||
|
||||
foreach($saveLater as $fk) {
|
||||
|
||||
$table = $fk->getTable();
|
||||
$foreign = $fk->getForeign();
|
||||
$local = $fk->getLocal();
|
||||
|
||||
$table = $fk->getTable();
|
||||
$alias = $this->table->getAlias($table->getComponentName());
|
||||
|
||||
if(isset($this->references[$alias])) {
|
||||
@ -836,6 +842,17 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
|
||||
final public function getID() {
|
||||
return $this->id;
|
||||
}
|
||||
/**
|
||||
* getLast
|
||||
* this method is used internally be Doctrine_Query
|
||||
* it is needed to provide compatibility between
|
||||
* records and collections
|
||||
*
|
||||
* @return Doctrine_Record
|
||||
*/
|
||||
public function getLast() {
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* hasRefence
|
||||
* @param string $name
|
||||
@ -845,8 +862,22 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
|
||||
return isset($this->references[$name]);
|
||||
}
|
||||
/**
|
||||
* initalizes a one-to-one relation
|
||||
*
|
||||
* @param Doctrine_Record $record
|
||||
* @param Doctrine_Relation $connector
|
||||
* @return void
|
||||
*/
|
||||
public function initSingleReference(Doctrine_Record $record) {
|
||||
$name = $this->table->getAlias($record->getTable()->getComponentName());
|
||||
$this->references[$name] = $record;
|
||||
}
|
||||
/**
|
||||
* initalizes a one-to-many / many-to-many relation
|
||||
*
|
||||
* @param Doctrine_Collection $coll
|
||||
* @param string $connectorField
|
||||
* @param Doctrine_Relation $connector
|
||||
* @return void
|
||||
*/
|
||||
public function initReference(Doctrine_Collection $coll, Doctrine_Relation $connector) {
|
||||
$name = $this->table->getAlias($coll->getTable()->getComponentName());
|
||||
|
@ -1,10 +1,8 @@
|
||||
<?php
|
||||
class Sensei_Group extends Doctrine_Record { }
|
||||
//class Sensei_Company extends Sensei_Group { }
|
||||
|
||||
class Sensei_Company extends Sensei_Group { }
|
||||
class Sensei_User extends Doctrine_Record { }
|
||||
//class Sensei_Customer extends Sensei_User { }
|
||||
|
||||
class Sensei_Customer extends Sensei_User { }
|
||||
class Sensei_Entity extends Doctrine_Record {
|
||||
/**
|
||||
* setTableDefinition
|
||||
@ -65,10 +63,7 @@ class Sensei_Session extends Doctrine_Record {
|
||||
$this->hasColumn("created","integer");
|
||||
}
|
||||
}
|
||||
|
||||
class Sensei_Exception extends Exception { }
|
||||
|
||||
|
||||
class Sensei extends Doctrine_Access {
|
||||
const ATTR_LIFESPAN = 0;
|
||||
/**
|
||||
|
@ -246,46 +246,7 @@ abstract class Doctrine_Session extends Doctrine_Configurable implements Countab
|
||||
public function create($name) {
|
||||
return $this->getTable($name)->create();
|
||||
}
|
||||
public function buildFlushTree2(array $tables) {
|
||||
$tree = array();
|
||||
foreach($tables as $table) {
|
||||
if( ! ($table instanceof Doctrine_Table))
|
||||
$table = $this->getTable($table);
|
||||
|
||||
$name = $table->getComponentName();
|
||||
$index = array_search($name,$tree);
|
||||
if($index === false)
|
||||
$tree[] = $name;
|
||||
|
||||
|
||||
foreach($table->getForeignKeys() as $rel) {
|
||||
$name = $rel->getTable()->getComponentName();
|
||||
$index = array_search($name,$tree);
|
||||
|
||||
if($rel instanceof Doctrine_ForeignKey) {
|
||||
if($index !== false)
|
||||
unset($tree[$index]);
|
||||
|
||||
$tree[] = $name;
|
||||
} elseif($rel instanceof Doctrine_LocalKey) {
|
||||
if($index !== false)
|
||||
unset($tree[$index]);
|
||||
|
||||
array_unshift($tree, $name);
|
||||
} elseif($rel instanceof Doctrine_Association) {
|
||||
$t = $rel->getAssociationFactory();
|
||||
$n = $t->getComponentName();
|
||||
$index = array_search($n,$tree);
|
||||
|
||||
if($index !== false)
|
||||
unset($tree[$index]);
|
||||
|
||||
$tree[] = $n;
|
||||
}
|
||||
}
|
||||
}
|
||||
return array_values($tree);
|
||||
}
|
||||
|
||||
/**
|
||||
* buildFlushTree
|
||||
@ -573,7 +534,6 @@ abstract class Doctrine_Session extends Doctrine_Configurable implements Countab
|
||||
$increment = true;
|
||||
}
|
||||
|
||||
|
||||
foreach($inserts as $k => $record) {
|
||||
$record->getTable()->getAttribute(Doctrine::ATTR_LISTENER)->onPreSave($record);
|
||||
// listen the onPreInsert event
|
||||
|
@ -81,6 +81,10 @@ class Doctrine_Table extends Doctrine_Configurable {
|
||||
* @var array $boundAliases bound relation aliases
|
||||
*/
|
||||
private $boundAliases = array();
|
||||
/**
|
||||
* @var integer $columnCount cached column count
|
||||
*/
|
||||
private $columnCount;
|
||||
|
||||
|
||||
/**
|
||||
@ -135,6 +139,8 @@ class Doctrine_Table extends Doctrine_Configurable {
|
||||
if(method_exists($record,"setTableDefinition")) {
|
||||
$record->setTableDefinition();
|
||||
|
||||
$this->columnCount = count($this->columns);
|
||||
|
||||
if(isset($this->columns)) {
|
||||
$method = new ReflectionMethod($this->name,"setTableDefinition");
|
||||
$class = $method->getDeclaringClass();
|
||||
@ -784,7 +790,7 @@ class Doctrine_Table extends Doctrine_Configurable {
|
||||
* @return integer
|
||||
*/
|
||||
final public function getColumnCount() {
|
||||
return count($this->columns);
|
||||
return $this->columnCount;
|
||||
}
|
||||
/**
|
||||
* returns all columns and their definitions
|
||||
|
@ -8,7 +8,7 @@ class Doctrine_Validator_NoSpace {
|
||||
* @return boolean
|
||||
*/
|
||||
public function validate(Doctrine_Record $record, $key, $value, $args) {
|
||||
if(preg_match("/[\s\r\t\n]/", $value))
|
||||
if(trim($value) === '')
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -7,6 +7,46 @@ class Doctrine_QueryTestCase extends Doctrine_UnitTestCase {
|
||||
$this->tables[] = "Forum_Thread";
|
||||
parent::prepareTables();
|
||||
}
|
||||
|
||||
public function testOneToOneRelationFetching() {
|
||||
|
||||
$count = $this->dbh->count();
|
||||
$users = $this->query->from("User-l:Email-i")->execute();
|
||||
$this->assertEqual(($count + 1), $this->dbh->count());
|
||||
$this->assertTrue($users instanceof Doctrine_Collection_Lazy);
|
||||
$count = $this->dbh->count();
|
||||
|
||||
foreach($users as $user) {
|
||||
// iterate through users and test that no additional queries are needed
|
||||
$user->Email->address;
|
||||
$this->assertEqual($count, $this->dbh->count());
|
||||
}
|
||||
$users[0]->Account->amount = 3000;
|
||||
$this->assertEqual($users[0]->Account->amount, 3000);
|
||||
$this->assertTrue($users[0]->Account instanceof Account);
|
||||
$this->assertEqual($users[0]->id, $users[0]->Account->entity_id);
|
||||
|
||||
$users[0]->Account->save();
|
||||
|
||||
$users[0]->refresh();
|
||||
$this->assertEqual($users[0]->Account->amount, 3000);
|
||||
$this->assertTrue($users[0]->Account instanceof Account);
|
||||
|
||||
$this->assertEqual($users[0]->id, $users[0]->Account->entity_id);
|
||||
|
||||
$this->assertEqual($users[0]->Account->getState(), Doctrine_Record::STATE_CLEAN);
|
||||
$users[0]->getTable()->clear();
|
||||
$users[0]->Account->getTable()->clear();
|
||||
|
||||
$count = $this->dbh->count();
|
||||
$users = $this->query->from("User-l:Account-i")->execute();
|
||||
$this->assertEqual(($count + 1), $this->dbh->count());
|
||||
$this->assertTrue($users instanceof Doctrine_Collection_Lazy);
|
||||
$this->assertEqual($users->count(), 1);
|
||||
|
||||
$this->assertEqual($users[0]->Account->amount,3000);
|
||||
}
|
||||
|
||||
public function testNotValidLazyPropertyFetching() {
|
||||
$q = new Doctrine_Query($this->session);
|
||||
|
||||
@ -49,7 +89,6 @@ class Doctrine_QueryTestCase extends Doctrine_UnitTestCase {
|
||||
$this->assertEqual($count + 1, count($this->dbh));
|
||||
}
|
||||
|
||||
|
||||
public function testQueryWithComplexAliases() {
|
||||
$q = new Doctrine_Query($this->session);
|
||||
|
||||
@ -209,7 +248,7 @@ class Doctrine_QueryTestCase extends Doctrine_UnitTestCase {
|
||||
$this->assertEqual($query->offset, 3);
|
||||
$this->assertEqual($coll->count(), 3);
|
||||
}
|
||||
public function testPrepared() {
|
||||
public function testPreparedQuery() {
|
||||
$coll = $this->session->query("FROM User WHERE User.name = :name", array(":name" => "zYne"));
|
||||
$this->assertEqual($coll->count(), 1);
|
||||
}
|
||||
@ -223,6 +262,25 @@ class Doctrine_QueryTestCase extends Doctrine_UnitTestCase {
|
||||
$this->assertEqual($users->count(),8);
|
||||
$this->assertTrue($users[0]->name == "Arnold Schwarzenegger");
|
||||
}
|
||||
public function testBatchFetching() {
|
||||
$query = new Doctrine_Query($this->session);
|
||||
$users = $query->query("FROM User-b");
|
||||
$this->assertEqual(trim($query->getQuery()),
|
||||
"SELECT entity.id AS User__id FROM entity WHERE (entity.type = 0)");
|
||||
|
||||
$this->assertEqual($users[0]->name, "zYne");
|
||||
$this->assertTrue($users instanceof Doctrine_Collection_Batch);
|
||||
}
|
||||
public function testLazyFetching() {
|
||||
$query = new Doctrine_Query($this->session);
|
||||
$users = $query->query("FROM User-l");
|
||||
$this->assertEqual(trim($query->getQuery()),
|
||||
"SELECT entity.id AS User__id FROM entity WHERE (entity.type = 0)");
|
||||
|
||||
$this->assertEqual($users[0]->name, "zYne");
|
||||
$this->assertTrue($users instanceof Doctrine_Collection_Lazy);
|
||||
|
||||
}
|
||||
|
||||
public function testQuery() {
|
||||
|
||||
@ -326,20 +384,8 @@ class Doctrine_QueryTestCase extends Doctrine_UnitTestCase {
|
||||
$count2 = $this->session->getDBH()->count();
|
||||
|
||||
|
||||
$users = $query->query("FROM User-b");
|
||||
$this->assertEqual(trim($query->getQuery()),
|
||||
"SELECT entity.id AS User__id FROM entity WHERE (entity.type = 0)");
|
||||
|
||||
$this->assertEqual($users[0]->name, "zYne");
|
||||
$this->assertTrue($users instanceof Doctrine_Collection_Batch);
|
||||
|
||||
|
||||
$users = $query->query("FROM User-l");
|
||||
$this->assertEqual(trim($query->getQuery()),
|
||||
"SELECT entity.id AS User__id FROM entity WHERE (entity.type = 0)");
|
||||
|
||||
$this->assertEqual($users[0]->name, "zYne");
|
||||
$this->assertTrue($users instanceof Doctrine_Collection_Lazy);
|
||||
|
||||
|
||||
//$this->clearCache();
|
||||
@ -403,5 +449,6 @@ class Doctrine_QueryTestCase extends Doctrine_UnitTestCase {
|
||||
//$this->assertTrue(isset($values['max']));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?php
|
||||
require_once("../classes/Doctrine.class.php");
|
||||
|
||||
Doctrine::loadAll();
|
||||
|
||||
class Sensei_UnitTestCase extends UnitTestCase {
|
||||
@ -13,6 +14,9 @@ class Sensei_UnitTestCase extends UnitTestCase {
|
||||
private $init = false;
|
||||
|
||||
public function init() {
|
||||
if(headers_sent())
|
||||
throw new Exception("'".ob_end_flush()."'");
|
||||
|
||||
$this->manager = Doctrine_Manager::getInstance();
|
||||
$this->manager->setAttribute(Doctrine::ATTR_CACHE, Doctrine::CACHE_NONE);
|
||||
|
||||
@ -40,7 +44,7 @@ class Sensei_UnitTestCase extends UnitTestCase {
|
||||
|
||||
$entity->loginname = "Chuck Norris";
|
||||
$entity->password = "toughguy";
|
||||
|
||||
|
||||
$entity->save();
|
||||
|
||||
$this->init = true;
|
||||
@ -109,6 +113,5 @@ class Sensei_UnitTestCase extends UnitTestCase {
|
||||
|
||||
$this->assertEqual($this->record->entity_id, 0);
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
|
@ -49,6 +49,7 @@ class Doctrine_UnitTestCase extends UnitTestCase {
|
||||
$this->manager->setAttribute(Doctrine::ATTR_LISTENER, $this->listener);
|
||||
}
|
||||
|
||||
$this->query = new Doctrine_Query($this->session);
|
||||
$this->prepareTables();
|
||||
$this->prepareData();
|
||||
}
|
||||
|
@ -207,4 +207,53 @@ class Forum_Thread extends Doctrine_Record {
|
||||
$this->ownsMany("Forum_Entry as Entries", "Forum_Entry.thread_id");
|
||||
}
|
||||
}
|
||||
class App extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("name", "string", 32);
|
||||
$this->hasColumn("user_id", "integer", 11);
|
||||
$this->hasColumn("app_category_id", "integer", 11);
|
||||
}
|
||||
public function setUp() {
|
||||
$this->hasOne("User","User.id");
|
||||
$this->hasMany("App_Category as Category","App_Category.id");
|
||||
}
|
||||
}
|
||||
|
||||
class App_User extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("first_name", "string", 32);
|
||||
$this->hasColumn("last_name", "string", 32);
|
||||
$this->hasColumn("email", "string", 128, "email");
|
||||
$this->hasColumn("username", "string", 16, "unique, nospace");
|
||||
$this->hasColumn("password", "string", 128, "notblank");
|
||||
$this->hasColumn("country", "string", 2, "country");
|
||||
$this->hasColumn("zipcode", "string", 9, "nospace");
|
||||
}
|
||||
public function setUp() {
|
||||
$this->hasMany("App","App.user_id");
|
||||
}
|
||||
}
|
||||
|
||||
class App_Category extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("name", "string", 32);
|
||||
$this->hasColumn("parent_id","integer");
|
||||
}
|
||||
public function setUp() {
|
||||
$this->hasMany("App","App.app_category_id");
|
||||
$this->hasMany("App_Category as Parent","App_Category.parent_id");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
$apps = $con->query("FROM App.Category");
|
||||
|
||||
if (!empty($apps))
|
||||
{
|
||||
foreach ($apps as $app)
|
||||
{
|
||||
print '<p>' . $app->Category[0]->name . ' => ' . $app->name . '</p>';
|
||||
}
|
||||
}
|
||||
*/
|
||||
?>
|
||||
|
@ -52,8 +52,6 @@ $test->addTestCase(new Doctrine_QueryTestCase());
|
||||
//$test->addTestCase(new Doctrine_Cache_SqliteTestCase());
|
||||
|
||||
|
||||
|
||||
|
||||
print "<pre>";
|
||||
$test->run(new HtmlReporter());
|
||||
$cache = Doctrine_Manager::getInstance()->getCurrentSession()->getCacheHandler();
|
||||
|
Loading…
x
Reference in New Issue
Block a user