Ejemplo n.º 1
1
 /**
  * Gather columns and fk constraints that are required for one part of relationship.
  *
  * @param array $joinColumns
  * @param \Doctrine\DBAL\Schema\Table $theJoinTable
  * @param ClassMetadata $class
  * @param array $mapping
  * @param array $primaryKeyColumns
  * @param array $uniqueConstraints
  */
 private function _gatherRelationJoinColumns($joinColumns, $theJoinTable, $class, $mapping, &$primaryKeyColumns, &$uniqueConstraints)
 {
     $localColumns = array();
     $foreignColumns = array();
     $fkOptions = array();
     $foreignTableName = $this->quoteStrategy->getTableName($class, $this->platform);
     foreach ($joinColumns as $joinColumn) {
         list($definingClass, $referencedFieldName) = $this->getDefiningClass($class, $joinColumn['referencedColumnName']);
         if (!$definingClass) {
             throw new \Doctrine\ORM\ORMException("Column name `" . $joinColumn['referencedColumnName'] . "` referenced for relation from " . $mapping['sourceEntity'] . " towards " . $mapping['targetEntity'] . " does not exist.");
         }
         $quotedColumnName = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform);
         $quotedRefColumnName = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $class, $this->platform);
         $primaryKeyColumns[] = $quotedColumnName;
         $localColumns[] = $quotedColumnName;
         $foreignColumns[] = $quotedRefColumnName;
         if (!$theJoinTable->hasColumn($quotedColumnName)) {
             // Only add the column to the table if it does not exist already.
             // It might exist already if the foreign key is mapped into a regular
             // property as well.
             $fieldMapping = $definingClass->getFieldMapping($referencedFieldName);
             $columnDef = null;
             if (isset($joinColumn['columnDefinition'])) {
                 $columnDef = $joinColumn['columnDefinition'];
             } else {
                 if (isset($fieldMapping['columnDefinition'])) {
                     $columnDef = $fieldMapping['columnDefinition'];
                 }
             }
             $columnOptions = array('notnull' => false, 'columnDefinition' => $columnDef);
             if (isset($joinColumn['nullable'])) {
                 $columnOptions['notnull'] = !$joinColumn['nullable'];
             }
             if (isset($fieldMapping['options'])) {
                 $columnOptions['options'] = $fieldMapping['options'];
             }
             if ($fieldMapping['type'] == "string" && isset($fieldMapping['length'])) {
                 $columnOptions['length'] = $fieldMapping['length'];
             } else {
                 if ($fieldMapping['type'] == "decimal") {
                     $columnOptions['scale'] = $fieldMapping['scale'];
                     $columnOptions['precision'] = $fieldMapping['precision'];
                 }
             }
             $theJoinTable->addColumn($quotedColumnName, $fieldMapping['type'], $columnOptions);
         }
         if (isset($joinColumn['unique']) && $joinColumn['unique'] == true) {
             $uniqueConstraints[] = array('columns' => array($quotedColumnName));
         }
         if (isset($joinColumn['onDelete'])) {
             $fkOptions['onDelete'] = $joinColumn['onDelete'];
         }
     }
     $theJoinTable->addUnnamedForeignKeyConstraint($foreignTableName, $localColumns, $foreignColumns, $fkOptions);
 }
 private function getUniqueAndRequiredAssociations(ClassMetadata $meta, $entity)
 {
     $associations = array();
     foreach ($meta->getAssociationNames() as $associationName) {
         $mapping = $meta->getAssociationMapping($associationName);
         if (!empty($mapping['id']) && $meta->usesIdGenerator()) {
             // autogenerated id
             continue;
         }
         if (!($mapping['type'] & ClassMetadata::TO_ONE)) {
             // is not to one relation
             continue;
         }
         if (empty($mapping['isOwningSide'])) {
             // is not owning side
             continue;
         }
         foreach ($mapping['joinColumns'] as $joinColumn) {
             if (!empty($joinColumn['nullable']) && empty($joinColumn['unique'])) {
                 // is nullable and is not unique
                 continue;
             }
             $targetColumn = $joinColumn['referencedColumnName'];
             $targetClass = $this->em->getClassMetadata($mapping['targetEntity']);
             $newVal = $meta->getFieldValue($entity, $associationName);
             if ($newVal !== NULL) {
                 $newValId = $this->uow->getEntityIdentifier($newVal);
             }
             switch (TRUE) {
                 case $newVal === NULL:
                     $value = NULL;
                     break;
                 case $targetClass->containsForeignIdentifier:
                     $value = $newValId[$targetClass->getFieldForColumn($targetColumn)];
                     break;
                 default:
                     $value = $newValId[$targetClass->fieldNames[$targetColumn]];
                     break;
             }
             $sourceColumn = $joinColumn['name'];
             $quotedColumn = $this->quotes->getJoinColumnName($joinColumn, $meta, $this->platform);
             $associations[$sourceColumn]['value'] = $value;
             $associations[$sourceColumn]['quotedColumn'] = $quotedColumn;
             $associations[$sourceColumn]['type'] = $targetClass->getTypeOfColumn($targetColumn);
         }
     }
     return $associations;
 }
Ejemplo n.º 3
0
 /**
  * Walks down a JoinAssociationDeclaration AST node, thereby generating the appropriate SQL.
  *
  * @param AST\JoinAssociationDeclaration $joinAssociationDeclaration
  * @param int $joinType
  *
  * @return string
  *
  * @throws QueryException
  */
 public function walkJoinAssociationDeclaration($joinAssociationDeclaration, $joinType = AST\Join::JOIN_TYPE_INNER)
 {
     $sql = '';
     $associationPathExpression = $joinAssociationDeclaration->joinAssociationPathExpression;
     $joinedDqlAlias = $joinAssociationDeclaration->aliasIdentificationVariable;
     $indexBy = $joinAssociationDeclaration->indexBy;
     $relation = $this->queryComponents[$joinedDqlAlias]['relation'];
     $targetClass = $this->em->getClassMetadata($relation['targetEntity']);
     $sourceClass = $this->em->getClassMetadata($relation['sourceEntity']);
     $targetTableName = $targetClass->getQuotedTableName($this->platform);
     $targetTableAlias = $this->getSQLTableAlias($targetClass->getTableName(), $joinedDqlAlias);
     $sourceTableAlias = $this->getSQLTableAlias($sourceClass->getTableName(), $associationPathExpression->identificationVariable);
     // Ensure we got the owning side, since it has all mapping info
     $assoc = !$relation['isOwningSide'] ? $targetClass->associationMappings[$relation['mappedBy']] : $relation;
     if ($this->query->getHint(Query::HINT_INTERNAL_ITERATION) == true && (!$this->query->getHint(self::HINT_DISTINCT) || isset($this->selectedClasses[$joinedDqlAlias]))) {
         if ($relation['type'] == ClassMetadata::ONE_TO_MANY || $relation['type'] == ClassMetadata::MANY_TO_MANY) {
             throw QueryException::iterateWithFetchJoinNotAllowed($assoc);
         }
     }
     // This condition is not checking ClassMetadata::MANY_TO_ONE, because by definition it cannot
     // be the owning side and previously we ensured that $assoc is always the owning side of the associations.
     // The owning side is necessary at this point because only it contains the JoinColumn information.
     switch (true) {
         case $assoc['type'] & ClassMetadata::TO_ONE:
             $conditions = array();
             foreach ($assoc['joinColumns'] as $joinColumn) {
                 $quotedSourceColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform);
                 $quotedTargetColumn = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $targetClass, $this->platform);
                 if ($relation['isOwningSide']) {
                     $conditions[] = $sourceTableAlias . '.' . $quotedSourceColumn . ' = ' . $targetTableAlias . '.' . $quotedTargetColumn;
                     continue;
                 }
                 $conditions[] = $sourceTableAlias . '.' . $quotedTargetColumn . ' = ' . $targetTableAlias . '.' . $quotedSourceColumn;
             }
             // Apply remaining inheritance restrictions
             $discrSql = $this->_generateDiscriminatorColumnConditionSQL(array($joinedDqlAlias));
             if ($discrSql) {
                 $conditions[] = $discrSql;
             }
             // Apply the filters
             $filterExpr = $this->generateFilterConditionSQL($targetClass, $targetTableAlias);
             if ($filterExpr) {
                 $conditions[] = $filterExpr;
             }
             $sql .= $targetTableName . ' ' . $targetTableAlias . ' ON ' . implode(' AND ', $conditions);
             break;
         case $assoc['type'] == ClassMetadata::MANY_TO_MANY:
             // Join relation table
             $joinTable = $assoc['joinTable'];
             $joinTableAlias = $this->getSQLTableAlias($joinTable['name'], $joinedDqlAlias);
             $joinTableName = $sourceClass->getQuotedJoinTableName($assoc, $this->platform);
             $conditions = array();
             $relationColumns = $relation['isOwningSide'] ? $assoc['joinTable']['joinColumns'] : $assoc['joinTable']['inverseJoinColumns'];
             foreach ($relationColumns as $joinColumn) {
                 $quotedSourceColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform);
                 $quotedTargetColumn = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $targetClass, $this->platform);
                 $conditions[] = $sourceTableAlias . '.' . $quotedTargetColumn . ' = ' . $joinTableAlias . '.' . $quotedSourceColumn;
             }
             $sql .= $joinTableName . ' ' . $joinTableAlias . ' ON ' . implode(' AND ', $conditions);
             // Join target table
             $sql .= $joinType == AST\Join::JOIN_TYPE_LEFT || $joinType == AST\Join::JOIN_TYPE_LEFTOUTER ? ' LEFT JOIN ' : ' INNER JOIN ';
             $conditions = array();
             $relationColumns = $relation['isOwningSide'] ? $assoc['joinTable']['inverseJoinColumns'] : $assoc['joinTable']['joinColumns'];
             foreach ($relationColumns as $joinColumn) {
                 $quotedSourceColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform);
                 $quotedTargetColumn = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $targetClass, $this->platform);
                 $conditions[] = $targetTableAlias . '.' . $quotedTargetColumn . ' = ' . $joinTableAlias . '.' . $quotedSourceColumn;
             }
             // Apply remaining inheritance restrictions
             $discrSql = $this->_generateDiscriminatorColumnConditionSQL(array($joinedDqlAlias));
             if ($discrSql) {
                 $conditions[] = $discrSql;
             }
             // Apply the filters
             $filterExpr = $this->generateFilterConditionSQL($targetClass, $targetTableAlias);
             if ($filterExpr) {
                 $conditions[] = $filterExpr;
             }
             $sql .= $targetTableName . ' ' . $targetTableAlias . ' ON ' . implode(' AND ', $conditions);
             break;
     }
     // FIXME: these should either be nested or all forced to be left joins (DDC-XXX)
     if ($targetClass->isInheritanceTypeJoined()) {
         $sql .= $this->_generateClassTableInheritanceJoins($targetClass, $joinedDqlAlias);
     }
     // Apply the indexes
     if ($indexBy) {
         // For Many-To-One or One-To-One associations this obviously makes no sense, but is ignored silently.
         $this->rsm->addIndexBy($indexBy->simpleStateFieldPathExpression->identificationVariable, $indexBy->simpleStateFieldPathExpression->field);
     } else {
         if (isset($relation['indexBy'])) {
             $this->rsm->addIndexBy($joinedDqlAlias, $relation['indexBy']);
         }
     }
     return $sql;
 }
Ejemplo n.º 4
0
    /**
     * Builds the left-hand-side of a where condition statement.
     *
     * @param string     $field
     * @param array|null $assoc
     *
     * @return string
     *
     * @throws \Doctrine\ORM\ORMException
     */
    protected function getSelectConditionStatementColumnSQL($field, $assoc = null)
    {
        if (isset($this->class->columnNames[$field])) {
            $className = (isset($this->class->fieldMappings[$field]['inherited']))
                ? $this->class->fieldMappings[$field]['inherited']
                : $this->class->name;

            return $this->getSQLTableAlias($className) . '.' . $this->quoteStrategy->getColumnName($field, $this->class, $this->platform);
        }

        if (isset($this->class->associationMappings[$field])) {

            if ( ! $this->class->associationMappings[$field]['isOwningSide']) {
                throw ORMException::invalidFindByInverseAssociation($this->class->name, $field);
            }

            $joinColumn = $this->class->associationMappings[$field]['joinColumns'][0];
            $className  = (isset($this->class->associationMappings[$field]['inherited']))
                ? $this->class->associationMappings[$field]['inherited']
                : $this->class->name;

            return $this->getSQLTableAlias($className) . '.' . $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform);
        }

        if ($assoc !== null && strpos($field, " ") === false && strpos($field, "(") === false) {
            // very careless developers could potentially open up this normally hidden api for userland attacks,
            // therefore checking for spaces and function calls which are not allowed.

            // found a join column condition, not really a "field"
            return $field;
        }

        throw ORMException::unrecognizedField($field);
    }
 /**
  * Builds the left-hand-side of a where condition statement.
  *
  * @param string     $field
  * @param array|null $assoc
  *
  * @return string[]
  *
  * @throws \Doctrine\ORM\ORMException
  */
 private function getSelectConditionStatementColumnSQL($field, $assoc = null)
 {
     if (isset($this->class->columnNames[$field])) {
         $className = isset($this->class->fieldMappings[$field]['inherited']) ? $this->class->fieldMappings[$field]['inherited'] : $this->class->name;
         return array($this->getSQLTableAlias($className) . '.' . $this->quoteStrategy->getColumnName($field, $this->class, $this->platform));
     }
     if (isset($this->class->associationMappings[$field])) {
         $association = $this->class->associationMappings[$field];
         // Many-To-Many requires join table check for joinColumn
         $columns = array();
         $class = $this->class;
         if ($association['type'] === ClassMetadata::MANY_TO_MANY) {
             if (!$association['isOwningSide']) {
                 $association = $assoc;
             }
             $joinTableName = $this->quoteStrategy->getJoinTableName($association, $class, $this->platform);
             $joinColumns = $assoc['isOwningSide'] ? $association['joinTable']['joinColumns'] : $association['joinTable']['inverseJoinColumns'];
             foreach ($joinColumns as $joinColumn) {
                 $columns[] = $joinTableName . '.' . $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform);
             }
         } else {
             if (!$association['isOwningSide']) {
                 throw ORMException::invalidFindByInverseAssociation($this->class->name, $field);
             }
             $className = isset($association['inherited']) ? $association['inherited'] : $this->class->name;
             foreach ($association['joinColumns'] as $joinColumn) {
                 $columns[] = $this->getSQLTableAlias($className) . '.' . $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform);
             }
         }
         return $columns;
     }
     if ($assoc !== null && strpos($field, " ") === false && strpos($field, "(") === false) {
         // very careless developers could potentially open up this normally hidden api for userland attacks,
         // therefore checking for spaces and function calls which are not allowed.
         // found a join column condition, not really a "field"
         return array($field);
     }
     throw ORMException::unrecognizedField($field);
 }
Ejemplo n.º 6
0
 /**
  * Gathers columns and fk constraints that are required for one part of relationship.
  *
  * @param array         $joinColumns
  * @param Table         $theJoinTable
  * @param ClassMetadata $class
  * @param array         $mapping
  * @param array         $primaryKeyColumns
  * @param array         $addedFks
  * @param array         $blacklistedFks
  *
  * @return void
  *
  * @throws \Doctrine\ORM\ORMException
  */
 private function gatherRelationJoinColumns($joinColumns, $theJoinTable, $class, $mapping, &$primaryKeyColumns, &$addedFks, &$blacklistedFks)
 {
     $localColumns = array();
     $foreignColumns = array();
     $fkOptions = array();
     $foreignTableName = $this->quoteStrategy->getTableName($class, $this->platform);
     $uniqueConstraints = array();
     foreach ($joinColumns as $joinColumn) {
         list($definingClass, $referencedFieldName) = $this->getDefiningClass($class, $joinColumn['referencedColumnName']);
         if (!$definingClass) {
             throw new \Doctrine\ORM\ORMException("Column name `" . $joinColumn['referencedColumnName'] . "` referenced for relation from " . $mapping['sourceEntity'] . " towards " . $mapping['targetEntity'] . " does not exist.");
         }
         $quotedColumnName = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform);
         $quotedRefColumnName = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $class, $this->platform);
         $primaryKeyColumns[] = $quotedColumnName;
         $localColumns[] = $quotedColumnName;
         $foreignColumns[] = $quotedRefColumnName;
         if (!$theJoinTable->hasColumn($quotedColumnName)) {
             // Only add the column to the table if it does not exist already.
             // It might exist already if the foreign key is mapped into a regular
             // property as well.
             $fieldMapping = $definingClass->getFieldMapping($referencedFieldName);
             $columnDef = null;
             if (isset($joinColumn['columnDefinition'])) {
                 $columnDef = $joinColumn['columnDefinition'];
             } elseif (isset($fieldMapping['columnDefinition'])) {
                 $columnDef = $fieldMapping['columnDefinition'];
             }
             $columnOptions = array('notnull' => false, 'columnDefinition' => $columnDef);
             if (isset($joinColumn['nullable'])) {
                 $columnOptions['notnull'] = !$joinColumn['nullable'];
             }
             if (isset($fieldMapping['options'])) {
                 $columnOptions['options'] = $fieldMapping['options'];
             }
             if ($fieldMapping['type'] == "string" && isset($fieldMapping['length'])) {
                 $columnOptions['length'] = $fieldMapping['length'];
             } elseif ($fieldMapping['type'] == "decimal") {
                 $columnOptions['scale'] = $fieldMapping['scale'];
                 $columnOptions['precision'] = $fieldMapping['precision'];
             }
             $theJoinTable->addColumn($quotedColumnName, $fieldMapping['type'], $columnOptions);
         }
         if (isset($joinColumn['unique']) && $joinColumn['unique'] == true) {
             $uniqueConstraints[] = array('columns' => array($quotedColumnName));
         }
         if (isset($joinColumn['onDelete'])) {
             $fkOptions['onDelete'] = $joinColumn['onDelete'];
         }
     }
     // Prefer unique constraints over implicit simple indexes created for foreign keys.
     // Also avoids index duplication.
     foreach ($uniqueConstraints as $indexName => $unique) {
         $theJoinTable->addUniqueIndex($unique['columns'], is_numeric($indexName) ? null : $indexName);
     }
     $compositeName = $theJoinTable->getName() . '.' . implode('', $localColumns);
     if (isset($addedFks[$compositeName]) && ($foreignTableName != $addedFks[$compositeName]['foreignTableName'] || 0 < count(array_diff($foreignColumns, $addedFks[$compositeName]['foreignColumns'])))) {
         foreach ($theJoinTable->getForeignKeys() as $fkName => $key) {
             if (0 === count(array_diff($key->getLocalColumns(), $localColumns)) && ($key->getForeignTableName() != $foreignTableName || 0 < count(array_diff($key->getForeignColumns(), $foreignColumns)))) {
                 $theJoinTable->removeForeignKey($fkName);
                 break;
             }
         }
         $blacklistedFks[$compositeName] = true;
     } elseif (!isset($blacklistedFks[$compositeName])) {
         $addedFks[$compositeName] = array('foreignTableName' => $foreignTableName, 'foreignColumns' => $foreignColumns);
         $theJoinTable->addUnnamedForeignKeyConstraint($foreignTableName, $localColumns, $foreignColumns, $fkOptions);
     }
 }
Ejemplo n.º 7
0
 /**
  * Gets the list of columns to put in the INSERT SQL statement.
  *
  * Subclasses should override this method to alter or change the list of
  * columns placed in the INSERT statements used by the persister.
  *
  * @return array The list of columns.
  */
 protected function _getInsertColumnList()
 {
     $columns = array();
     foreach ($this->_class->reflFields as $name => $field) {
         if ($this->_class->isVersioned && $this->_class->versionField == $name) {
             continue;
         }
         if (isset($this->_class->associationMappings[$name])) {
             $assoc = $this->_class->associationMappings[$name];
             if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
                 foreach ($assoc['joinColumns'] as $joinColumn) {
                     $columns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->_class, $this->_platform);
                 }
             }
         } else {
             if ($this->_class->generatorType != ClassMetadata::GENERATOR_TYPE_IDENTITY || $this->_class->identifier[0] != $name) {
                 $columns[] = $this->quoteStrategy->getColumnName($name, $this->_class, $this->_platform);
                 $this->_columnTypes[$name] = $this->_class->fieldMappings[$name]['type'];
             }
         }
     }
     return $columns;
 }
 /**
  * @param DoctrineSqlFilter $sqlFilter
  * @param QuoteStrategy $quoteStrategy
  * @param ClassMetadata $targetEntity
  * @param string $targetTableAlias
  * @param string $targetEntityPropertyName
  * @return string
  * @throws InvalidQueryRewritingConstraintException
  * @throws \Exception
  */
 protected function getSqlForManyToOneAndOneToOneRelationsWithPropertyPath(DoctrineSqlFilter $sqlFilter, QuoteStrategy $quoteStrategy, ClassMetadata $targetEntity, $targetTableAlias, $targetEntityPropertyName)
 {
     $subselectQuery = $this->getSubselectQuery($targetEntity, $targetEntityPropertyName);
     $associationMapping = $targetEntity->getAssociationMapping($targetEntityPropertyName);
     $subselectConstraintQueries = array();
     foreach ($associationMapping['joinColumns'] as $joinColumn) {
         $rootAliases = $subselectQuery->getQueryBuilder()->getRootAliases();
         $subselectQuery->getQueryBuilder()->select($rootAliases[0] . '.' . $targetEntity->getFieldForColumn($joinColumn['referencedColumnName']));
         $subselectSql = $subselectQuery->getSql();
         foreach ($subselectQuery->getParameters() as $parameter) {
             $parameterValue = $parameter->getValue();
             if (is_object($parameterValue)) {
                 $parameterValue = $this->persistenceManager->getIdentifierByObject($parameter->getValue());
             }
             $subselectSql = preg_replace('/\\?/', $this->entityManager->getConnection()->quote($parameterValue, $parameter->getType()), $subselectSql, 1);
         }
         $quotedColumnName = $quoteStrategy->getJoinColumnName($joinColumn, $targetEntity, $this->entityManager->getConnection()->getDatabasePlatform());
         $subselectIdentifier = 'subselect' . md5($subselectSql);
         $subselectConstraintQueries[] = $targetTableAlias . '.' . $quotedColumnName . ' IN (SELECT ' . $subselectIdentifier . '.' . $joinColumn['referencedColumnName'] . '0 FROM (' . $subselectSql . ') AS ' . $subselectIdentifier . ' ) ';
     }
     return ' (' . implode(' ) AND ( ', $subselectConstraintQueries) . ') ';
 }
 /**
  * @param array    $assoc
  * @param object   $sourceEntity
  * @param int|null $offset
  * @param int|null $limit
  *
  * @return \Doctrine\DBAL\Driver\Statement
  *
  * @throws \Doctrine\ORM\Mapping\MappingException
  */
 private function getManyToManyStatement(array $assoc, $sourceEntity, $offset = null, $limit = null)
 {
     $this->switchPersisterContext($offset, $limit);
     $sourceClass = $this->em->getClassMetadata($assoc['sourceEntity']);
     $class = $sourceClass;
     $association = $assoc;
     $criteria = array();
     $parameters = array();
     if (!$assoc['isOwningSide']) {
         $class = $this->em->getClassMetadata($assoc['targetEntity']);
         $association = $class->associationMappings[$assoc['mappedBy']];
     }
     $joinColumns = $assoc['isOwningSide'] ? $association['joinTable']['joinColumns'] : $association['joinTable']['inverseJoinColumns'];
     $quotedJoinTable = $this->quoteStrategy->getJoinTableName($association, $class, $this->platform);
     foreach ($joinColumns as $joinColumn) {
         $sourceKeyColumn = $joinColumn['referencedColumnName'];
         $quotedKeyColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform);
         switch (true) {
             case $sourceClass->containsForeignIdentifier:
                 $field = $sourceClass->getFieldForColumn($sourceKeyColumn);
                 $value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
                 if (isset($sourceClass->associationMappings[$field])) {
                     $value = $this->em->getUnitOfWork()->getEntityIdentifier($value);
                     $value = $value[$this->em->getClassMetadata($sourceClass->associationMappings[$field]['targetEntity'])->identifier[0]];
                 }
                 break;
             case isset($sourceClass->fieldNames[$sourceKeyColumn]):
                 $field = $sourceClass->fieldNames[$sourceKeyColumn];
                 $value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
                 break;
             default:
                 throw MappingException::joinColumnMustPointToMappedField($sourceClass->name, $sourceKeyColumn);
         }
         $criteria[$quotedJoinTable . '.' . $quotedKeyColumn] = $value;
         $parameters[] = array('value' => $value, 'field' => $field, 'class' => $sourceClass);
     }
     $sql = $this->getSelectSQL($criteria, $assoc, null, $limit, $offset);
     list($params, $types) = $this->expandToManyParameters($parameters);
     return $this->conn->executeQuery($sql, $params, $types);
 }