[2.0] Implemented many-to-many SQL join construction, small test included.
This commit is contained in:
parent
96f4d511e8
commit
00c44b7c41
@ -21,6 +21,7 @@
|
||||
|
||||
namespace Doctrine\DBAL;
|
||||
|
||||
use Doctrine\Common\DoctrineException;
|
||||
use Doctrine\Common\EventManager;
|
||||
|
||||
/**
|
||||
@ -40,7 +41,7 @@ final class DriverManager
|
||||
'pdo_mysql' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
|
||||
'pdo_sqlite' => 'Doctrine\DBAL\Driver\PDOSqlite\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_firebird' => 'Doctrine\DBAL\Driver\PDOFirebird\Driver',
|
||||
'pdo_informix' => 'Doctrine\DBAL\Driver\PDOInformix\Driver',
|
||||
@ -107,7 +108,7 @@ final class DriverManager
|
||||
|
||||
// check for existing pdo object
|
||||
if (isset($params['pdo']) && ! $params['pdo'] instanceof PDO) {
|
||||
throw Exceptions\DBALException::invalidPDOInstance();
|
||||
throw DoctrineException::invalidPDOInstance();
|
||||
} else if (isset($params['pdo'])) {
|
||||
$params['driver'] = $params['pdo']->getAttribute(PDO::ATTR_DRIVER_NAME);
|
||||
} else {
|
||||
@ -140,14 +141,14 @@ final class DriverManager
|
||||
|
||||
// driver
|
||||
if ( ! isset($params['driver']) && ! isset($params['driverClass'])) {
|
||||
throw Exceptions\DBALException::driverRequired();
|
||||
throw DoctrineException::driverRequired();
|
||||
}
|
||||
|
||||
// check validity of parameters
|
||||
|
||||
// driver
|
||||
if ( isset($params['driver']) && ! isset(self::$_driverMap[$params['driver']])) {
|
||||
throw Exceptions\DBALException::unknownDriver($params['driver']);
|
||||
throw DoctrineException::unknownDriver($params['driver']);
|
||||
}
|
||||
}
|
||||
}
|
@ -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.
|
||||
*
|
||||
|
@ -276,6 +276,21 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
|
||||
//TODO: Register collection as dirty with the UoW if necessary
|
||||
//$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:
|
||||
|
@ -99,7 +99,7 @@ class SqlWalker
|
||||
} else if ($discSql = $this->_generateDiscriminatorColumnConditionSql($this->_currentRootAlias)) {
|
||||
$sql .= ' WHERE ' . $discSql;
|
||||
}
|
||||
//$sql .= $AST->getWhereClause() ? $this->walkWhereClause($AST->getWhereClause()) : '';
|
||||
|
||||
$sql .= $AST->getGroupByClause() ? $this->walkGroupByClause($AST->getGroupByClause()) : '';
|
||||
$sql .= $AST->getHavingClause() ? $this->walkHavingClause($AST->getHavingClause()) : '';
|
||||
$sql .= $AST->getOrderByClause() ? $this->walkOrderByClause($AST->getOrderByClause()) : '';
|
||||
@ -247,27 +247,66 @@ class SqlWalker
|
||||
$targetTableAlias = $this->getSqlTableAlias($targetTableName);
|
||||
$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()) {
|
||||
$assoc = $targetQComp['metadata']->getAssociationMapping($targetQComp['relation']->getMappedByFieldName());
|
||||
} else {
|
||||
$assoc = $targetQComp['relation'];
|
||||
}
|
||||
|
||||
if ($targetQComp['relation']->isOneToOne() || $targetQComp['relation']->isOneToMany()) {
|
||||
if ($assoc->isOneToOne()/* || $assoc->isOneToMany()*/) {
|
||||
$sql .= $targetTableName . ' ' . $targetTableAlias . ' ON ';
|
||||
$joinColumns = $assoc->getSourceToTargetKeyColumns();
|
||||
$first = true;
|
||||
foreach ($joinColumns as $sourceColumn => $targetColumn) {
|
||||
if ( ! $first) $sql .= ' AND ';
|
||||
if ( ! $first) {
|
||||
$sql .= ' AND ';
|
||||
} else {
|
||||
$first = false;
|
||||
}
|
||||
if ($targetQComp['relation']->isOwningSide()) {
|
||||
$sql .= "$sourceTableAlias.$sourceColumn = $targetTableAlias.$targetColumn";
|
||||
} else {
|
||||
$sql .= "$sourceTableAlias.$targetColumn = $targetTableAlias.$sourceColumn";
|
||||
}
|
||||
}
|
||||
} else { // ManyToMany
|
||||
//TODO
|
||||
} else if ($assoc->isManyToMany()) {
|
||||
// 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);
|
||||
|
@ -29,5 +29,17 @@ class CmsGroup
|
||||
* @DoctrineManyToMany(targetEntity="CmsUser", mappedBy="groups")
|
||||
*/
|
||||
public $users;
|
||||
|
||||
public function setName($name) {
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function getName() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function addUser(CmsUser $user) {
|
||||
$this->users[] = $user;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,12 +53,25 @@ class CmsUser
|
||||
*/
|
||||
public function addPhonenumber(CmsPhonenumber $phone) {
|
||||
$this->phonenumbers[] = $phone;
|
||||
$phone->user = $this;
|
||||
if ($phone->user !== $this) {
|
||||
$phone->user = $this;
|
||||
}
|
||||
}
|
||||
|
||||
public function addArticle(CmsArticle $article) {
|
||||
$this->articles[] = $article;
|
||||
$article->user = $this;
|
||||
if ($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) {
|
||||
|
@ -222,7 +222,7 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertEquals('developer', $usersScalar[0]['u_status']);
|
||||
}
|
||||
|
||||
public function testBasicInnerJoin()
|
||||
public function testBasicOneToManyInnerJoin()
|
||||
{
|
||||
$user = new CmsUser;
|
||||
$user->name = 'Guilherme';
|
||||
@ -238,7 +238,7 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertEquals(0, $users->count());
|
||||
}
|
||||
|
||||
public function testBasicLeftJoin()
|
||||
public function testBasicOneToManyLeftJoin()
|
||||
{
|
||||
$user = new CmsUser;
|
||||
$user->name = 'Guilherme';
|
||||
@ -259,4 +259,37 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertEquals(0, $users[0]->phonenumbers->count());
|
||||
$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());
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user