1
0
mirror of synced 2025-01-18 06:21:40 +03:00

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

This commit is contained in:
romanb 2009-05-07 13:54:01 +00:00
parent 96f4d511e8
commit 00c44b7c41
7 changed files with 183 additions and 15 deletions

View File

@ -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']);
}
}
}

View File

@ -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.
*

View File

@ -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:

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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) {

View File

@ -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());
}
}