Commit 00c44b7c authored by romanb's avatar romanb

[2.0] Implemented many-to-many SQL join construction, small test included.

parent 96f4d511
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
namespace Doctrine\DBAL; namespace Doctrine\DBAL;
use Doctrine\Common\DoctrineException;
use Doctrine\Common\EventManager; use Doctrine\Common\EventManager;
/** /**
...@@ -40,7 +41,7 @@ final class DriverManager ...@@ -40,7 +41,7 @@ final class DriverManager
'pdo_mysql' => 'Doctrine\DBAL\Driver\PDOMySql\Driver', 'pdo_mysql' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
'pdo_sqlite' => 'Doctrine\DBAL\Driver\PDOSqlite\Driver', 'pdo_sqlite' => 'Doctrine\DBAL\Driver\PDOSqlite\Driver',
'pdo_pgsql' => 'Doctrine\DBAL\Driver\PDOPgSql\Driver', 'pdo_pgsql' => 'Doctrine\DBAL\Driver\PDOPgSql\Driver',
'pdo_oracle' => 'Doctrine\DBAL\Driver\PDOOracle\Driver', 'pdo_oci' => 'Doctrine\DBAL\Driver\PDOOracle\Driver',
'pdo_mssql' => 'Doctrine\DBAL\Driver\PDOMsSql\Driver', 'pdo_mssql' => 'Doctrine\DBAL\Driver\PDOMsSql\Driver',
'pdo_firebird' => 'Doctrine\DBAL\Driver\PDOFirebird\Driver', 'pdo_firebird' => 'Doctrine\DBAL\Driver\PDOFirebird\Driver',
'pdo_informix' => 'Doctrine\DBAL\Driver\PDOInformix\Driver', 'pdo_informix' => 'Doctrine\DBAL\Driver\PDOInformix\Driver',
...@@ -107,7 +108,7 @@ final class DriverManager ...@@ -107,7 +108,7 @@ final class DriverManager
// check for existing pdo object // check for existing pdo object
if (isset($params['pdo']) && ! $params['pdo'] instanceof PDO) { if (isset($params['pdo']) && ! $params['pdo'] instanceof PDO) {
throw Exceptions\DBALException::invalidPDOInstance(); throw DoctrineException::invalidPDOInstance();
} else if (isset($params['pdo'])) { } else if (isset($params['pdo'])) {
$params['driver'] = $params['pdo']->getAttribute(PDO::ATTR_DRIVER_NAME); $params['driver'] = $params['pdo']->getAttribute(PDO::ATTR_DRIVER_NAME);
} else { } else {
...@@ -140,14 +141,14 @@ final class DriverManager ...@@ -140,14 +141,14 @@ final class DriverManager
// driver // driver
if ( ! isset($params['driver']) && ! isset($params['driverClass'])) { if ( ! isset($params['driver']) && ! isset($params['driverClass'])) {
throw Exceptions\DBALException::driverRequired(); throw DoctrineException::driverRequired();
} }
// check validity of parameters // check validity of parameters
// driver // driver
if ( isset($params['driver']) && ! isset(self::$_driverMap[$params['driver']])) { if ( isset($params['driver']) && ! isset(self::$_driverMap[$params['driver']])) {
throw Exceptions\DBALException::unknownDriver($params['driver']); throw DoctrineException::unknownDriver($params['driver']);
} }
} }
} }
\ No newline at end of file
...@@ -352,6 +352,61 @@ class OraclePlatform extends AbstractPlatform ...@@ -352,6 +352,61 @@ class OraclePlatform extends AbstractPlatform
} }
} }
/**
* @override
*/
public function getIntegerTypeDeclarationSql(array $field)
{
return 'NUMBER(10)';
}
/**
* @override
*/
public function getBigIntTypeDeclarationSql(array $field)
{
return 'NUMBER(20)';
}
/**
* @override
*/
public function getSmallIntTypeDeclarationSql(array $field)
{
return 'NUMBER(5)';
}
/**
* @override
*/
protected function _getCommonIntegerTypeDeclarationSql(array $columnDef)
{
return '';
}
/**
* Gets the SQL snippet used to declare a VARCHAR column on the Oracle platform.
*
* @params array $field
* @override
*/
public function getVarcharTypeDeclarationSql(array $field)
{
if ( ! isset($field['length'])) {
if (array_key_exists('default', $field)) {
$field['length'] = $this->getVarcharMaxLength();
} else {
$field['length'] = false;
}
}
$length = ($field['length'] <= $this->getVarcharMaxLength()) ? $field['length'] : false;
$fixed = (isset($field['fixed'])) ? $field['fixed'] : false;
return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(2000)')
: ($length ? 'VARCHAR2(' . $length . ')' : 'VARCHAR2(4000)');
}
/** /**
* Whether the platform prefers sequences for ID generation. * Whether the platform prefers sequences for ID generation.
* *
......
...@@ -277,6 +277,21 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -277,6 +277,21 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
//$this->_changed(); //$this->_changed();
} }
public function contains($element)
{
//TODO: Probably need to hit the database here...?
/*if ( ! $this->_initialized) {
return $this->_checkElementExistence($element);
}
return parent::contains($element);*/
return parent::contains($element);
}
private function _checkElementExistence($element)
{
}
/** /**
* INTERNAL: * INTERNAL:
* Sets a flag that indicates whether the collection is currently being hydrated. * Sets a flag that indicates whether the collection is currently being hydrated.
......
...@@ -99,7 +99,7 @@ class SqlWalker ...@@ -99,7 +99,7 @@ class SqlWalker
} else if ($discSql = $this->_generateDiscriminatorColumnConditionSql($this->_currentRootAlias)) { } else if ($discSql = $this->_generateDiscriminatorColumnConditionSql($this->_currentRootAlias)) {
$sql .= ' WHERE ' . $discSql; $sql .= ' WHERE ' . $discSql;
} }
//$sql .= $AST->getWhereClause() ? $this->walkWhereClause($AST->getWhereClause()) : '';
$sql .= $AST->getGroupByClause() ? $this->walkGroupByClause($AST->getGroupByClause()) : ''; $sql .= $AST->getGroupByClause() ? $this->walkGroupByClause($AST->getGroupByClause()) : '';
$sql .= $AST->getHavingClause() ? $this->walkHavingClause($AST->getHavingClause()) : ''; $sql .= $AST->getHavingClause() ? $this->walkHavingClause($AST->getHavingClause()) : '';
$sql .= $AST->getOrderByClause() ? $this->walkOrderByClause($AST->getOrderByClause()) : ''; $sql .= $AST->getOrderByClause() ? $this->walkOrderByClause($AST->getOrderByClause()) : '';
...@@ -247,27 +247,66 @@ class SqlWalker ...@@ -247,27 +247,66 @@ class SqlWalker
$targetTableAlias = $this->getSqlTableAlias($targetTableName); $targetTableAlias = $this->getSqlTableAlias($targetTableName);
$sourceTableAlias = $this->getSqlTableAlias($sourceQComp['metadata']->getTableName()); $sourceTableAlias = $this->getSqlTableAlias($sourceQComp['metadata']->getTableName());
$sql .= $targetTableName . ' ' . $targetTableAlias . ' ON '; // Ensure we got the owning side, since it has all mapping info
if ( ! $targetQComp['relation']->isOwningSide()) { if ( ! $targetQComp['relation']->isOwningSide()) {
$assoc = $targetQComp['metadata']->getAssociationMapping($targetQComp['relation']->getMappedByFieldName()); $assoc = $targetQComp['metadata']->getAssociationMapping($targetQComp['relation']->getMappedByFieldName());
} else { } else {
$assoc = $targetQComp['relation']; $assoc = $targetQComp['relation'];
} }
if ($targetQComp['relation']->isOneToOne() || $targetQComp['relation']->isOneToMany()) { if ($assoc->isOneToOne()/* || $assoc->isOneToMany()*/) {
$sql .= $targetTableName . ' ' . $targetTableAlias . ' ON ';
$joinColumns = $assoc->getSourceToTargetKeyColumns(); $joinColumns = $assoc->getSourceToTargetKeyColumns();
$first = true; $first = true;
foreach ($joinColumns as $sourceColumn => $targetColumn) { foreach ($joinColumns as $sourceColumn => $targetColumn) {
if ( ! $first) $sql .= ' AND '; if ( ! $first) {
$sql .= ' AND ';
} else {
$first = false;
}
if ($targetQComp['relation']->isOwningSide()) { if ($targetQComp['relation']->isOwningSide()) {
$sql .= "$sourceTableAlias.$sourceColumn = $targetTableAlias.$targetColumn"; $sql .= "$sourceTableAlias.$sourceColumn = $targetTableAlias.$targetColumn";
} else { } else {
$sql .= "$sourceTableAlias.$targetColumn = $targetTableAlias.$sourceColumn"; $sql .= "$sourceTableAlias.$targetColumn = $targetTableAlias.$sourceColumn";
} }
} }
} else { // ManyToMany } else if ($assoc->isManyToMany()) {
//TODO // Join relation table
$joinTable = $assoc->getJoinTable();
$joinTableAlias = $this->getSqlTableAlias($joinTable['name']);
$sql .= $joinTable['name'] . ' ' . $joinTableAlias . ' ON ';
if ($targetQComp['relation']->isOwningSide()) {
$sourceToRelationJoinColumns = $assoc->getSourceToRelationKeyColumns();
foreach ($sourceToRelationJoinColumns as $sourceColumn => $relationColumn) {
$sql .= "$sourceTableAlias.$sourceColumn = $joinTableAlias.$relationColumn";
}
} else {
$targetToRelationJoinColumns = $assoc->getTargetToRelationKeyColumns();
foreach ($targetToRelationJoinColumns as $targetColumn => $relationColumn) {
$sql .= "$sourceTableAlias.$targetColumn = $joinTableAlias.$relationColumn";
}
}
// Join target table
if ($joinType == AST\Join::JOIN_TYPE_LEFT || $joinType == AST\Join::JOIN_TYPE_LEFTOUTER) {
$sql .= ' LEFT JOIN ';
} else {
$sql .= ' INNER JOIN ';
}
$sql .= $targetTableName . ' ' . $targetTableAlias . ' ON ';
if ($targetQComp['relation']->isOwningSide()) {
$targetToRelationJoinColumns = $assoc->getTargetToRelationKeyColumns();
foreach ($targetToRelationJoinColumns as $targetColumn => $relationColumn) {
$sql .= "$targetTableAlias.$targetColumn = $joinTableAlias.$relationColumn";
}
} else {
$sourceToRelationJoinColumns = $assoc->getSourceToRelationKeyColumns();
foreach ($sourceToRelationJoinColumns as $sourceColumn => $relationColumn) {
$sql .= "$targetTableAlias.$sourceColumn = $joinTableAlias.$relationColumn";
}
}
} }
$discrSql = $this->_generateDiscriminatorColumnConditionSql($joinedDqlAlias); $discrSql = $this->_generateDiscriminatorColumnConditionSql($joinedDqlAlias);
......
...@@ -29,5 +29,17 @@ class CmsGroup ...@@ -29,5 +29,17 @@ class CmsGroup
* @DoctrineManyToMany(targetEntity="CmsUser", mappedBy="groups") * @DoctrineManyToMany(targetEntity="CmsUser", mappedBy="groups")
*/ */
public $users; public $users;
public function setName($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function addUser(CmsUser $user) {
$this->users[] = $user;
}
} }
...@@ -53,13 +53,26 @@ class CmsUser ...@@ -53,13 +53,26 @@ class CmsUser
*/ */
public function addPhonenumber(CmsPhonenumber $phone) { public function addPhonenumber(CmsPhonenumber $phone) {
$this->phonenumbers[] = $phone; $this->phonenumbers[] = $phone;
if ($phone->user !== $this) {
$phone->user = $this; $phone->user = $this;
} }
}
public function addArticle(CmsArticle $article) { public function addArticle(CmsArticle $article) {
$this->articles[] = $article; $this->articles[] = $article;
if ($article->user !== $this) {
$article->user = $this; $article->user = $this;
} }
}
public function addGroup(CmsGroup $group) {
$this->groups[] = $group;
$group->addUser($this);
}
public function getGroups() {
return $this->groups;
}
public function removePhonenumber($index) { public function removePhonenumber($index) {
if (isset($this->phonenumbers[$index])) { if (isset($this->phonenumbers[$index])) {
......
...@@ -222,7 +222,7 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase ...@@ -222,7 +222,7 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals('developer', $usersScalar[0]['u_status']); $this->assertEquals('developer', $usersScalar[0]['u_status']);
} }
public function testBasicInnerJoin() public function testBasicOneToManyInnerJoin()
{ {
$user = new CmsUser; $user = new CmsUser;
$user->name = 'Guilherme'; $user->name = 'Guilherme';
...@@ -238,7 +238,7 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase ...@@ -238,7 +238,7 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals(0, $users->count()); $this->assertEquals(0, $users->count());
} }
public function testBasicLeftJoin() public function testBasicOneToManyLeftJoin()
{ {
$user = new CmsUser; $user = new CmsUser;
$user->name = 'Guilherme'; $user->name = 'Guilherme';
...@@ -259,4 +259,37 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase ...@@ -259,4 +259,37 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals(0, $users[0]->phonenumbers->count()); $this->assertEquals(0, $users[0]->phonenumbers->count());
$this->assertNull($users[0]->articles); $this->assertNull($users[0]->articles);
} }
public function testBasicManyToManyJoin()
{
$user = new CmsUser;
$user->name = 'Guilherme';
$user->username = 'gblanco';
$user->status = 'developer';
$group1 = new CmsGroup;
$group1->setName('Doctrine Developers');
$user->addGroup($group1);
$this->_em->save($user);
$this->_em->save($group1);
$this->_em->flush();
$this->_em->clear();
$this->assertEquals(0, $this->_em->getUnitOfWork()->size());
$query = $this->_em->createQuery("select u, g from Doctrine\Tests\Models\CMS\CmsUser u join u.groups g");
$result = $query->getResultList();
$this->assertEquals(2, $this->_em->getUnitOfWork()->size());
$this->assertTrue($result[0] instanceof CmsUser);
$this->assertEquals('Guilherme', $result[0]->name);
$this->assertEquals(1, $result[0]->getGroups()->count());
$groups = $result[0]->getGroups();
$this->assertEquals('Doctrine Developers', $groups[0]->getName());
}
} }
\ No newline at end of file
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