1
0
Fork 0
mirror of synced 2025-04-03 13:23:37 +03:00

#1178 - reverting patch and keeping tests (rebase gone awry)

Also cleaning up `OrmFunctionalTestCase`
This commit is contained in:
Marco Pivetta 2015-01-16 23:33:02 +01:00
parent 5c1d1931b7
commit 445798ed46
4 changed files with 111 additions and 120 deletions

View file

@ -25,8 +25,6 @@ use Doctrine\ORM\Persisters\SqlExpressionVisitor;
use Doctrine\ORM\Persisters\SqlValueVisitor; use Doctrine\ORM\Persisters\SqlValueVisitor;
use Doctrine\ORM\PersistentCollection; use Doctrine\ORM\PersistentCollection;
use Doctrine\ORM\Query; use Doctrine\ORM\Query;
use Doctrine\ORM\UnitOfWork;
use Doctrine\ORM\Utility\PersisterHelper;
/** /**
* Persister for many-to-many collections. * Persister for many-to-many collections.
@ -376,20 +374,22 @@ class ManyToManyPersister extends AbstractCollectionPersister
$mapping = $collection->getMapping(); $mapping = $collection->getMapping();
$identifier = $this->uow->getEntityIdentifier($collection->getOwner()); $identifier = $this->uow->getEntityIdentifier($collection->getOwner());
$sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']); // Optimization for single column identifier
$params = array(); if (count($mapping['relationToSourceKeyColumns']) === 1) {
$types = array(); return array(reset($identifier));
foreach ($mapping['relationToSourceKeyColumns'] as $columnName => $refColumnName) {
$field = isset($sourceClass->fieldNames[$refColumnName])
? $sourceClass->fieldNames[$refColumnName]
: $sourceClass->getFieldForColumn($columnName);
$params[] = $identifier[$field];
$types[] = PersisterHelper::getTypeOfField($field, $sourceClass, $this->em);
} }
return array($params, $types); // Composite identifier
$sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']);
$params = array();
foreach ($mapping['relationToSourceKeyColumns'] as $columnName => $refColumnName) {
$params[] = isset($sourceClass->fieldNames[$refColumnName])
? $identifier[$sourceClass->fieldNames[$refColumnName]]
: $identifier[$sourceClass->getFieldForColumn($columnName)];
}
return $params;
} }
/** /**
@ -534,28 +534,24 @@ class ManyToManyPersister extends AbstractCollectionPersister
$indexBy = $mapping['indexBy']; $indexBy = $mapping['indexBy'];
$id = $this->uow->getEntityIdentifier($collection->getOwner()); $id = $this->uow->getEntityIdentifier($collection->getOwner());
$sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']); $targetEntity = $this->em->getClassMetadata($mapping['targetEntity']);
$targetClass = $this->em->getClassMetadata($mapping['targetEntity']);
if ( ! $mapping['isOwningSide']) { if (! $mapping['isOwningSide']) {
$associationSourceClass = $this->em->getClassMetadata($mapping['targetEntity']); $associationSourceClass = $this->em->getClassMetadata($mapping['targetEntity']);
$mapping = $associationSourceClass->associationMappings[$mapping['mappedBy']]; $mapping = $associationSourceClass->associationMappings[$mapping['mappedBy']];
$joinColumns = $mapping['joinTable']['joinColumns']; $joinColumns = $mapping['joinTable']['joinColumns'];
$sourceRelationMode = 'relationToTargetKeyColumns'; $relationMode = 'relationToTargetKeyColumns';
$targetRelationMode = 'relationToSourceKeyColumns';
} else { } else {
$associationSourceClass = $this->em->getClassMetadata($mapping['sourceEntity']);
$joinColumns = $mapping['joinTable']['inverseJoinColumns']; $joinColumns = $mapping['joinTable']['inverseJoinColumns'];
$sourceRelationMode = 'relationToSourceKeyColumns'; $associationSourceClass = $this->em->getClassMetadata($mapping['sourceEntity']);
$targetRelationMode = 'relationToTargetKeyColumns'; $relationMode = 'relationToSourceKeyColumns';
} }
$quotedJoinTable = $this->quoteStrategy->getJoinTableName($mapping, $associationSourceClass, $this->platform) . ' t'; $quotedJoinTable = $this->quoteStrategy->getJoinTableName($mapping, $associationSourceClass, $this->platform). ' t';
$whereClauses = array(); $whereClauses = array();
$params = array(); $params = array();
$types = array();
$joinNeeded = ! in_array($indexBy, $targetClass->identifier); $joinNeeded = !in_array($indexBy, $targetEntity->identifier);
if ($joinNeeded) { // extra join needed if indexBy is not a @id if ($joinNeeded) { // extra join needed if indexBy is not a @id
$joinConditions = array(); $joinConditions = array();
@ -563,25 +559,21 @@ class ManyToManyPersister extends AbstractCollectionPersister
foreach ($joinColumns as $joinTableColumn) { foreach ($joinColumns as $joinTableColumn) {
$joinConditions[] = 't.' . $joinTableColumn['name'] . ' = tr.' . $joinTableColumn['referencedColumnName']; $joinConditions[] = 't.' . $joinTableColumn['name'] . ' = tr.' . $joinTableColumn['referencedColumnName'];
} }
$tableName = $this->quoteStrategy->getTableName($targetClass, $this->platform); $tableName = $this->quoteStrategy->getTableName($targetEntity, $this->platform);
$quotedJoinTable .= ' JOIN ' . $tableName . ' tr ON ' . implode(' AND ', $joinConditions); $quotedJoinTable .= ' JOIN ' . $tableName . ' tr ON ' . implode(' AND ', $joinConditions);
$columnName = $targetClass->getColumnName($indexBy);
$whereClauses[] = 'tr.' . $columnName . ' = ?'; $whereClauses[] = 'tr.' . $targetEntity->getColumnName($indexBy) . ' = ?';
$params[] = $key; $params[] = $key;
$types[] = PersisterHelper::getTypeOfColumn($columnName, $targetClass, $this->em);
} }
foreach ($mapping['joinTableColumns'] as $joinTableColumn) { foreach ($mapping['joinTableColumns'] as $joinTableColumn) {
if (isset($mapping[$sourceRelationMode][$joinTableColumn])) { if (isset($mapping[$relationMode][$joinTableColumn])) {
$column = $mapping[$sourceRelationMode][$joinTableColumn];
$whereClauses[] = 't.' . $joinTableColumn . ' = ?'; $whereClauses[] = 't.' . $joinTableColumn . ' = ?';
$params[] = $id[$targetEntity->getFieldForColumn($mapping[$relationMode][$joinTableColumn])]; $params[] = $id[$targetEntity->getFieldForColumn($mapping[$relationMode][$joinTableColumn])];
} elseif (!$joinNeeded) { } elseif (!$joinNeeded) {
$whereClauses[] = 't.' . $joinTableColumn . ' = ?'; $whereClauses[] = 't.' . $joinTableColumn . ' = ?';
$params[] = $key; $params[] = $key;
$types[] = PersisterHelper::getTypeOfColumn($column, $targetClass, $this->em);
} }
} }
@ -594,7 +586,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
} }
} }
return array($quotedJoinTable, $whereClauses, $params, $types); return array($quotedJoinTable, $whereClauses, $params);
} }
/** /**
@ -626,7 +618,6 @@ class ManyToManyPersister extends AbstractCollectionPersister
$quotedJoinTable = $this->quoteStrategy->getJoinTableName($mapping, $sourceClass, $this->platform); $quotedJoinTable = $this->quoteStrategy->getJoinTableName($mapping, $sourceClass, $this->platform);
$whereClauses = array(); $whereClauses = array();
$params = array(); $params = array();
$types = array();
foreach ($mapping['joinTableColumns'] as $joinTableColumn) { foreach ($mapping['joinTableColumns'] as $joinTableColumn) {
$whereClauses[] = ($addFilters ? 't.' : '') . $joinTableColumn . ' = ?'; $whereClauses[] = ($addFilters ? 't.' : '') . $joinTableColumn . ' = ?';
@ -634,11 +625,6 @@ class ManyToManyPersister extends AbstractCollectionPersister
if (isset($mapping['relationToTargetKeyColumns'][$joinTableColumn])) { if (isset($mapping['relationToTargetKeyColumns'][$joinTableColumn])) {
$params[] = $targetId[$targetClass->getFieldForColumn($mapping['relationToTargetKeyColumns'][$joinTableColumn])]; $params[] = $targetId[$targetClass->getFieldForColumn($mapping['relationToTargetKeyColumns'][$joinTableColumn])];
$params[] = $targetClass->containsForeignIdentifier
? $targetId[$targetClass->getFieldForColumn($column)]
: $targetId[$targetClass->fieldNames[$column]];
$types[] = PersisterHelper::getTypeOfColumn($column, $targetClass, $this->em);
continue; continue;
} }

View file

@ -710,7 +710,6 @@ class BasicEntityPersister implements EntityPersister
{ {
$sql = $this->getSelectSQL($criteria, $assoc, $lockMode, $limit, null, $orderBy); $sql = $this->getSelectSQL($criteria, $assoc, $lockMode, $limit, null, $orderBy);
list($params, $types) = $this->expandParameters($criteria); list($params, $types) = $this->expandParameters($criteria);
$stmt = $this->conn->executeQuery($sql, $params, $types); $stmt = $this->conn->executeQuery($sql, $params, $types);
if ($entity !== null) { if ($entity !== null) {
@ -863,12 +862,12 @@ class BasicEntityPersister implements EntityPersister
list($params, $types) = $valueVisitor->getParamsAndTypes(); list($params, $types) = $valueVisitor->getParamsAndTypes();
foreach ($params as $param) { foreach ($params as $param) {
$sqlParams[] = PersisterHelper::getValue($param, $this->em); $sqlParams[] = $this->getValue($param);
} }
foreach ($types as $type) { foreach ($types as $type) {
list($field, $value) = $type; list($field, $value) = $type;
$sqlTypes[] = $this->getType($field, $value, $this->class); $sqlTypes[] = $this->getType($field, $value);
} }
return array($sqlParams, $sqlTypes); return array($sqlParams, $sqlTypes);
@ -966,12 +965,11 @@ class BasicEntityPersister implements EntityPersister
*/ */
private function getManyToManyStatement(array $assoc, $sourceEntity, $offset = null, $limit = null) private function getManyToManyStatement(array $assoc, $sourceEntity, $offset = null, $limit = null)
{ {
$criteria = array(); $sourceClass = $this->em->getClassMetadata($assoc['sourceEntity']);
$parameters = array(); $class = $sourceClass;
$association = $assoc;
$criteria = array();
$sourceClass = $this->em->getClassMetadata($assoc['sourceEntity']);
$class = $sourceClass;
$association = $assoc;
if ( ! $assoc['isOwningSide']) { if ( ! $assoc['isOwningSide']) {
$class = $this->em->getClassMetadata($assoc['targetEntity']); $class = $this->em->getClassMetadata($assoc['targetEntity']);
@ -986,8 +984,8 @@ class BasicEntityPersister implements EntityPersister
foreach ($joinColumns as $joinColumn) { foreach ($joinColumns as $joinColumn) {
$sourceKeyColumn = $joinColumn['referencedColumnName']; $sourceKeyColumn = $joinColumn['referencedColumnName'];
$quotedKeyColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); $quotedKeyColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform);
switch (true) { switch (true) {
case $sourceClass->containsForeignIdentifier: case $sourceClass->containsForeignIdentifier:
@ -1014,11 +1012,10 @@ class BasicEntityPersister implements EntityPersister
} }
$criteria[$quotedJoinTable . '.' . $quotedKeyColumn] = $value; $criteria[$quotedJoinTable . '.' . $quotedKeyColumn] = $value;
$parameters[] = array('value' => $value, 'field' => $field, 'class' => $sourceClass);
} }
$sql = $this->getSelectSQL($criteria, $assoc, null, $limit, $offset); $sql = $this->getSelectSQL($criteria, $assoc, null, $limit, $offset);
list($params, $types) = $this->expandToManyParameters($parameters); list($params, $types) = $this->expandParameters($criteria);
return $this->conn->executeQuery($sql, $params, $types); return $this->conn->executeQuery($sql, $params, $types);
} }
@ -1306,13 +1303,16 @@ class BasicEntityPersister implements EntityPersister
$targetClass = $this->em->getClassMetadata($assoc['targetEntity']); $targetClass = $this->em->getClassMetadata($assoc['targetEntity']);
foreach ($assoc['joinColumns'] as $joinColumn) { foreach ($assoc['joinColumns'] as $joinColumn) {
$type = null;
$isIdentifier = isset($assoc['id']) && $assoc['id'] === true; $isIdentifier = isset($assoc['id']) && $assoc['id'] === true;
$quotedColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform); $quotedColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform);
$resultColumnName = $this->getSQLColumnAlias($joinColumn['name']); $resultColumnName = $this->getSQLColumnAlias($joinColumn['name']);
$columnList[] = $this->getSQLTableAlias($class->name, ($alias == 'r' ? '' : $alias) ) $columnList[] = $this->getSQLTableAlias($class->name, ($alias == 'r' ? '' : $alias) )
. '.' . $quotedColumn . ' AS ' . $resultColumnName; . '.' . $quotedColumn . ' AS ' . $resultColumnName;
$type = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em); if (isset($targetClass->fieldNames[$joinColumn['referencedColumnName']])) {
$type = $targetClass->fieldMappings[$targetClass->fieldNames[$joinColumn['referencedColumnName']]]['type'];
}
$this->rsm->addMetaResult($alias, $resultColumnName, $quotedColumn, $isIdentifier, $type); $this->rsm->addMetaResult($alias, $resultColumnName, $quotedColumn, $isIdentifier, $type);
} }
@ -1713,9 +1713,7 @@ class BasicEntityPersister implements EntityPersister
*/ */
private function getOneToManyStatement(array $assoc, $sourceEntity, $offset = null, $limit = null) private function getOneToManyStatement(array $assoc, $sourceEntity, $offset = null, $limit = null)
{ {
$criteria = array(); $criteria = array();
$parameters = array();
$owningAssoc = $this->class->associationMappings[$assoc['mappedBy']]; $owningAssoc = $this->class->associationMappings[$assoc['mappedBy']];
$sourceClass = $this->em->getClassMetadata($assoc['sourceEntity']); $sourceClass = $this->em->getClassMetadata($assoc['sourceEntity']);
@ -1732,20 +1730,15 @@ class BasicEntityPersister implements EntityPersister
} }
$criteria[$tableAlias . "." . $targetKeyColumn] = $value; $criteria[$tableAlias . "." . $targetKeyColumn] = $value;
$parameters[] = array('value' => $value, 'field' => $field, 'class' => $sourceClass);
continue; continue;
} }
$field = $sourceClass->fieldNames[$sourceKeyColumn]; $criteria[$tableAlias . "." . $targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
$criteria[$tableAlias . "." . $targetKeyColumn] = $value;
$parameters[] = array('value' => $value, 'field' => $field, 'class' => $sourceClass);
} }
$sql = $this->getSelectSQL($criteria, $assoc, null, $limit, $offset); $sql = $this->getSelectSQL($criteria, $assoc, null, $limit, $offset);
list($params, $types) = $this->expandToManyParameters($parameters); list($params, $types) = $this->expandParameters($criteria);
return $this->conn->executeQuery($sql, $params, $types); return $this->conn->executeQuery($sql, $params, $types);
} }
@ -1763,53 +1756,25 @@ class BasicEntityPersister implements EntityPersister
continue; // skip null values. continue; // skip null values.
} }
$types[] = $this->getType($field, $value, $this->class); $types[] = $this->getType($field, $value);
$params[] = PersisterHelper::getValue($value, $this->em); $params[] = $this->getValue($value);
} }
return array($params, $types); return array($params, $types);
} }
/** /**
* Expands the parameters from the given criteria and use the correct binding types if found, * Infers field type to be used by parameter type casting.
* specialized for OneToMany or ManyToMany associations.
* *
* @param array $criteria * @param string $field
* @param mixed $value
* *
* @return array * @return integer
*/
private function expandToManyParameters($criteria)
{
$params = array();
$types = array();
foreach ($criteria as $criterion) {
if ($criterion['value'] === null) {
continue; // skip null values.
}
$types[] = $this->getType($criterion['field'], $criterion['value'], $criterion['class']);
$params[] = PersisterHelper::getValue($criterion['value'], $this->em);
}
return array($params, $types);
}
/**
* Infers the binding type of a field by parameter type casting.
*
* @param string $fieldName
* @param mixed $value
* @param ClassMetadata|null $class
*
* @return int|string|null
* *
* @throws \Doctrine\ORM\Query\QueryException * @throws \Doctrine\ORM\Query\QueryException
*/ */
private function getType($fieldName, $value, ClassMetadata $class) private function getType($field, $value)
{ {
$type = Helper::getTypeOfField($fieldName, $class, $this->em);
switch (true) { switch (true) {
case (isset($this->class->fieldMappings[$field])): case (isset($this->class->fieldMappings[$field])):
$type = $this->class->fieldMappings[$field]['type']; $type = $this->class->fieldMappings[$field]['type'];
@ -1837,8 +1802,8 @@ class BasicEntityPersister implements EntityPersister
break; break;
case (isset($class->associationMappings[$field])): case (isset($this->class->associationMappings[$field])):
$assoc = $class->associationMappings[$field]; $assoc = $this->class->associationMappings[$field];
if (count($assoc['sourceToTargetKeyColumns']) > 1) { if (count($assoc['sourceToTargetKeyColumns']) > 1) {
throw Query\QueryException::associationPathCompositeKeyNotSupported(); throw Query\QueryException::associationPathCompositeKeyNotSupported();
@ -1866,6 +1831,44 @@ class BasicEntityPersister implements EntityPersister
return $type; return $type;
} }
/**
* Retrieves parameter value.
*
* @param mixed $value
*
* @return mixed
*/
private function getValue($value)
{
if ( ! is_array($value)) {
return $this->getIndividualValue($value);
}
$newValue = array();
foreach ($value as $itemValue) {
$newValue[] = $this->getIndividualValue($itemValue);
}
return $newValue;
}
/**
* Retrieves an individual parameter value.
*
* @param mixed $value
*
* @return mixed
*/
private function getIndividualValue($value)
{
if ( ! is_object($value) || ! $this->em->getMetadataFactory()->hasMetadataFor(ClassUtils::getClass($value))) {
return $value;
}
return $this->em->getUnitOfWork()->getSingleIdentifierValue($value);
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
@ -1883,21 +1886,20 @@ class BasicEntityPersister implements EntityPersister
. $this->getLockTablesSql(null) . $this->getLockTablesSql(null)
. ' WHERE ' . $this->getSelectConditionSQL($criteria); . ' WHERE ' . $this->getSelectConditionSQL($criteria);
list($params, $types) = $this->expandParameters($criteria); list($params) = $this->expandParameters($criteria);
if (null !== $extraConditions) { if (null !== $extraConditions) {
$sql .= ' AND ' . $this->getSelectConditionCriteriaSQL($extraConditions); $sql .= ' AND ' . $this->getSelectConditionCriteriaSQL($extraConditions);
list($extraParams, $extraTypes) = $this->expandCriteriaParameters($extraConditions); list($criteriaParams, $values) = $this->expandCriteriaParameters($extraConditions);
$params = array_merge($params, $extraParams); $params = array_merge($params, $criteriaParams);
$types = array_merge($types, $extraTypes);
} }
if ($filterSql = $this->generateFilterConditionSQL($this->class, $alias)) { if ($filterSql = $this->generateFilterConditionSQL($this->class, $alias)) {
$sql .= ' AND ' . $filterSql; $sql .= ' AND ' . $filterSql;
} }
return (bool) $this->conn->fetchColumn($sql, $params, 0, $types); return (bool) $this->conn->fetchColumn($sql, $params);
} }
/** /**
@ -1920,9 +1922,7 @@ class BasicEntityPersister implements EntityPersister
} }
/** /**
* @param string $columnName * {@inheritdoc}
*
* @return string
*/ */
public function getSQLColumnAlias($columnName) public function getSQLColumnAlias($columnName)
{ {

View file

@ -19,16 +19,6 @@ class SchemaValidatorTest extends \Doctrine\Tests\OrmFunctionalTestCase
if ($modelSet == "customtype") { if ($modelSet == "customtype") {
continue; continue;
} }
// DDC-3380: Register DBAL type for these modelsets
if (substr($modelSet, 0, 4) == 'vct_') {
if (DBALType::hasType('rot13')) {
DBALType::overrideType('rot13', 'Doctrine\Tests\DbalTypes\Rot13Type');
} else {
DBALType::addType('rot13', 'Doctrine\Tests\DbalTypes\Rot13Type');
}
}
$modelSets[] = array($modelSet); $modelSets[] = array($modelSet);
} }
return $modelSets; return $modelSets;

View file

@ -2,6 +2,7 @@
namespace Doctrine\Tests; namespace Doctrine\Tests;
use Doctrine\DBAL\Types\Type;
use Doctrine\Tests\EventListener\CacheMetadataListener; use Doctrine\Tests\EventListener\CacheMetadataListener;
use Doctrine\ORM\Cache\Logging\StatisticsCacheLogger; use Doctrine\ORM\Cache\Logging\StatisticsCacheLogger;
use Doctrine\ORM\Cache\DefaultCacheFactory; use Doctrine\ORM\Cache\DefaultCacheFactory;
@ -504,6 +505,8 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
*/ */
protected function setUp() protected function setUp()
{ {
$this->setUpDBALTypes();
$forceCreateTables = false; $forceCreateTables = false;
if ( ! isset(static::$_sharedConn)) { if ( ! isset(static::$_sharedConn)) {
@ -691,4 +694,16 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
{ {
return count($this->_sqlLoggerStack->queries); return count($this->_sqlLoggerStack->queries);
} }
/**
* Configures DBAL types required in tests
*/
protected function setUpDBALTypes()
{
if (Type::hasType('rot13')) {
Type::overrideType('rot13', 'Doctrine\Tests\DbalTypes\Rot13Type');
} else {
Type::addType('rot13', 'Doctrine\Tests\DbalTypes\Rot13Type');
}
}
} }